diff options
Diffstat (limited to 'actionpack/lib/action_dispatch')
7 files changed, 110 insertions, 102 deletions
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 8e03a7879f..1f4f3ac0da 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -32,24 +32,35 @@ module ActionDispatch # :nodoc: # puts @response.body # end # end - class Response < Rack::Response - attr_accessor :request, :blank + class Response + attr_accessor :request, :header, :status + attr_writer :sending_file - attr_writer :header, :sending_file alias_method :headers=, :header= + alias_method :headers, :header + + delegate :[], :[]=, :to => :@header + delegate :each, :to => :@body + + # Sets the HTTP response's content MIME type. For example, in the controller + # you could write this: + # + # response.content_type = "text/plain" + # + # If a character set has been defined for this response (see charset=) then + # the character set information will also be included in the content type + # information. + attr_accessor :charset, :content_type + + CONTENT_TYPE = "Content-Type" + + cattr_accessor(:default_charset) { "utf-8" } module Setup def initialize(status = 200, header = {}, body = []) - @writer = lambda { |x| @body << x } - @block = nil - @length = 0 + self.body, self.header, self.status = body, header, status - @header = header - self.body, self.status = body, status - - @cookie = [] @sending_file = false - @blank = false if content_type = self["Content-Type"] @@ -62,6 +73,7 @@ module ActionDispatch # :nodoc: end end + include Rack::Response::Helpers include Setup include ActionDispatch::Http::Cache::Response @@ -106,13 +118,29 @@ module ActionDispatch # :nodoc: def body=(body) @blank = true if body == EMPTY - @body = body.respond_to?(:to_str) ? [body] : body + + # Explicitly check for strings. This is *wrong* theoretically + # but if we don't check this, the performance on string bodies + # is bad on Ruby 1.8 (because strings responds to each then). + @body = if body.respond_to?(:to_str) || !body.respond_to?(:each) + [body] + else + body + end end def body_parts @body end + def set_cookie(key, value) + ::Rack::Utils.set_cookie_header!(header, key, value) + end + + def delete_cookie(key, value={}) + ::Rack::Utils.delete_cookie_header!(header, key, value) + end + def location headers['Location'] end @@ -122,46 +150,21 @@ module ActionDispatch # :nodoc: headers['Location'] = url end - # Sets the HTTP response's content MIME type. For example, in the controller - # you could write this: - # - # response.content_type = "text/plain" - # - # If a character set has been defined for this response (see charset=) then - # the character set information will also be included in the content type - # information. - attr_accessor :charset, :content_type - - CONTENT_TYPE = "Content-Type" - - cattr_accessor(:default_charset) { "utf-8" } - def to_a assign_default_content_type_and_charset! handle_conditional_get! - self["Set-Cookie"] = self["Set-Cookie"].join("\n") if self["Set-Cookie"].respond_to?(:join) - super - end - alias prepare! to_a + @header["Set-Cookie"] = @header["Set-Cookie"].join("\n") if @header["Set-Cookie"].respond_to?(:join) - def each(&callback) - if @body.respond_to?(:call) - @writer = lambda { |x| callback.call(x) } - @body.call(self, self) + if [204, 304].include?(@status) + @header.delete "Content-Type" + [@status, @header, []] else - @body.each { |part| callback.call(part.to_s) } + [@status, @header, self] end - - @writer = callback - @block.call(self) if @block - end - - def write(str) - str = str.to_s - @writer.call str - str end + alias prepare! to_a + alias to_ary to_a # For implicit splat on 1.9.2 # Returns the response cookies, converted to a Hash of (name => value) pairs # @@ -180,18 +183,18 @@ module ActionDispatch # :nodoc: cookies end - private - def assign_default_content_type_and_charset! - return if headers[CONTENT_TYPE].present? + private - @content_type ||= Mime::HTML - @charset ||= self.class.default_charset + def assign_default_content_type_and_charset! + return if headers[CONTENT_TYPE].present? - type = @content_type.to_s.dup - type << "; charset=#{@charset}" unless @sending_file + @content_type ||= Mime::HTML + @charset ||= self.class.default_charset - headers[CONTENT_TYPE] = type - end + type = @content_type.to_s.dup + type << "; charset=#{@charset}" unless @sending_file + headers[CONTENT_TYPE] = type + end end end diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb index 027ff7f8ac..2adbce031b 100644 --- a/actionpack/lib/action_dispatch/middleware/flash.rb +++ b/actionpack/lib/action_dispatch/middleware/flash.rb @@ -4,7 +4,7 @@ module ActionDispatch # read a notice you put there or <tt>flash["notice"] = "hello"</tt> # to put a new one. def flash - @env['action_dispatch.request.flash_hash'] ||= (session["flash"] || Flash::FlashHash.new) + @env[Flash::KEY] ||= (session["flash"] || Flash::FlashHash.new) end end @@ -40,18 +40,16 @@ module ActionDispatch # # See docs on the FlashHash class for more details about the flash. class Flash + KEY = 'action_dispatch.request.flash_hash'.freeze + class FlashNow #:nodoc: + attr_accessor :flash + def initialize(flash) @flash = flash - @closed = false end - attr_reader :closed - alias :closed? :closed - def close!; @closed = true end - def []=(k, v) - raise ClosedError, :flash if closed? @flash[k] = v @flash.discard(k) v @@ -79,11 +77,16 @@ module ActionDispatch @used = Set.new @closed = false @flashes = {} + @now = nil end - attr_reader :closed - alias :closed? :closed - def close!; @closed = true end + def initialize_copy(other) + if other.now_is_loaded? + @now = other.now.dup + @now.flash = self + end + super + end def []=(k, v) #:nodoc: raise ClosedError, :flash if closed? @@ -152,6 +155,10 @@ module ActionDispatch @now ||= FlashNow.new(self) end + attr_reader :closed + alias :closed? :closed + def close!; @closed = true; end + # Keeps either the entire current flash or a specific flash entry available for the next action: # # flash.keep # keeps the entire flash @@ -205,7 +212,12 @@ module ActionDispatch self[:notice] = message end - private + protected + + def now_is_loaded? + !!@now + end + # Used internally by the <tt>keep</tt> and <tt>discard</tt> methods # use() # marks the entire flash as used # use('msg') # marks the "msg" entry as used @@ -231,13 +243,18 @@ module ActionDispatch @app.call(env) ensure session = env['rack.session'] || {} - flash_hash = env['action_dispatch.request.flash_hash'] + flash_hash = env[KEY] if flash_hash - if !flash_hash.empty? || session.key?('flash') - session["flash"] = flash_hash - end - flash_hash.close! + if !flash_hash.empty? || session.key?('flash') + session["flash"] = flash_hash + new_hash = flash_hash.dup + else + new_hash = flash_hash + end + + env[KEY] = new_hash + new_hash.close! end if session.key?('flash') && session['flash'].empty? diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index 64d3a87fd0..1a811ce1b1 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -29,7 +29,9 @@ module ActionDispatch end def generate_sid - ActiveSupport::SecureRandom.hex(16) + sid = ActiveSupport::SecureRandom.hex(16) + sid.encode!('UTF-8') if sid.respond_to?(:encode!) + sid end protected diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index dbe3206808..b1adf3d2d1 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -50,7 +50,7 @@ module ActionDispatch # Only this middleware cares about RoutingError. So, let's just raise # it here. if headers['X-Cascade'] == 'pass' - raise ActionController::RoutingError, "No route matches #{env['PATH_INFO'].inspect}" + raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}" end rescue Exception => exception raise exception if env['action_dispatch.show_exceptions'] == false diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb index c57f694c4d..348f7b86b8 100644 --- a/actionpack/lib/action_dispatch/middleware/static.rb +++ b/actionpack/lib/action_dispatch/middleware/static.rb @@ -2,25 +2,23 @@ require 'rack/utils' module ActionDispatch class FileHandler - def initialize(at, root) - @at, @root = at.chomp('/'), root.chomp('/') - @compiled_at = @at.blank? ? nil : /^#{Regexp.escape(at)}/ + def initialize(root) + @root = root.chomp('/') @compiled_root = /^#{Regexp.escape(root)}/ @file_server = ::Rack::File.new(@root) end def match?(path) path = path.dup - if !@compiled_at || path.sub!(@compiled_at, '') - full_path = path.empty? ? @root : File.join(@root, ::Rack::Utils.unescape(path)) - paths = "#{full_path}#{ext}" - matches = Dir[paths] - match = matches.detect { |m| File.file?(m) } - if match - match.sub!(@compiled_root, '') - match - end + full_path = path.empty? ? @root : File.join(@root, ::Rack::Utils.unescape(path)) + paths = "#{full_path}#{ext}" + + matches = Dir[paths] + match = matches.detect { |m| File.file?(m) } + if match + match.sub!(@compiled_root, '') + match end end @@ -39,9 +37,9 @@ module ActionDispatch class Static FILE_METHODS = %w(GET HEAD).freeze - def initialize(app, roots) + def initialize(app, path) @app = app - @file_handlers = create_file_handlers(roots) + @file_handler = FileHandler.new(path) end def call(env) @@ -49,24 +47,13 @@ module ActionDispatch method = env['REQUEST_METHOD'] if FILE_METHODS.include?(method) - @file_handlers.each do |file_handler| - if match = file_handler.match?(path) - env["PATH_INFO"] = match - return file_handler.call(env) - end + if match = @file_handler.match?(path) + env["PATH_INFO"] = match + return @file_handler.call(env) end end @app.call(env) end - - private - def create_file_handlers(roots) - roots = { '' => roots } unless roots.is_a?(Hash) - - roots.map do |at, root| - FileHandler.new(at, root) if File.exist?(root) - end.compact - end end end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index b28f6c2297..1d09091dc7 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -275,8 +275,7 @@ module ActionDispatch module MountedHelpers end - def mounted_helpers(name = :main_app) - define_mounted_helper(name) if name + def mounted_helpers MountedHelpers end diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb index 8a04cfa886..e209978fb7 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/response.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb @@ -42,7 +42,7 @@ module ActionDispatch elsif type.is_a?(Symbol) && @response.response_code == Rack::Utils::SYMBOL_TO_STATUS_CODE[type] assert_block("") { true } # to count the assertion else - assert_block(build_message(message, "Expected response to be a <?>, but was <?>", type, @response.response_code)) { false } + assert(false, build_message(message, "Expected response to be a <?>, but was <?>", type, @response.response_code)) end end |
