diff options
Diffstat (limited to 'actionpack/lib/action_dispatch/http')
| -rw-r--r-- | actionpack/lib/action_dispatch/http/cache.rb | 14 | ||||
| -rw-r--r-- | actionpack/lib/action_dispatch/http/filter_parameters.rb | 5 | ||||
| -rw-r--r-- | actionpack/lib/action_dispatch/http/headers.rb | 15 | ||||
| -rw-r--r-- | actionpack/lib/action_dispatch/http/mime_negotiation.rb | 2 | ||||
| -rw-r--r-- | actionpack/lib/action_dispatch/http/mime_type.rb | 16 | ||||
| -rw-r--r-- | actionpack/lib/action_dispatch/http/mime_types.rb | 2 | ||||
| -rw-r--r-- | actionpack/lib/action_dispatch/http/parameters.rb | 6 | ||||
| -rw-r--r-- | actionpack/lib/action_dispatch/http/rack_cache.rb | 5 | ||||
| -rw-r--r-- | actionpack/lib/action_dispatch/http/request.rb | 32 | ||||
| -rw-r--r-- | actionpack/lib/action_dispatch/http/response.rb | 11 | ||||
| -rw-r--r-- | actionpack/lib/action_dispatch/http/upload.rb | 18 | ||||
| -rw-r--r-- | actionpack/lib/action_dispatch/http/url.rb | 53 |
12 files changed, 112 insertions, 67 deletions
diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb index bea62b94d2..5ee4c044ea 100644 --- a/actionpack/lib/action_dispatch/http/cache.rb +++ b/actionpack/lib/action_dispatch/http/cache.rb @@ -60,6 +60,20 @@ module ActionDispatch headers[LAST_MODIFIED] = utc_time.httpdate end + def date + if date_header = headers['Date'] + Time.httpdate(date_header) + end + end + + def date? + headers.include?('Date') + end + + def date=(utc_time) + headers['Date'] = utc_time.httpdate + end + def etag=(etag) key = ActiveSupport::Cache.expand_cache_key(etag) @etag = self[ETAG] = %("#{Digest::MD5.hexdigest(key)}") diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb index 8dd1af7f3d..6413929be3 100644 --- a/actionpack/lib/action_dispatch/http/filter_parameters.rb +++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb @@ -10,8 +10,6 @@ module ActionDispatch # value of the params hash and all subhashes is passed to it, the value # or key can be replaced using String#replace or similar method. # - # Examples: - # # env["action_dispatch.parameter_filter"] = [:password] # => replaces the value to all keys matching /password/i with "[FILTERED]" # @@ -22,7 +20,6 @@ module ActionDispatch # v.reverse! if k =~ /secret/i # end # => reverses the value to all keys matching /secret/i - # module FilterParameters extend ActiveSupport::Concern @@ -50,7 +47,7 @@ module ActionDispatch end def env_filter - parameter_filter_for(Array.wrap(@env["action_dispatch.parameter_filter"]) << /RAW_POST_DATA/) + parameter_filter_for(Array(@env["action_dispatch.parameter_filter"]) + [/RAW_POST_DATA/, "rack.request.form_vars"]) end def parameter_filter_for(filters) diff --git a/actionpack/lib/action_dispatch/http/headers.rb b/actionpack/lib/action_dispatch/http/headers.rb index 040b51e040..a3bb25f75a 100644 --- a/actionpack/lib/action_dispatch/http/headers.rb +++ b/actionpack/lib/action_dispatch/http/headers.rb @@ -14,17 +14,18 @@ module ActionDispatch end def [](header_name) - if include?(header_name) - super - else - super(env_name(header_name)) - end + super env_name(header_name) + end + + def fetch(header_name, default=nil, &block) + super env_name(header_name), default, &block end private - # Converts a HTTP header name to an environment variable name. + # Converts a HTTP header name to an environment variable name if it is + # not contained within the headers hash. def env_name(header_name) - @@env_cache[header_name] + include?(header_name) ? header_name : @@env_cache[header_name] end end end diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb index 5c48a60469..e31f3b823d 100644 --- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb +++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/module/attribute_accessors' + module ActionDispatch module Http module MimeNegotiation diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 25affb9f50..0eaae80461 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -38,7 +38,7 @@ module Mime # respond_to do |format| # format.html # format.ics { render :text => post.to_ics, :mime_type => Mime::Type["text/calendar"] } - # format.xml { render :xml => @people.to_xml } + # format.xml { render :xml => @people } # end # end # end @@ -82,6 +82,7 @@ module Mime class << self TRAILING_STAR_REGEXP = /(text|application)\/\*/ + PARAMETER_SEPARATOR_REGEXP = /;\s*\w+="?\w+"?/ def lookup(string) LOOKUP[string] @@ -108,6 +109,7 @@ module Mime def parse(accept_header) if accept_header !~ /,/ + accept_header = accept_header.split(PARAMETER_SEPARATOR_REGEXP).first if accept_header =~ TRAILING_STAR_REGEXP parse_data_with_trailing_star($1) else @@ -117,7 +119,7 @@ module Mime # keep track of creation order to keep the subsequent sort stable list, index = [], 0 accept_header.split(/,/).each do |header| - params, q = header.split(/;\s*q=/) + params, q = header.split(PARAMETER_SEPARATOR_REGEXP) if params.present? params.strip! @@ -177,11 +179,11 @@ module Mime end end - # input: 'text' - # returned value: [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT] + # For an input of <tt>'text'</tt>, returns <tt>[Mime::JSON, Mime::XML, Mime::ICS, + # Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT]</tt>. # - # input: 'application' - # returned value: [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::URL_ENCODED_FORM] + # For an input of <tt>'application'</tt>, returns <tt>[Mime::HTML, Mime::JS, + # Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::URL_ENCODED_FORM]</tt>. def parse_data_with_trailing_star(input) Mime::SET.select { |m| m =~ input } end @@ -190,7 +192,7 @@ module Mime # # Usage: # - # Mime::Type.unregister(:mobile) + # Mime::Type.unregister(:mobile) def unregister(symbol) symbol = symbol.to_s.upcase mime = Mime.const_get(symbol) diff --git a/actionpack/lib/action_dispatch/http/mime_types.rb b/actionpack/lib/action_dispatch/http/mime_types.rb index 3da4f91051..a6b3aee5e7 100644 --- a/actionpack/lib/action_dispatch/http/mime_types.rb +++ b/actionpack/lib/action_dispatch/http/mime_types.rb @@ -9,7 +9,7 @@ Mime::Type.register "text/calendar", :ics Mime::Type.register "text/csv", :csv Mime::Type.register "image/png", :png, [], %w(png) -Mime::Type.register "image/jpeg", :jpeg, [], %w(jpg jpeg jpe) +Mime::Type.register "image/jpeg", :jpeg, [], %w(jpg jpeg jpe pjpeg) Mime::Type.register "image/gif", :gif, [], %w(gif) Mime::Type.register "image/bmp", :bmp, [], %w(bmp) Mime::Type.register "image/tiff", :tiff, [], %w(tif tiff) diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb index ef5d207b26..bcfd0b0d00 100644 --- a/actionpack/lib/action_dispatch/http/parameters.rb +++ b/actionpack/lib/action_dispatch/http/parameters.rb @@ -35,14 +35,16 @@ module ActionDispatch @env["action_dispatch.request.path_parameters"] ||= {} end + def reset_parameters #:nodoc: + @env.delete("action_dispatch.request.parameters") + end + private # TODO: Validate that the characters are UTF-8. If they aren't, # you'll get a weird error down the road, but our form handling # should really prevent that from happening def encode_params(params) - return params unless "ruby".encoding_aware? - if params.is_a?(String) return params.force_encoding("UTF-8").encode! elsif !params.is_a?(Hash) diff --git a/actionpack/lib/action_dispatch/http/rack_cache.rb b/actionpack/lib/action_dispatch/http/rack_cache.rb index cc8edee300..003ae4029d 100644 --- a/actionpack/lib/action_dispatch/http/rack_cache.rb +++ b/actionpack/lib/action_dispatch/http/rack_cache.rb @@ -8,8 +8,7 @@ module ActionDispatch new end - # TODO: Finally deal with the RAILS_CACHE global - def initialize(store = RAILS_CACHE) + def initialize(store = Rails.cache) @store = store end @@ -33,7 +32,7 @@ module ActionDispatch new end - def initialize(store = RAILS_CACHE) + def initialize(store = Rails.cache) @store = store end diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 820921252d..aa5ba3e8a5 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -17,7 +17,10 @@ module ActionDispatch include ActionDispatch::Http::Upload include ActionDispatch::Http::URL - LOCALHOST = [/^127\.0\.0\.\d{1,3}$/, "::1", /^0:0:0:0:0:0:0:1(%.*)?$/].freeze + autoload :Session, 'action_dispatch/request/session' + + LOCALHOST = Regexp.union [/^127\.0\.0\.\d{1,3}$/, /^::1$/, /^0:0:0:0:0:0:0:1(%.*)?$/] + ENV_METHODS = %w[ AUTH_TYPE GATEWAY_INTERFACE PATH_TRANSLATED REMOTE_HOST REMOTE_IDENT REMOTE_USER REMOTE_ADDR @@ -97,6 +100,12 @@ module ActionDispatch HTTP_METHOD_LOOKUP[request_method] == :post end + # Is this a PATCH request? + # Equivalent to <tt>request.request_method == :patch</tt>. + def patch? + HTTP_METHOD_LOOKUP[request_method] == :patch + end + # Is this a PUT request? # Equivalent to <tt>request.request_method_symbol == :put</tt>. def put? @@ -189,7 +198,7 @@ module ActionDispatch # variable is already set, wrap it in a StringIO. def body if raw_post = @env['RAW_POST_DATA'] - raw_post.force_encoding(Encoding::BINARY) if raw_post.respond_to?(:force_encoding) + raw_post.force_encoding(Encoding::BINARY) StringIO.new(raw_post) else @env['rack.input'] @@ -213,26 +222,33 @@ module ActionDispatch end def session=(session) #:nodoc: - @env['rack.session'] = session + Session.set @env, session end def session_options=(options) - @env['rack.session.options'] = options + Session::Options.set @env, options end # Override Rack's GET method to support indifferent access def GET - @env["action_dispatch.request.query_parameters"] ||= (normalize_parameters(super) || {}) + begin + @env["action_dispatch.request.query_parameters"] ||= (normalize_parameters(super) || {}) + rescue TypeError => e + raise ActionController::BadRequest, "Invalid query parameters: #{e.message}" + end end alias :query_parameters :GET # Override Rack's POST method to support indifferent access def POST - @env["action_dispatch.request.request_parameters"] ||= (normalize_parameters(super) || {}) + begin + @env["action_dispatch.request.request_parameters"] ||= (normalize_parameters(super) || {}) + rescue TypeError => e + raise ActionController::BadRequest, "Invalid request parameters: #{e.message}" + end end alias :request_parameters :POST - # Returns the authorization header regardless of whether it was specified directly or through one of the # proxy alternatives. def authorization @@ -244,7 +260,7 @@ module ActionDispatch # True if the request came from localhost, 127.0.0.1. def local? - LOCALHOST.any? { |local_ip| local_ip === remote_addr && local_ip === remote_ip } + LOCALHOST =~ remote_addr && LOCALHOST =~ remote_ip end private diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 84732085f0..cc46f9983c 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -29,7 +29,7 @@ module ActionDispatch # :nodoc: # class DemoControllerTest < ActionDispatch::IntegrationTest # def test_print_root_path_to_console # get('/') - # puts @response.body + # puts response.body # end # end class Response @@ -51,12 +51,13 @@ module ActionDispatch # :nodoc: # 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 + attr_accessor :charset + attr_reader :content_type CONTENT_TYPE = "Content-Type".freeze SET_COOKIE = "Set-Cookie".freeze LOCATION = "Location".freeze - + cattr_accessor(:default_charset) { "utf-8" } include Rack::Response::Helpers @@ -83,6 +84,10 @@ module ActionDispatch # :nodoc: @status = Rack::Utils.status_code(status) end + def content_type=(content_type) + @content_type = content_type.to_s + end + # The response code of the request def response_code @status diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb index 94fa747a79..ce8c2729e9 100644 --- a/actionpack/lib/action_dispatch/http/upload.rb +++ b/actionpack/lib/action_dispatch/http/upload.rb @@ -4,11 +4,12 @@ module ActionDispatch attr_accessor :original_filename, :content_type, :tempfile, :headers def initialize(hash) + @tempfile = hash[:tempfile] + raise(ArgumentError, ':tempfile is required') unless @tempfile + @original_filename = encode_filename(hash[:filename]) @content_type = hash[:type] @headers = hash[:head] - @tempfile = hash[:tempfile] - raise(ArgumentError, ':tempfile is required') unless @tempfile end def read(*args) @@ -16,18 +17,15 @@ module ActionDispatch end # Delegate these methods to the tempfile. - [:open, :path, :rewind, :size].each do |method| + [:open, :path, :rewind, :size, :eof?].each do |method| class_eval "def #{method}; @tempfile.#{method}; end" end - + private + def encode_filename(filename) - # Encode the filename in the utf8 encoding, unless it is nil or we're in 1.8 - if "ruby".encoding_aware? && filename - filename.force_encoding("UTF-8").encode! - else - filename - end + # Encode the filename in the utf8 encoding, unless it is nil + filename.force_encoding("UTF-8").encode! if filename end end diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index 64459836b5..4266ec042e 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -1,6 +1,8 @@ module ActionDispatch module Http module URL + IP_HOST_REGEXP = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ + mattr_accessor :tld_length self.tld_length = 1 @@ -21,38 +23,45 @@ module ActionDispatch end def url_for(options = {}) - unless options[:host].present? || options[:only_path].present? + path = "" + path << options.delete(:script_name).to_s.chomp("/") + path << options.delete(:path).to_s + + params = options[:params] || {} + params.reject! {|k,v| v.to_param.nil? } + + result = build_host_url(options) + + result << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path) + result << "?#{params.to_query}" unless params.empty? + result << "##{Journey::Router::Utils.escape_fragment(options[:anchor].to_param.to_s)}" if options[:anchor] + result + end + + private + + def build_host_url(options) + if options[:host].blank? && options[:only_path].blank? raise ArgumentError, 'Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true' end - rewritten_url = "" + result = "" unless options[:only_path] unless options[:protocol] == false - rewritten_url << (options[:protocol] || "http") - rewritten_url << ":" unless rewritten_url.match(%r{:|//}) + result << (options[:protocol] || "http") + result << ":" unless result.match(%r{:|//}) end - rewritten_url << "//" unless rewritten_url.match("//") - rewritten_url << rewrite_authentication(options) - rewritten_url << host_or_subdomain_and_domain(options) - rewritten_url << ":#{options.delete(:port)}" if options[:port] + result << "//" unless result.match("//") + result << rewrite_authentication(options) + result << host_or_subdomain_and_domain(options) + result << ":#{options.delete(:port)}" if options[:port] end - - path = options.delete(:path) || '' - - params = options[:params] || {} - params.reject! {|k,v| v.to_param.nil? } - - rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path) - rewritten_url << "?#{params.to_query}" unless params.empty? - rewritten_url << "##{Journey::Router::Utils.escape_fragment(options[:anchor].to_param.to_s)}" if options[:anchor] - rewritten_url + result end - private - def named_host?(host) - !(host.nil? || /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.match(host)) + host && IP_HOST_REGEXP !~ host end def rewrite_authentication(options) @@ -167,7 +176,7 @@ module ActionDispatch # such as 2 to catch <tt>"www"</tt> instead of <tt>"www.rubyonrails"</tt> # in "www.rubyonrails.co.uk". def subdomain(tld_length = @@tld_length) - subdomains(tld_length).join(".") + ActionDispatch::Http::URL.extract_subdomain(host, tld_length) end end end |
