aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/http/headers.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch/http/headers.rb')
-rw-r--r--actionpack/lib/action_dispatch/http/headers.rb75
1 files changed, 53 insertions, 22 deletions
diff --git a/actionpack/lib/action_dispatch/http/headers.rb b/actionpack/lib/action_dispatch/http/headers.rb
index bc5410dc38..3c03976f03 100644
--- a/actionpack/lib/action_dispatch/http/headers.rb
+++ b/actionpack/lib/action_dispatch/http/headers.rb
@@ -2,9 +2,23 @@ module ActionDispatch
module Http
# Provides access to the request's HTTP headers from the environment.
#
- # env = { "CONTENT_TYPE" => "text/plain" }
- # headers = ActionDispatch::Http::Headers.new(env)
+ # env = { "CONTENT_TYPE" => "text/plain", "HTTP_USER_AGENT" => "curl/7.43.0" }
+ # headers = ActionDispatch::Http::Headers.from_hash(env)
# headers["Content-Type"] # => "text/plain"
+ # headers["User-Agent"] # => "curl/7.43.0"
+ #
+ # Also note that when headers are mapped to CGI-like variables by the Rack
+ # server, both dashes and underscores are converted to underscores. This
+ # ambiguity cannot be resolved at this stage anymore. Both underscores and
+ # dashes have to be interpreted as if they were originally sent as dashes.
+ #
+ # # GET / HTTP/1.1
+ # # ...
+ # # User-Agent: curl/7.43.0
+ # # X_Custom_Header: token
+ #
+ # headers["X_Custom_Header"] # => nil
+ # headers["X-Custom-Header"] # => "token"
class Headers
CGI_VARIABLES = Set.new(%W[
AUTH_TYPE
@@ -30,27 +44,37 @@ module ActionDispatch
HTTP_HEADER = /\A[A-Za-z0-9-]+\z/
include Enumerable
- attr_reader :env
- def initialize(env = {}) # :nodoc:
- @env = env
+ def self.from_hash(hash)
+ new ActionDispatch::Request.new hash
+ end
+
+ def initialize(request) # :nodoc:
+ @req = request
end
# Returns the value for the given key mapped to @env.
def [](key)
- @env[env_name(key)]
+ @req.get_header env_name(key)
end
# Sets the given value for the key mapped to @env.
def []=(key, value)
- @env[env_name(key)] = value
+ @req.set_header env_name(key), value
+ end
+
+ # Add a value to a multivalued header like Vary or Accept-Encoding.
+ def add(key, value)
+ @req.add_header env_name(key), value
end
def key?(key)
- @env.key? env_name(key)
+ @req.has_header? env_name(key)
end
alias :include? :key?
+ DEFAULT = Object.new # :nodoc:
+
# Returns the value for the given key mapped to @env.
#
# If the key is not found and an optional code block is not provided,
@@ -58,18 +82,22 @@ module ActionDispatch
#
# If the code block is provided, then it will be run and
# its result returned.
- def fetch(key, *args, &block)
- @env.fetch env_name(key), *args, &block
+ def fetch(key, default = DEFAULT)
+ @req.fetch_header(env_name(key)) do
+ return default unless default == DEFAULT
+ return yield if block_given?
+ raise KeyError, key
+ end
end
def each(&block)
- @env.each(&block)
+ @req.each_header(&block)
end
# Returns a new Http::Headers instance containing the contents of
# <tt>headers_or_env</tt> and the original instance.
def merge(headers_or_env)
- headers = Http::Headers.new(env.dup)
+ headers = @req.dup.headers
headers.merge!(headers_or_env)
headers
end
@@ -79,21 +107,24 @@ module ActionDispatch
# <tt>headers_or_env</tt>.
def merge!(headers_or_env)
headers_or_env.each do |key, value|
- self[env_name(key)] = value
+ @req.set_header env_name(key), value
end
end
+ def env; @req.env.dup; end
+
private
- # Converts a HTTP header name to an environment variable name if it is
- # not contained within the headers hash.
- def env_name(key)
- key = key.to_s
- if key =~ HTTP_HEADER
- key = key.upcase.tr('-', '_')
- key = "HTTP_" + key unless CGI_VARIABLES.include?(key)
+
+ # Converts an HTTP header name to an environment variable name if it is
+ # not contained within the headers hash.
+ def env_name(key)
+ key = key.to_s
+ if key =~ HTTP_HEADER
+ key = key.upcase.tr("-", "_")
+ key = "HTTP_" + key unless CGI_VARIABLES.include?(key)
+ end
+ key
end
- key
- end
end
end
end