diff options
Diffstat (limited to 'actionpack/lib/action_dispatch/http')
-rw-r--r-- | actionpack/lib/action_dispatch/http/mime_type.rb | 3 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/mime_types.rb | 2 | ||||
-rwxr-xr-x | actionpack/lib/action_dispatch/http/request.rb | 77 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/response.rb | 78 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/status_codes.rb | 6 |
5 files changed, 113 insertions, 53 deletions
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 02ad7f7d94..25156a4c75 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -1,8 +1,9 @@ require 'set' +require 'active_support/core_ext/class/attribute_accessors' module Mime SET = [] - EXTENSION_LOOKUP = Hash.new { |h, k| h[k] = Type.new(k) unless k.blank? } + EXTENSION_LOOKUP = {} LOOKUP = Hash.new { |h, k| h[k] = Type.new(k) unless k.blank? } def self.[](type) diff --git a/actionpack/lib/action_dispatch/http/mime_types.rb b/actionpack/lib/action_dispatch/http/mime_types.rb index 2d7fba1173..7c28cac419 100644 --- a/actionpack/lib/action_dispatch/http/mime_types.rb +++ b/actionpack/lib/action_dispatch/http/mime_types.rb @@ -1,9 +1,9 @@ # Build list of Mime types for HTTP responses # http://www.iana.org/assignments/media-types/ +Mime::Type.register "text/html", :html, %w( application/xhtml+xml ), %w( xhtml ) Mime::Type.register "*/*", :all Mime::Type.register "text/plain", :text, [], %w(txt) -Mime::Type.register "text/html", :html, %w( application/xhtml+xml ), %w( xhtml ) Mime::Type.register "text/javascript", :js, %w( application/javascript application/x-javascript ) Mime::Type.register "text/css", :css Mime::Type.register "text/calendar", :ics diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 523ab32b35..140feb9a68 100755 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -3,6 +3,9 @@ require 'stringio' require 'strscan' require 'active_support/memoizable' +require 'active_support/core_ext/array/wrap' +require 'active_support/core_ext/hash/indifferent_access' +require 'active_support/core_ext/object/tap' module ActionDispatch class Request < Rack::Request @@ -31,7 +34,7 @@ module ActionDispatch # <tt>:get</tt>. If the request \method is not listed in the HTTP_METHODS # constant above, an UnknownHttpMethod exception is raised. def request_method - @request_method ||= HTTP_METHOD_LOOKUP[super] || raise(ActionController::UnknownHttpMethod, "#{super}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}") + HTTP_METHOD_LOOKUP[super] || raise(ActionController::UnknownHttpMethod, "#{super}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}") end # Returns the HTTP request \method used for action processing as a @@ -85,7 +88,7 @@ module ActionDispatch # For backward compatibility, the post \format is extracted from the # X-Post-Data-Format HTTP header if present. def content_type - @content_type ||= begin + @env["action_dispatch.request.content_type"] ||= begin if @env['CONTENT_TYPE'] =~ /^([^,\;]*)/ Mime::Type.lookup($1.strip.downcase) else @@ -93,10 +96,14 @@ module ActionDispatch end end end - + + def media_type + content_type.to_s + end + # Returns the accepted MIME type for the request. def accepts - @accepts ||= begin + @env["action_dispatch.request.accepts"] ||= begin header = @env['HTTP_ACCEPT'].to_s.strip fallback = xhr? ? Mime::JS : Mime::HTML @@ -156,7 +163,7 @@ module ActionDispatch # GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first depending on the value of <tt>ActionController::Base.use_accept_header</tt> def format(view_path = []) - @format ||= + @env["action_dispatch.request.format"] ||= if parameters[:format] Mime[parameters[:format]] elsif ActionController::Base.use_accept_header && !(accepts == ONLY_ALL) @@ -167,12 +174,23 @@ module ActionDispatch end def formats - @formats = - if ActionController::Base.use_accept_header - Array(Mime[parameters[:format]] || accepts) + if ActionController::Base.use_accept_header + if param = parameters[:format] + Array.wrap(Mime[param]) else - [format] + accepts.dup + end.tap do |ret| + if defined?(ActionController::Http) + if ret == ONLY_ALL + ret.replace Mime::SET + elsif all = ret.index(Mime::ALL) + ret.delete_at(all) && ret.insert(all, *Mime::SET) + end + end end + else + [format] + Mime::SET + end end # Sets the \format by string extension, which can be used to force custom formats @@ -188,7 +206,7 @@ module ActionDispatch # end def format=(extension) parameters[:format] = extension.to_s - @format = Mime::Type.lookup_by_extension(parameters[:format]) + @env["action_dispatch.request.format"] = Mime::Type.lookup_by_extension(parameters[:format]) end # Returns a symbolized version of the <tt>:format</tt> parameter of the request. @@ -324,6 +342,10 @@ EOM port == standard_port ? '' : ":#{port}" end + def server_port + @env['SERVER_PORT'].to_i + end + # Returns the \domain part of a \host, such as "rubyonrails.org" in "www.rubyonrails.org". You can specify # a different <tt>tld_length</tt>, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk". def domain(tld_length = 1) @@ -344,7 +366,7 @@ EOM # Returns the query string, accounting for server idiosyncrasies. def query_string - @env['QUERY_STRING'].present? ? @env['QUERY_STRING'] : (@env['REQUEST_URI'].split('?', 2)[1] || '') + @env['QUERY_STRING'].present? ? @env['QUERY_STRING'] : (@env['REQUEST_URI'].to_s.split('?', 2)[1] || '') end # Returns the request URI, accounting for server idiosyncrasies. @@ -392,18 +414,19 @@ EOM # Returns both GET and POST \parameters in a single hash. def parameters - @parameters ||= request_parameters.merge(query_parameters).update(path_parameters).with_indifferent_access + @env["action_dispatch.request.parameters"] ||= request_parameters.merge(query_parameters).update(path_parameters).with_indifferent_access end alias_method :params, :parameters def path_parameters=(parameters) #:nodoc: - @env["rack.routing_args"] = parameters - @symbolized_path_parameters = @parameters = nil + @env.delete("action_dispatch.request.symbolized_path_parameters") + @env.delete("action_dispatch.request.parameters") + @env["action_dispatch.request.path_parameters"] = parameters end # The same as <tt>path_parameters</tt> with explicitly symbolized keys. def symbolized_path_parameters - @symbolized_path_parameters ||= path_parameters.symbolize_keys + @env["action_dispatch.request.symbolized_path_parameters"] ||= path_parameters.symbolize_keys end # Returns a hash with the \parameters used to form the \path of the request. @@ -413,7 +436,7 @@ EOM # # See <tt>symbolized_path_parameters</tt> for symbolized keys. def path_parameters - @env["rack.routing_args"] ||= {} + @env["action_dispatch.request.path_parameters"] ||= {} end # The request body is an IO input stream. If the RAW_POST_DATA environment @@ -433,13 +456,13 @@ EOM # Override Rack's GET method to support indifferent access def GET - @env["action_controller.request.query_parameters"] ||= normalize_parameters(super) + @env["action_dispatch.request.query_parameters"] ||= normalize_parameters(super) end alias_method :query_parameters, :GET # Override Rack's POST method to support indifferent access def POST - @env["action_controller.request.request_parameters"] ||= normalize_parameters(super) + @env["action_dispatch.request.request_parameters"] ||= normalize_parameters(super) end alias_method :request_parameters, :POST @@ -447,29 +470,21 @@ EOM @env['rack.input'] end - def session - @env['rack.session'] ||= {} + def reset_session + self.session_options.delete(:id) + self.session = {} end def session=(session) #:nodoc: @env['rack.session'] = session end - def reset_session - @env['rack.session.options'].delete(:id) - @env['rack.session'] = {} - end - - def session_options - @env['rack.session.options'] ||= {} - end - def session_options=(options) @env['rack.session.options'] = options end - def server_port - @env['SERVER_PORT'].to_i + def flash + session['flash'] || {} end private diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index ecf40b8103..b9db7a4508 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -1,4 +1,5 @@ require 'digest/md5' +require 'active_support/core_ext/module/delegation' module ActionDispatch # :nodoc: # Represents an HTTP response generated by a controller action. One can use @@ -34,17 +35,31 @@ module ActionDispatch # :nodoc: DEFAULT_HEADERS = { "Cache-Control" => "no-cache" } attr_accessor :request - attr_accessor :session, :assigns, :template, :layout - attr_accessor :redirected_to, :redirected_to_method_params + attr_writer :header + alias_method :headers=, :header= delegate :default_charset, :to => 'ActionController::Base' def initialize super @header = Rack::Utils::HeaderHash.new(DEFAULT_HEADERS) - @session, @assigns = [], [] end + # The response code of the request + def response_code + status.to_s[0,3].to_i rescue 0 + end + + # Returns a String to ensure compatibility with Net::HTTPResponse + def code + status.to_s.split(' ')[0] + end + + def message + status.to_s.split(' ',2)[1] || StatusCodes::STATUS_CODES[response_code] + end + alias_method :status_message, :message + def body str = '' each { |part| str << part.to_s } @@ -53,7 +68,7 @@ module ActionDispatch # :nodoc: def body=(body) @body = - if body.is_a?(String) + if body.respond_to?(:to_str) [body] else body @@ -64,9 +79,14 @@ module ActionDispatch # :nodoc: @body end - def location; headers['Location'] end - def location=(url) headers['Location'] = url end + def location + headers['Location'] + end + alias_method :redirect_url, :location + def location=(url) + headers['Location'] = url + end # Sets the HTTP response's content MIME type. For example, in the controller # you could write this: @@ -137,19 +157,20 @@ module ActionDispatch # :nodoc: end end - def redirect(url, status) - self.status = status - self.location = url.gsub(/[\r\n]/, '') - self.body = "<html><body>You are being <a href=\"#{CGI.escapeHTML(url)}\">redirected</a>.</body></html>" - end - def sending_file? headers["Content-Transfer-Encoding"] == "binary" end def assign_default_content_type_and_charset! - self.content_type ||= Mime::HTML - self.charset ||= default_charset unless sending_file? + if type = headers['Content-Type'] || headers['type'] + unless type =~ /charset=/ || sending_file? + headers['Content-Type'] = "#{type}; charset=#{default_charset}" + end + else + type = Mime::HTML.to_s + type += "; charset=#{default_charset}" unless sending_file? + headers['Content-Type'] = type + end end def prepare! @@ -165,10 +186,8 @@ module ActionDispatch # :nodoc: if @body.respond_to?(:call) @writer = lambda { |x| callback.call(x) } @body.call(self, self) - elsif @body.is_a?(String) - callback.call(@body) else - @body.each(&callback) + @body.each { |part| callback.call(part.to_s) } end @writer = callback @@ -192,6 +211,23 @@ module ActionDispatch # :nodoc: super(key, value) end + # Returns the response cookies, converted to a Hash of (name => value) pairs + # + # assert_equal 'AuthorOfNewPage', r.cookies['author'] + def cookies + cookies = {} + if header = headers['Set-Cookie'] + header = header.split("\n") if header.respond_to?(:to_str) + header.each do |cookie| + if pair = cookie.split(';').first + key, value = pair.split("=").map { |v| Rack::Utils.unescape(v) } + cookies[key] = value + end + end + end + cookies + end + private def handle_conditional_get! if etag? || last_modified? @@ -245,7 +281,13 @@ module ActionDispatch # :nodoc: end def convert_cookies! - headers['Set-Cookie'] = Array(headers['Set-Cookie']).compact + headers['Set-Cookie'] = + if header = headers['Set-Cookie'] + header = header.split("\n") if header.respond_to?(:to_str) + header.compact + else + [] + end end end end diff --git a/actionpack/lib/action_dispatch/http/status_codes.rb b/actionpack/lib/action_dispatch/http/status_codes.rb index 830de2a6db..5bac842ec1 100644 --- a/actionpack/lib/action_dispatch/http/status_codes.rb +++ b/actionpack/lib/action_dispatch/http/status_codes.rb @@ -1,3 +1,5 @@ +require 'active_support/inflector' + module ActionDispatch module StatusCodes #:nodoc: STATUS_CODES = Rack::Utils::HTTP_STATUS_CODES.merge({ @@ -16,7 +18,7 @@ module ActionDispatch # :created or :not_implemented) into its corresponding HTTP status # code (like 200 or 501). SYMBOL_TO_STATUS_CODE = STATUS_CODES.inject({}) { |hash, (code, message)| - hash[message.gsub(/ /, "").underscore.to_sym] = code + hash[ActiveSupport::Inflector.underscore(message.gsub(/ /, "")).to_sym] = code hash }.freeze @@ -37,4 +39,4 @@ module ActionDispatch end end end -end
\ No newline at end of file +end |