aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/http
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch/http')
-rw-r--r--actionpack/lib/action_dispatch/http/cache.rb23
-rw-r--r--actionpack/lib/action_dispatch/http/filter_parameters.rb4
-rw-r--r--actionpack/lib/action_dispatch/http/headers.rb5
-rw-r--r--actionpack/lib/action_dispatch/http/mime_negotiation.rb16
-rw-r--r--actionpack/lib/action_dispatch/http/mime_type.rb74
-rw-r--r--actionpack/lib/action_dispatch/http/mime_types.rb3
-rw-r--r--actionpack/lib/action_dispatch/http/parameters.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb68
8 files changed, 106 insertions, 89 deletions
diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb
index 1d0a6b6eb3..30ade14c26 100644
--- a/actionpack/lib/action_dispatch/http/cache.rb
+++ b/actionpack/lib/action_dispatch/http/cache.rb
@@ -59,7 +59,7 @@ module ActionDispatch
end
def last_modified?
- have_header? LAST_MODIFIED
+ has_header? LAST_MODIFIED
end
def last_modified=(utc_time)
@@ -73,7 +73,7 @@ module ActionDispatch
end
def date?
- have_header? DATE
+ has_header? DATE
end
def date=(utc_time)
@@ -82,24 +82,19 @@ module ActionDispatch
def etag=(etag)
key = ActiveSupport::Cache.expand_cache_key(etag)
- set_header ETAG, %("#{Digest::MD5.hexdigest(key)}")
+ super %("#{Digest::MD5.hexdigest(key)}")
end
- def etag
- get_header ETAG
- end
- alias :etag? :etag
+ def etag?; etag; end
private
DATE = 'Date'.freeze
LAST_MODIFIED = "Last-Modified".freeze
- ETAG = "ETag".freeze
- CACHE_CONTROL = "Cache-Control".freeze
SPECIAL_KEYS = Set.new(%w[extras no-cache max-age public must-revalidate])
def cache_control_segments
- if cache_control = get_header(CACHE_CONTROL)
+ if cache_control = _cache_control
cache_control.delete(' ').split(',')
else
[]
@@ -153,11 +148,11 @@ module ActionDispatch
control.merge! cache_control
if control.empty?
- set_header CACHE_CONTROL, DEFAULT_CACHE_CONTROL
+ self._cache_control = DEFAULT_CACHE_CONTROL
elsif control[:no_cache]
- set_header CACHE_CONTROL, NO_CACHE
+ self._cache_control = NO_CACHE
if control[:extras]
- set_header(CACHE_CONTROL, get_header(CACHE_CONTROL) + ", #{control[:extras].join(', ')}")
+ self._cache_control = _cache_control + ", #{control[:extras].join(', ')}"
end
else
extras = control[:extras]
@@ -169,7 +164,7 @@ module ActionDispatch
options << MUST_REVALIDATE if control[:must_revalidate]
options.concat(extras) if extras
- set_header CACHE_CONTROL, options.join(", ")
+ self._cache_control = options.join(", ")
end
end
end
diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb
index 9c0f39f2e7..9dcab79c3a 100644
--- a/actionpack/lib/action_dispatch/http/filter_parameters.rb
+++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb
@@ -30,12 +30,12 @@ module ActionDispatch
@filtered_path = nil
end
- # Return a hash of parameters with all sensitive data replaced.
+ # Returns a hash of parameters with all sensitive data replaced.
def filtered_parameters
@filtered_parameters ||= parameter_filter.filter(parameters)
end
- # Return a hash of request.env with all sensitive data replaced.
+ # Returns a hash of request.env with all sensitive data replaced.
def filtered_env
@filtered_env ||= env_filter.filter(@env)
end
diff --git a/actionpack/lib/action_dispatch/http/headers.rb b/actionpack/lib/action_dispatch/http/headers.rb
index 9a3aaca3f0..12f81dc1a5 100644
--- a/actionpack/lib/action_dispatch/http/headers.rb
+++ b/actionpack/lib/action_dispatch/http/headers.rb
@@ -49,6 +49,11 @@ module ActionDispatch
@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)
@req.has_header? env_name(key)
end
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index a966c5e452..7acf91902d 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -10,7 +10,7 @@ module ActionDispatch
self.ignore_accept_header = false
end
- # The MIME type of the HTTP request, such as Mime::Type[:XML].
+ # The MIME type of the HTTP request, such as Mime[:xml].
#
# For backward compatibility, the post \format is extracted from the
# X-Post-Data-Format HTTP header if present.
@@ -49,9 +49,9 @@ module ActionDispatch
# Returns the MIME type for the \format used in the request.
#
- # GET /posts/5.xml | request.format => Mime::Type[:XML]
- # GET /posts/5.xhtml | request.format => Mime::Type[:HTML]
- # GET /posts/5 | request.format => Mime::Type[:HTML] or Mime::Type[:JS], or request.accepts.first
+ # GET /posts/5.xml | request.format => Mime[:xml]
+ # GET /posts/5.xhtml | request.format => Mime[:html]
+ # GET /posts/5 | request.format => Mime[:html] or Mime[:js], or request.accepts.first
#
def format(view_path = [])
formats.first || Mime::NullType.instance
@@ -70,9 +70,9 @@ module ActionDispatch
elsif use_accept_header && valid_accept_header
accepts
elsif xhr?
- [Mime::Type[:JS]]
+ [Mime[:js]]
else
- [Mime::Type[:HTML]]
+ [Mime[:html]]
end
set_header k, v
end
@@ -138,14 +138,14 @@ module ActionDispatch
#
def negotiate_mime(order)
formats.each do |priority|
- if priority == Mime::Type[:ALL]
+ if priority == Mime::ALL
return order.first
elsif order.include?(priority)
return priority
end
end
- order.include?(Mime::Type[:ALL]) ? format : nil
+ order.include?(Mime::ALL) ? format : nil
end
protected
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb
index 36e90e5855..95094c25c0 100644
--- a/actionpack/lib/action_dispatch/http/mime_type.rb
+++ b/actionpack/lib/action_dispatch/http/mime_type.rb
@@ -46,7 +46,8 @@ module Mime
end
def const_missing(sym)
- if Mime::Type.registered?(sym)
+ ext = sym.downcase
+ if Mime[ext]
ActiveSupport::Deprecation.warn <<-eow
Accessing mime types via constants is deprecated. Please change:
@@ -54,16 +55,17 @@ Accessing mime types via constants is deprecated. Please change:
to:
- `Mime::Type[:#{sym}]`
+ `Mime[:#{ext}]`
eow
- Mime::Type[sym]
+ Mime[ext]
else
super
end
end
def const_defined?(sym, inherit = true)
- if Mime::Type.registered?(sym)
+ ext = sym.downcase
+ if Mime[ext]
ActiveSupport::Deprecation.warn <<-eow
Accessing mime types via constants is deprecated. Please change:
@@ -71,7 +73,7 @@ Accessing mime types via constants is deprecated. Please change:
to:
- `Mime::Type.registered?(:#{sym})`
+ `Mime[:#{ext}]`
eow
true
else
@@ -106,7 +108,7 @@ to:
def initialize(index, name, q = nil)
@index = index
@name = name
- q ||= 0.0 if @name == Mime::Type[:ALL].to_s # default wildcard match to end of list
+ q ||= 0.0 if @name == '*/*'.freeze # default wildcard match to end of list
@q = ((q || 1.0).to_f * 100).to_i
end
@@ -131,7 +133,7 @@ to:
exchange_xml_items if app_xml_idx > text_xml_idx # make sure app_xml is ahead of text_xml in the list
delete_at(text_xml_idx) # delete text_xml from the list
elsif text_xml_idx
- text_xml.name = Mime::Type[:XML].to_s
+ text_xml.name = Mime[:xml].to_s
end
# Look for more specific XML-based types and sort them ahead of app/xml
@@ -160,7 +162,7 @@ to:
end
def app_xml_idx
- @app_xml_idx ||= index(Mime::Type[:XML].to_s)
+ @app_xml_idx ||= index(Mime[:xml].to_s)
end
def text_xml
@@ -177,8 +179,6 @@ to:
end
end
- TYPES = {}
-
class << self
TRAILING_STAR_REGEXP = /(text|application)\/\*/
PARAMETER_SEPARATOR_REGEXP = /;\s*\w+="?\w+"?/
@@ -187,18 +187,6 @@ to:
@register_callbacks << block
end
- def registered?(symbol)
- TYPES.key? symbol
- end
-
- def [](symbol)
- TYPES[symbol]
- end
-
- def add_type(symbol, type)
- TYPES[symbol] = type
- end
-
def lookup(string)
LOOKUP[string]
end
@@ -215,7 +203,6 @@ to:
def register(string, symbol, mime_type_synonyms = [], extension_synonyms = [], skip_lookup = false)
new_mime = Type.new(string, symbol, mime_type_synonyms)
- add_type symbol.upcase, new_mime
SET << new_mime
@@ -255,13 +242,13 @@ to:
parse_data_with_trailing_star($1) if accept_header =~ TRAILING_STAR_REGEXP
end
- # For an input of <tt>'text'</tt>, returns <tt>[Mime::Type[:JSON], Mime::Type[:XML], Mime::Type[:ICS],
- # Mime::Type[:HTML], Mime::Type[:CSS], Mime::Type[:CSV], Mime::Type[:JS], Mime::Type[:YAML], Mime::Type[:TEXT]</tt>.
+ # 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>.
#
- # For an input of <tt>'application'</tt>, returns <tt>[Mime::Type[:HTML], Mime::Type[:JS],
- # Mime::Type[:XML], Mime::Type[:YAML], Mime::Type[:ATOM], Mime::Type[:JSON], Mime::Type[:RSS], Mime::Type[:URL_ENCODED_FORM]</tt>.
- def parse_data_with_trailing_star(input)
- Mime::SET.select { |m| m =~ input }
+ # 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(type)
+ Mime::SET.select { |m| m =~ type }
end
# This method is opposite of register method.
@@ -270,12 +257,12 @@ to:
#
# Mime::Type.unregister(:mobile)
def unregister(symbol)
- symbol = symbol.upcase
- mime = TYPES.delete symbol
-
- SET.delete_if { |v| v.eql?(mime) }
- LOOKUP.delete_if { |_,v| v.eql?(mime) }
- EXTENSION_LOOKUP.delete_if { |_,v| v.eql?(mime) }
+ symbol = symbol.downcase
+ if mime = Mime[symbol]
+ SET.delete_if { |v| v.eql?(mime) }
+ LOOKUP.delete_if { |_, v| v.eql?(mime) }
+ EXTENSION_LOOKUP.delete_if { |_, v| v.eql?(mime) }
+ end
end
end
@@ -343,13 +330,24 @@ to:
def respond_to_missing?(method, include_private = false) #:nodoc:
method.to_s.ends_with? '?'
end
+ end
+
+ class AllType < Type
+ include Singleton
- class All < Type
- def all?; true; end
- def html?; true; end
+ def initialize
+ super '*/*', :all
end
+
+ def all?; true; end
+ def html?; true; end
end
+ # ALL isn't a real MIME type, so we don't register it for lookup with the
+ # other concrete types. It's a wildcard match that we use for `respond_to`
+ # negotiation internals.
+ ALL = AllType.instance
+
class NullType
include Singleton
diff --git a/actionpack/lib/action_dispatch/http/mime_types.rb b/actionpack/lib/action_dispatch/http/mime_types.rb
index 04828f7c87..87715205d9 100644
--- a/actionpack/lib/action_dispatch/http/mime_types.rb
+++ b/actionpack/lib/action_dispatch/http/mime_types.rb
@@ -31,6 +31,3 @@ Mime::Type.register "application/json", :json, %w( text/x-json application/jsonr
Mime::Type.register "application/pdf", :pdf, [], %w(pdf)
Mime::Type.register "application/zip", :zip, [], %w(zip)
-
-# Create Mime::Type[:ALL] but do not add it to the SET.
-Mime::Type.add_type :ALL, Mime::Type::All.new("*/*", :all, [])
diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb
index e3c4392760..248ecfd676 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -4,7 +4,7 @@ module ActionDispatch
PARAMETERS_KEY = 'action_dispatch.request.path_parameters'
DEFAULT_PARSERS = {
- Mime::Type[:JSON] => lambda { |raw_post|
+ Mime[:json] => lambda { |raw_post|
data = ActiveSupport::JSON.decode(raw_post)
data.is_a?(Hash) ? data : {:_json => data}
}
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index f6f63f1f32..c54efb6541 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -39,7 +39,7 @@ module ActionDispatch # :nodoc:
end
def []=(k,v)
- if @response.committed?
+ if @response.sending? || @response.sent?
raise ActionDispatch::IllegalStateError, 'header already sent'
end
@@ -78,6 +78,10 @@ module ActionDispatch # :nodoc:
cattr_accessor(:default_headers)
include Rack::Response::Helpers
+ # Aliasing these off because AD::Http::Cache::Response defines them
+ alias :_cache_control :cache_control
+ alias :_cache_control= :cache_control=
+
include ActionDispatch::Http::FilterRedirect
include ActionDispatch::Http::Cache::Response
include MonitorMixin
@@ -156,31 +160,11 @@ module ActionDispatch # :nodoc:
yield self if block_given?
end
- def have_header?(key); headers.key? key; end
+ def has_header?(key); headers.key? key; end
def get_header(key); headers[key]; end
def set_header(key, v); headers[key] = v; end
def delete_header(key); headers.delete key; end
- # Add a header that may have multiple values.
- #
- # Example:
- # response.add_header 'Vary', 'Accept'
- # response.add_header 'Vary', 'Accept-Encoding'
- # response.add_header 'Vary', 'Cookie'
- #
- # assert_equal 'Accept,Accept-Encoding,Cookie', response.get_header 'Vary'
- #
- # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
- def add_header(key, v)
- if v.nil?
- get_header key
- elsif have_header? key
- set_header key, "#{get_header key},#{v}"
- else
- set_header key, v
- end
- end
-
def await_commit
synchronize do
@cv.wait_until { @committed }
@@ -299,6 +283,10 @@ module ActionDispatch # :nodoc:
@stream.body
end
+ def write(string)
+ @stream.write string
+ end
+
EMPTY = " "
# Allows you to manually set or override the response body.
@@ -314,6 +302,40 @@ module ActionDispatch # :nodoc:
end
end
+ # Avoid having to pass an open file handle as the response body.
+ # Rack::Sendfile will usually intercept the response and uses
+ # the path directly, so there is no reason to open the file.
+ class FileBody #:nodoc:
+ attr_reader :to_path
+
+ def initialize(path)
+ @to_path = path
+ end
+
+ def body
+ File.binread(to_path)
+ end
+
+ # Stream the file's contents if Rack::Sendfile isn't present.
+ def each
+ File.open(to_path, 'rb') do |file|
+ while chunk = file.read(16384)
+ yield chunk
+ end
+ end
+ end
+ end
+
+ # Send the file stored at +path+ as the response body.
+ def send_file(path)
+ commit!
+ @stream = FileBody.new(path)
+ end
+
+ def reset_body!
+ @stream = build_buffer(self, [])
+ end
+
def body_parts
parts = []
@stream.each { |x| parts << x }
@@ -409,7 +431,7 @@ module ActionDispatch # :nodoc:
return if content_type
ct = parse_content_type
- set_content_type(ct.mime_type || Mime::Type[:HTML].to_s,
+ set_content_type(ct.mime_type || Mime[:html].to_s,
ct.charset || self.class.default_charset)
end