aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG.md22
-rw-r--r--actionpack/lib/abstract_controller/collector.rb6
-rw-r--r--actionpack/lib/abstract_controller/rendering.rb11
-rw-r--r--actionpack/lib/action_controller/base.rb1
-rw-r--r--actionpack/lib/action_controller/metal.rb9
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb16
-rw-r--r--actionpack/lib/action_controller/metal/live.rb12
-rw-r--r--actionpack/lib/action_controller/metal/mime_responds.rb8
-rw-r--r--actionpack/lib/action_controller/metal/params_wrapper.rb4
-rw-r--r--actionpack/lib/action_controller/metal/renderers.rb14
-rw-r--r--actionpack/lib/action_controller/metal/rendering.rb23
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb4
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb5
-rw-r--r--actionpack/lib/action_controller/metal/testing.rb6
-rw-r--r--actionpack/lib/action_controller/renderer.rb93
-rw-r--r--actionpack/lib/action_controller/test_case.rb30
-rw-r--r--actionpack/lib/action_dispatch/http/mime_negotiation.rb20
-rw-r--r--actionpack/lib/action_dispatch/http/mime_type.rb120
-rw-r--r--actionpack/lib/action_dispatch/http/mime_types.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/parameters.rb35
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb10
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb115
-rw-r--r--actionpack/lib/action_dispatch/journey/nfa/dot.rb2
-rw-r--r--actionpack/lib/action_dispatch/journey/visitors.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb124
-rw-r--r--actionpack/lib/action_dispatch/middleware/exception_wrapper.rb6
-rw-r--r--actionpack/lib/action_dispatch/middleware/flash.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/params_parser.rb41
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/cookie_store.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/ssl.rb3
-rw-r--r--actionpack/lib/action_dispatch/routing.rb3
-rw-r--r--actionpack/lib/action_dispatch/routing/url_for.rb3
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/test_response.rb2
-rw-r--r--actionpack/test/abstract/collector_test.rb6
-rw-r--r--actionpack/test/abstract_unit.rb1
-rw-r--r--actionpack/test/controller/action_pack_assertions_test.rb2
-rw-r--r--actionpack/test/controller/content_type_test.rb44
-rw-r--r--actionpack/test/controller/live_stream_test.rb92
-rw-r--r--actionpack/test/controller/new_base/content_type_test.rb4
-rw-r--r--actionpack/test/controller/redirect_test.rb6
-rw-r--r--actionpack/test/controller/render_other_test.rb2
-rw-r--r--actionpack/test/controller/render_xml_test.rb2
-rw-r--r--actionpack/test/controller/renderer_test.rb23
-rw-r--r--actionpack/test/controller/send_file_test.rb104
-rw-r--r--actionpack/test/controller/test_case_test.rb36
-rw-r--r--actionpack/test/controller/url_for_test.rb20
-rw-r--r--actionpack/test/controller/webservice_test.rb22
-rw-r--r--actionpack/test/dispatch/mime_type_test.rb87
-rw-r--r--actionpack/test/dispatch/request_test.rb48
-rw-r--r--actionpack/test/dispatch/response_test.rb35
-rw-r--r--actionpack/test/journey/router_test.rb1
53 files changed, 730 insertions, 565 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index f2229d61fb..bb15edee63 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,25 @@
+* ActionDispatch::Response#new no longer applies default headers. If you want
+ default headers applied to the response object, then call
+ `ActionDispatch::Response.create`. This change only impacts people who are
+ directly constructing an `ActionDispatch::Response` object.
+
+* Accessing mime types via constants like `Mime::HTML` is deprecated. Please
+ change code like this:
+
+ Mime::HTML
+
+ To this:
+
+ Mime::Type[:HTML]
+
+ This change is so that Rails will not manage a list of constants, and fixes
+ an issue where if a type isn't registered you could possibly get the wrong
+ object.
+
+* `url_for` does not modify its arguments when generating polymorphic URLs.
+
+ *Bernerd Schaefer*
+
* Make it easier to opt in to `config.force_ssl` and `config.ssl_options` by
making them less dangerous to try and easier to disable.
diff --git a/actionpack/lib/abstract_controller/collector.rb b/actionpack/lib/abstract_controller/collector.rb
index ddd56b354a..3b5128cda5 100644
--- a/actionpack/lib/abstract_controller/collector.rb
+++ b/actionpack/lib/abstract_controller/collector.rb
@@ -7,7 +7,7 @@ module AbstractController
const = sym.upcase
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{sym}(*args, &block) # def html(*args, &block)
- custom(Mime::#{const}, *args, &block) # custom(Mime::HTML, *args, &block)
+ custom(Mime::Type[:#{const}], *args, &block) # custom(Mime::Type[:HTML], *args, &block)
end # end
RUBY
end
@@ -25,7 +25,7 @@ module AbstractController
def method_missing(symbol, &block)
const_name = symbol.upcase
- unless Mime.const_defined?(const_name)
+ unless Mime::Type.registered?(const_name)
raise NoMethodError, "To respond to a custom format, register it as a MIME type first: " \
"http://guides.rubyonrails.org/action_controller_overview.html#restful-downloads. " \
"If you meant to respond to a variant like :tablet or :phone, not a custom format, " \
@@ -33,7 +33,7 @@ module AbstractController
"format.html { |html| html.tablet { ... } }"
end
- mime_constant = Mime.const_get(const_name)
+ mime_constant = Mime::Type[const_name]
if Mime::SET.include?(mime_constant)
AbstractController::Collector.generate_method_for_mime(mime_constant)
diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb
index 6db0941b52..78b43f2fbe 100644
--- a/actionpack/lib/abstract_controller/rendering.rb
+++ b/actionpack/lib/abstract_controller/rendering.rb
@@ -24,9 +24,9 @@ module AbstractController
options = _normalize_render(*args, &block)
self.response_body = render_to_body(options)
if options[:html]
- _set_content_type Mime::HTML.to_s
+ _set_html_content_type
else
- _set_content_type _get_content_type(rendered_format)
+ _set_rendered_content_type rendered_format
end
self.response_body
end
@@ -55,7 +55,7 @@ module AbstractController
# Returns Content-Type of rendered content
# :api: public
def rendered_format
- Mime::TEXT
+ Mime::Type[:TEXT]
end
DEFAULT_PROTECTED_INSTANCE_VARIABLES = Set.new %i(
@@ -106,11 +106,10 @@ module AbstractController
def _process_format(format)
end
- def _get_content_type(rendered_format) # :nodoc:
- rendered_format.to_s
+ def _set_html_content_type # :nodoc:
end
- def _set_content_type(type) # :nodoc:
+ def _set_rendered_content_type(format) # :nodoc:
end
# Normalize args and options.
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 0727bb8369..04e5922ce8 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -248,6 +248,7 @@ module ActionController
MODULES.each do |mod|
include mod
end
+ setup_renderer!
# Define some internal variables that should not be propagated to the view.
PROTECTED_IVARS = AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + [
diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb
index 030a1f3478..3d72755f1d 100644
--- a/actionpack/lib/action_controller/metal.rb
+++ b/actionpack/lib/action_controller/metal.rb
@@ -135,18 +135,11 @@ module ActionController
end
def self.make_response!(request)
- ActionDispatch::Response.new.tap do |res|
+ ActionDispatch::Response.create.tap do |res|
res.request = request
end
end
- def self.build_with_env(env = {}) #:nodoc:
- new.tap { |c|
- c.set_request! ActionDispatch::Request.new(env)
- c.set_response! make_response!(c.request)
- }
- end
-
# Delegates to the class' <tt>controller_name</tt>
def controller_name
self.class.controller_name
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 15d4562abb..fe470552b0 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -34,7 +34,7 @@ module ActionController
#
# def authenticate
# case request.format
- # when Mime::XML, Mime::ATOM
+ # when Mime::Type[:XML], Mime::Type[:ATOM]
# if user = authenticate_with_http_basic { |u, p| @account.users.authenticate(u, p) }
# @current_user = user
# else
@@ -361,7 +361,7 @@ module ActionController
#
# def authenticate
# case request.format
- # when Mime::XML, Mime::ATOM
+ # when Mime::Type[:XML], Mime::Type[:ATOM]
# if user = authenticate_with_http_token { |t, o| @account.users.authenticate(t, o) }
# @current_user = user
# else
@@ -436,15 +436,17 @@ module ActionController
end
end
- # Parses the token and options out of the token authorization header. If
- # the header looks like this:
+ # Parses the token and options out of the token authorization header.
+ # The value for the Authorization header is expected to have the prefix
+ # <tt>"Token"</tt> or <tt>"Bearer"</tt>. If the header looks like this:
# Authorization: Token token="abc", nonce="def"
- # Then the returned token is "abc", and the options is {nonce: "def"}
+ # Then the returned token is <tt>"abc"</tt>, and the options are
+ # <tt>{nonce: "def"}</tt>
#
# request - ActionDispatch::Request instance with the current headers.
#
- # Returns an Array of [String, Hash] if a token is present.
- # Returns nil if no token is found.
+ # Returns an +Array+ of <tt>[String, Hash]</tt> if a token is present.
+ # Returns +nil+ if no token is found.
def token_and_options(request)
authorization_request = request.authorization.to_s
if authorization_request[TOKEN_REGEX]
diff --git a/actionpack/lib/action_controller/metal/live.rb b/actionpack/lib/action_controller/metal/live.rb
index 69583f8ab4..c874165816 100644
--- a/actionpack/lib/action_controller/metal/live.rb
+++ b/actionpack/lib/action_controller/metal/live.rb
@@ -145,8 +145,8 @@ module ActionController
def write(string)
unless @response.committed?
- @response.headers["Cache-Control"] = "no-cache"
- @response.headers.delete "Content-Length"
+ @response.set_header "Cache-Control", "no-cache"
+ @response.delete_header "Content-Length"
end
super
@@ -236,6 +236,10 @@ module ActionController
end
end
+ def initialize(status = 200, header = {}, body = [])
+ super(status, Header.new(self, header), body)
+ end
+
private
def before_committed
@@ -257,10 +261,6 @@ module ActionController
buf
end
- def merge_default_headers(original, default)
- Header.new self, super
- end
-
def handle_conditional_get!
super unless committed?
end
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb
index e62da0fa70..fc42fe5c07 100644
--- a/actionpack/lib/action_controller/metal/mime_responds.rb
+++ b/actionpack/lib/action_controller/metal/mime_responds.rb
@@ -191,7 +191,7 @@ module ActionController #:nodoc:
if format = collector.negotiate_format(request)
_process_format(format)
- _set_content_type _get_content_type format
+ _set_rendered_content_type format
response = collector.response
response ? response.call : render({})
else
@@ -229,14 +229,14 @@ module ActionController #:nodoc:
@responses = {}
@variant = variant
- mimes.each { |mime| @responses["Mime::#{mime.upcase}".constantize] = nil }
+ mimes.each { |mime| @responses[Mime::Type[mime.upcase.to_sym]] = nil }
end
def any(*args, &block)
if args.any?
args.each { |type| send(type, &block) }
else
- custom(Mime::ALL, &block)
+ custom(Mime::Type[:ALL], &block)
end
end
alias :all :any
@@ -251,7 +251,7 @@ module ActionController #:nodoc:
end
def response
- response = @responses.fetch(format, @responses[Mime::ALL])
+ response = @responses.fetch(format, @responses[Mime::Type[:ALL]])
if response.is_a?(VariantCollector) # `format.html.phone` - variant inline syntax
response.variant
elsif response.nil? || response.arity == 0 # `format.html` - just a format, call its block
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index e680432127..c38fc40b81 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -276,7 +276,9 @@ module ActionController
# Checks if we should perform parameters wrapping.
def _wrapper_enabled?
- ref = request.content_mime_type.try(:ref)
+ return false unless request.has_content_type?
+
+ ref = request.content_mime_type.ref
_wrapper_formats.include?(ref) && _wrapper_key && !request.request_parameters[_wrapper_key]
end
end
diff --git a/actionpack/lib/action_controller/metal/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb
index cb74c4f0d4..d867c97b46 100644
--- a/actionpack/lib/action_controller/metal/renderers.rb
+++ b/actionpack/lib/action_controller/metal/renderers.rb
@@ -68,11 +68,11 @@ module ActionController
# ActionController::Renderers.add :csv do |obj, options|
# filename = options[:filename] || 'data'
# str = obj.respond_to?(:to_csv) ? obj.to_csv : obj.to_s
- # send_data str, type: Mime::CSV,
+ # send_data str, type: Mime::Type[:CSV],
# disposition: "attachment; filename=#{filename}.csv"
# end
#
- # Note that we used Mime::CSV for the csv mime type as it comes with Rails.
+ # Note that we used Mime::Type[:CSV] for the csv mime type as it comes with Rails.
# For a custom renderer, you'll need to register a mime type with
# <tt>Mime::Type.register</tt>.
#
@@ -116,24 +116,24 @@ module ActionController
json = json.to_json(options) unless json.kind_of?(String)
if options[:callback].present?
- if content_type.nil? || content_type == Mime::JSON
- self.content_type = Mime::JS
+ if content_type.nil? || content_type == Mime::Type[:JSON]
+ self.content_type = Mime::Type[:JS]
end
"/**/#{options[:callback]}(#{json})"
else
- self.content_type ||= Mime::JSON
+ self.content_type ||= Mime::Type[:JSON]
json
end
end
add :js do |js, options|
- self.content_type ||= Mime::JS
+ self.content_type ||= Mime::Type[:JS]
js.respond_to?(:to_js) ? js.to_js(options) : js
end
add :xml do |xml, options|
- self.content_type ||= Mime::XML
+ self.content_type ||= Mime::Type[:XML]
xml.respond_to?(:to_xml) ? xml.to_xml(options) : xml
end
end
diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb
index c8934b367f..1ecccf9864 100644
--- a/actionpack/lib/action_controller/metal/rendering.rb
+++ b/actionpack/lib/action_controller/metal/rendering.rb
@@ -11,10 +11,17 @@ module ActionController
# Documentation at ActionController::Renderer#render
delegate :render, to: :renderer
- # Returns a renderer class (inherited from ActionController::Renderer)
+ # Returns a renderer instance (inherited from ActionController::Renderer)
# for the controller.
- def renderer
- @renderer ||= Renderer.for(self)
+ attr_reader :renderer
+
+ def setup_renderer! # :nodoc:
+ @renderer = Renderer.for(self)
+ end
+
+ def inherited(klass)
+ klass.setup_renderer!
+ super
end
end
@@ -56,12 +63,14 @@ module ActionController
nil
end
- def _get_content_type(rendered_format)
- self.content_type || super
+ def _set_html_content_type
+ self.content_type = Mime::Type[:HTML].to_s
end
- def _set_content_type(format)
- self.content_type = format
+ def _set_rendered_content_type(format)
+ unless response.content_type
+ self.content_type = format.to_s
+ end
end
# Normalize arguments by catching blocks and setting them on :update.
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index e5f3cb8e8d..5674eef67b 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -137,8 +137,8 @@ module ActionController #:nodoc:
def handle_unverified_request
request = @controller.request
request.session = NullSessionHash.new(request)
- request.env['action_dispatch.request.flash_hash'] = nil
- request.env['rack.session.options'] = { skip: true }
+ request.flash = nil
+ request.session_options = { skip: true }
request.cookie_jar = NullCookieJar.build(request, {})
end
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index bf5c7003ff..903dba3eb4 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -97,9 +97,8 @@ module ActionController
# environment they should only be set once at boot-time and never mutated at
# runtime.
#
- # <tt>ActionController::Parameters</tt> inherits from
- # <tt>ActiveSupport::HashWithIndifferentAccess</tt>, this means
- # that you can fetch values using either <tt>:key</tt> or <tt>"key"</tt>.
+ # You can fetch values of <tt>ActionController::Parameters</tt> using either
+ # <tt>:key</tt> or <tt>"key"</tt>.
#
# params = ActionController::Parameters.new(key: 'value')
# params[:key] # => "value"
diff --git a/actionpack/lib/action_controller/metal/testing.rb b/actionpack/lib/action_controller/metal/testing.rb
index 47d940f692..b2b3b4283f 100644
--- a/actionpack/lib/action_controller/metal/testing.rb
+++ b/actionpack/lib/action_controller/metal/testing.rb
@@ -2,12 +2,6 @@ module ActionController
module Testing
extend ActiveSupport::Concern
- # TODO : Rewrite tests using controller.headers= to use Rack env
- def headers=(new_headers)
- @_response ||= ActionDispatch::Response.new
- @_response.headers.replace(new_headers)
- end
-
# Behavior specific to functional tests
module Functional # :nodoc:
def set_response!(request)
diff --git a/actionpack/lib/action_controller/renderer.rb b/actionpack/lib/action_controller/renderer.rb
index e8b29c5b5e..e4d19e9dba 100644
--- a/actionpack/lib/action_controller/renderer.rb
+++ b/actionpack/lib/action_controller/renderer.rb
@@ -34,67 +34,78 @@ module ActionController
# ApplicationController.renderer.new(method: 'post', https: true)
#
class Renderer
- class_attribute :controller, :defaults
- # Rack environment to render templates in.
- attr_reader :env
+ attr_reader :defaults, :controller
- class << self
- delegate :render, to: :new
+ DEFAULTS = {
+ http_host: 'example.org',
+ https: false,
+ method: 'get',
+ script_name: '',
+ input: ''
+ }.freeze
- # Create a new renderer class for a specific controller class.
- def for(controller)
- Class.new self do
- self.controller = controller
- self.defaults = {
- http_host: 'example.org',
- https: false,
- method: 'get',
- script_name: '',
- 'rack.input' => ''
- }
- end
- end
+ # Create a new renderer instance for a specific controller class.
+ def self.for(controller, env = {}, defaults = DEFAULTS)
+ new(controller, env, defaults)
+ end
+
+ # Create a new renderer for the same controller but with a new env.
+ def new(env = {})
+ self.class.new controller, env, defaults
+ end
+
+ # Create a new renderer for the same controller but with new defaults.
+ def with_defaults(defaults)
+ self.class.new controller, env, self.defaults.merge(defaults)
end
# Accepts a custom Rack environment to render templates in.
# It will be merged with ActionController::Renderer.defaults
- def initialize(env = {})
- @env = normalize_keys(defaults).merge normalize_keys(env)
- @env['action_dispatch.routes'] = controller._routes
+ def initialize(controller, env, defaults)
+ @controller = controller
+ @defaults = defaults
+ @env = normalize_keys defaults.merge(env)
end
# Render templates with any options from ActionController::Base#render_to_string.
def render(*args)
- raise 'missing controller' unless controller?
+ raise 'missing controller' unless controller
- instance = controller.build_with_env(env)
+ request = ActionDispatch::Request.new @env
+ request.routes = controller._routes
+
+ instance = controller.new
+ instance.set_request! request
+ instance.set_response! controller.make_response!(request)
instance.render_to_string(*args)
end
private
def normalize_keys(env)
- http_header_format(env).tap do |new_env|
- handle_method_key! new_env
- handle_https_key! new_env
- end
+ new_env = {}
+ env.each_pair { |k,v| new_env[rack_key_for(k)] = rack_value_for(k, v) }
+ new_env
end
- def http_header_format(env)
- env.transform_keys do |key|
- key.is_a?(Symbol) ? key.to_s.upcase : key
- end
- end
+ RACK_KEY_TRANSLATION = {
+ http_host: 'HTTP_HOST',
+ https: 'HTTPS',
+ method: 'REQUEST_METHOD',
+ script_name: 'SCRIPT_NAME',
+ input: 'rack.input'
+ }
- def handle_method_key!(env)
- if method = env.delete('METHOD')
- env['REQUEST_METHOD'] = method.upcase
- end
- end
+ IDENTITY = ->(_) { _ }
+
+ RACK_VALUE_TRANSLATION = {
+ https: ->(v) { v ? 'on' : 'off' },
+ method: ->(v) { v.upcase },
+ }
+
+ def rack_key_for(key); RACK_KEY_TRANSLATION[key]; end
- def handle_https_key!(env)
- if env.has_key? 'HTTPS'
- env['HTTPS'] = env['HTTPS'] ? 'on' : 'off'
- end
+ def rack_value_for(key, value)
+ RACK_VALUE_TRANSLATION.fetch(key, IDENTITY).call value
end
end
end
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 472bb74add..cf78688126 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -33,6 +33,9 @@ module ActionController
self.session = session
self.session_options = TestSession::DEFAULT_OPTIONS
+ @custom_param_parsers = {
+ Mime::Type[:XML] => lambda { |raw_post| Hash.from_xml(raw_post)['hash'] }
+ }
end
def query_string=(string)
@@ -74,23 +77,18 @@ module ActionController
set_header k, 'application/x-www-form-urlencoded'
end
- # FIXME: setting `request_parametes` is normally handled by the
- # params parser middleware, and we should remove this roundtripping
- # when we switch to caling `call` on the controller
-
- case content_mime_type.ref
+ case content_mime_type.to_sym
+ when nil
+ raise "Unknown Content-Type: #{content_type}"
when :json
data = ActiveSupport::JSON.encode(non_path_parameters)
- params = ActiveSupport::JSON.decode(data).with_indifferent_access
- self.request_parameters = params
when :xml
data = non_path_parameters.to_xml
- params = Hash.from_xml(data)['hash']
- self.request_parameters = params
when :url_encoded_form
data = non_path_parameters.to_query
else
- raise "Unknown Content-Type: #{content_type}"
+ @custom_param_parsers[content_mime_type] = ->(_) { non_path_parameters }
+ data = non_path_parameters.to_query
end
end
@@ -133,6 +131,12 @@ module ActionController
"multipart/form-data; boundary=#{Rack::Test::MULTIPART_BOUNDARY}"
end
end.new
+
+ private
+
+ def params_parsers
+ super.merge @custom_param_parsers
+ end
end
class LiveTestResponse < Live::Response
@@ -398,7 +402,7 @@ module ActionController
MSG
@request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
- @request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
+ @request.env['HTTP_ACCEPT'] ||= [Mime::Type[:JS], Mime::Type[:HTML], Mime::Type[:XML], 'text/xml', Mime::Type[:ALL]].join(', ')
__send__(*args).tap do
@request.env.delete 'HTTP_X_REQUESTED_WITH'
@request.env.delete 'HTTP_ACCEPT'
@@ -501,7 +505,7 @@ module ActionController
if xhr
@request.set_header 'HTTP_X_REQUESTED_WITH', 'XMLHttpRequest'
@request.fetch_header('HTTP_ACCEPT') do |k|
- @request.set_header k, [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
+ @request.set_header k, [Mime::Type[:JS], Mime::Type[:HTML], Mime::Type[:XML], 'text/xml', Mime::Type[:ALL]].join(', ')
end
end
@@ -581,7 +585,7 @@ module ActionController
end
def build_response(klass)
- klass.new
+ klass.create
end
included do
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index cab60a508a..a966c5e452 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::XML.
+ # The MIME type of the HTTP request, such as Mime::Type[:XML].
#
# For backward compatibility, the post \format is extracted from the
# X-Post-Data-Format HTTP header if present.
@@ -29,6 +29,10 @@ module ActionDispatch
content_mime_type && content_mime_type.to_s
end
+ def has_content_type?
+ has_header? 'CONTENT_TYPE'
+ end
+
# Returns the accepted MIME type for the request.
def accepts
fetch_header("action_dispatch.request.accepts") do |k|
@@ -45,9 +49,9 @@ module ActionDispatch
# Returns the MIME type for the \format used in the request.
#
- # 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
+ # 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
#
def format(view_path = [])
formats.first || Mime::NullType.instance
@@ -66,9 +70,9 @@ module ActionDispatch
elsif use_accept_header && valid_accept_header
accepts
elsif xhr?
- [Mime::JS]
+ [Mime::Type[:JS]]
else
- [Mime::HTML]
+ [Mime::Type[:HTML]]
end
set_header k, v
end
@@ -134,14 +138,14 @@ module ActionDispatch
#
def negotiate_mime(order)
formats.each do |priority|
- if priority == Mime::ALL
+ if priority == Mime::Type[:ALL]
return order.first
elsif order.include?(priority)
return priority
end
end
- order.include?(Mime::ALL) ? format : nil
+ order.include?(Mime::Type[: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 a639f8a8f8..a4dfe72c63 100644
--- a/actionpack/lib/action_dispatch/http/mime_type.rb
+++ b/actionpack/lib/action_dispatch/http/mime_type.rb
@@ -1,23 +1,32 @@
-require 'set'
require 'singleton'
require 'active_support/core_ext/module/attribute_accessors'
require 'active_support/core_ext/string/starts_ends_with'
+require 'active_support/deprecation'
module Mime
- class Mimes < Array
- def symbols
- @symbols ||= map(&:to_sym)
+ class Mimes
+ include Enumerable
+
+ def initialize
+ @mimes = []
+ @symbols = nil
end
- %w(<< concat shift unshift push pop []= clear compact! collect!
- delete delete_at delete_if flatten! map! insert reject! reverse!
- replace slice! sort! uniq!).each do |method|
- module_eval <<-CODE, __FILE__, __LINE__ + 1
- def #{method}(*)
- @symbols = nil
- super
- end
- CODE
+ def each
+ @mimes.each { |x| yield x }
+ end
+
+ def <<(type)
+ @mimes << type
+ @symbols = nil
+ end
+
+ def delete_if
+ @mimes.delete_if { |x| yield x }.tap { @symbols = nil }
+ end
+
+ def symbols
+ @symbols ||= map(&:to_sym)
end
end
@@ -35,6 +44,40 @@ module Mime
return type if type.is_a?(Type)
EXTENSION_LOOKUP.fetch(type.to_s) { |k| yield k }
end
+
+ def const_missing(sym)
+ if Mime::Type.registered?(sym)
+ ActiveSupport::Deprecation.warn <<-eow
+Accessing mime types via constants is deprecated. Please change:
+
+ `Mime::#{sym}`
+
+to:
+
+ `Mime::Type[:#{sym}]`
+ eow
+ Mime::Type[sym]
+ else
+ super
+ end
+ end
+
+ def const_defined?(sym, inherit = true)
+ if Mime::Type.registered?(sym)
+ ActiveSupport::Deprecation.warn <<-eow
+Accessing mime types via constants is deprecated. Please change:
+
+ `Mime.const_defined?(#{sym})`
+
+to:
+
+ `Mime::Type.registered?(:#{sym})`
+ eow
+ true
+ else
+ super
+ end
+ end
end
# Encapsulates the notion of a mime type. Can be used at render time, for example, with:
@@ -51,9 +94,6 @@ module Mime
# end
# end
class Type
- @@html_types = Set.new [:html, :all]
- cattr_reader :html_types
-
attr_reader :symbol
@register_callbacks = []
@@ -66,7 +106,7 @@ module Mime
def initialize(index, name, q = nil)
@index = index
@name = name
- q ||= 0.0 if @name == Mime::ALL.to_s # default wildcard match to end of list
+ q ||= 0.0 if @name == Mime::Type[:ALL].to_s # default wildcard match to end of list
@q = ((q || 1.0).to_f * 100).to_i
end
@@ -120,7 +160,7 @@ module Mime
end
def app_xml_idx
- @app_xml_idx ||= index(Mime::XML.to_s)
+ @app_xml_idx ||= index(Mime::Type[:XML].to_s)
end
def text_xml
@@ -137,6 +177,8 @@ module Mime
end
end
+ TYPES = {}
+
class << self
TRAILING_STAR_REGEXP = /(text|application)\/\*/
PARAMETER_SEPARATOR_REGEXP = /;\s*\w+="?\w+"?/
@@ -145,6 +187,18 @@ module Mime
@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
@@ -160,17 +214,18 @@ module Mime
end
def register(string, symbol, mime_type_synonyms = [], extension_synonyms = [], skip_lookup = false)
- Mime.const_set(symbol.upcase, Type.new(string, symbol, mime_type_synonyms))
+ new_mime = Type.new(string, symbol, mime_type_synonyms)
+ add_type symbol.upcase, new_mime
- new_mime = Mime.const_get(symbol.upcase)
SET << new_mime
- ([string] + mime_type_synonyms).each { |str| LOOKUP[str] = SET.last } unless skip_lookup
- ([symbol] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext.to_s] = SET.last }
+ ([string] + mime_type_synonyms).each { |str| LOOKUP[str] = new_mime } unless skip_lookup
+ ([symbol] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext.to_s] = new_mime }
@register_callbacks.each do |callback|
callback.call(new_mime)
end
+ new_mime
end
def parse(accept_header)
@@ -216,8 +271,7 @@ module Mime
# Mime::Type.unregister(:mobile)
def unregister(symbol)
symbol = symbol.upcase
- mime = Mime.const_get(symbol)
- Mime.instance_eval { remove_const(symbol) }
+ mime = TYPES.delete symbol
SET.delete_if { |v| v.eql?(mime) }
LOOKUP.delete_if { |_,v| v.eql?(mime) }
@@ -243,7 +297,7 @@ module Mime
end
def ref
- to_sym || to_s
+ symbol || to_s
end
def ===(list)
@@ -255,24 +309,23 @@ module Mime
end
def ==(mime_type)
- return false if mime_type.blank?
+ return false unless mime_type
(@synonyms + [ self ]).any? do |synonym|
synonym.to_s == mime_type.to_s || synonym.to_sym == mime_type.to_sym
end
end
def =~(mime_type)
- return false if mime_type.blank?
+ return false unless mime_type
regexp = Regexp.new(Regexp.quote(mime_type.to_s))
- (@synonyms + [ self ]).any? do |synonym|
- synonym.to_s =~ regexp
- end
+ @synonyms.any? { |synonym| synonym.to_s =~ regexp } || @string =~ regexp
end
def html?
- @@html_types.include?(to_sym) || @string =~ /html/
+ symbol == :html || @string =~ /html/
end
+ def all?; false; end
private
@@ -290,6 +343,11 @@ module Mime
def respond_to_missing?(method, include_private = false) #:nodoc:
method.to_s.ends_with? '?'
end
+
+ class All < Type
+ def all?; true; end
+ def html?; true; end
+ end
end
class NullType
diff --git a/actionpack/lib/action_dispatch/http/mime_types.rb b/actionpack/lib/action_dispatch/http/mime_types.rb
index 01a10c693b..0af3e5c0df 100644
--- a/actionpack/lib/action_dispatch/http/mime_types.rb
+++ b/actionpack/lib/action_dispatch/http/mime_types.rb
@@ -33,4 +33,4 @@ Mime::Type.register "application/pdf", :pdf, [], %w(pdf)
Mime::Type.register "application/zip", :zip, [], %w(zip)
# Create Mime::ALL but do not add it to the SET.
-Mime::ALL = Mime::Type.new("*/*", :all, [])
+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 3c9f8cd9e4..e3c4392760 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -3,6 +3,20 @@ module ActionDispatch
module Parameters
PARAMETERS_KEY = 'action_dispatch.request.path_parameters'
+ DEFAULT_PARSERS = {
+ Mime::Type[:JSON] => lambda { |raw_post|
+ data = ActiveSupport::JSON.decode(raw_post)
+ data.is_a?(Hash) ? data : {:_json => data}
+ }
+ }
+
+ def self.included(klass)
+ class << klass
+ attr_accessor :parameter_parsers
+ end
+
+ klass.parameter_parsers = DEFAULT_PARSERS
+ end
# Returns both GET and POST \parameters in a single hash.
def parameters
params = get_header("action_dispatch.request.parameters")
@@ -31,6 +45,27 @@ module ActionDispatch
def path_parameters
get_header(PARAMETERS_KEY) || {}
end
+
+ private
+
+ def parse_formatted_parameters(parsers)
+ return yield if content_length.zero?
+
+ strategy = parsers.fetch(content_mime_type) { return yield }
+
+ begin
+ strategy.call(raw_post)
+ rescue => e # JSON or Ruby code block errors
+ my_logger = logger || ActiveSupport::Logger.new($stderr)
+ my_logger.debug "Error occurred while parsing request parameters.\nContents:\n\n#{raw_post}"
+
+ raise ParamsParser::ParseError.new(e.message, e)
+ end
+ end
+
+ def params_parsers
+ ActionDispatch::Request.parameter_parsers
+ end
end
end
end
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 18504eba6d..eaa7e88b34 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -324,7 +324,7 @@ module ActionDispatch
else
self.session = {}
end
- set_header('action_dispatch.request.flash_hash', nil)
+ self.flash = nil
end
def session=(session) #:nodoc:
@@ -348,8 +348,14 @@ module ActionDispatch
# Override Rack's POST method to support indifferent access
def POST
fetch_header("action_dispatch.request.request_parameters") do
- self.request_parameters = Request::Utils.normalize_encode_params(super || {})
+ pr = parse_formatted_parameters(params_parsers) do |params|
+ super || {}
+ end
+ self.request_parameters = Request::Utils.normalize_encode_params(pr)
end
+ rescue ParamsParser::ParseError # one of the parse strategies blew up
+ self.request_parameters = Request::Utils.normalize_encode_params(super || {})
+ raise
rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
raise ActionController::BadRequest.new(:request, e)
end
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 4aee489912..cbeea9e267 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -38,8 +38,6 @@ module ActionDispatch # :nodoc:
# The HTTP status code.
attr_reader :status
- attr_writer :sending_file
-
# Get headers for this response.
attr_reader :header
@@ -48,20 +46,6 @@ module ActionDispatch # :nodoc:
delegate :[], :[]=, :to => :@header
delegate :each, :to => :@stream
- # 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_reader :content_type
-
- # The charset of the response. HTML wants to know the encoding of the
- # content you're giving them, so we need to send that along.
- attr_reader :charset
-
CONTENT_TYPE = "Content-Type".freeze
SET_COOKIE = "Set-Cookie".freeze
LOCATION = "Location".freeze
@@ -119,31 +103,30 @@ module ActionDispatch # :nodoc:
end
end
+ def self.create(status = 200, header = {}, body = [], default_headers: self.default_headers)
+ header = merge_default_headers(header, default_headers)
+ new status, header, body
+ end
+
+ def self.merge_default_headers(original, default)
+ default.respond_to?(:merge) ? default.merge(original) : original
+ end
+
# The underlying body, as a streamable object.
attr_reader :stream
- def initialize(status = 200, header = {}, body = [], default_headers: self.class.default_headers)
+ def initialize(status = 200, header = {}, body = [])
super()
- header = merge_default_headers(header, default_headers)
@header = header
self.body, self.status = body, status
- @sending_file = false
@blank = false
@cv = new_cond
@committed = false
@sending = false
@sent = false
- @content_type = nil
- @charset = self.class.default_charset
-
- if content_type = self[CONTENT_TYPE]
- type, charset = content_type.split(/;\s*charset=/)
- @content_type = Mime::Type.lookup(type)
- @charset = charset || self.class.default_charset
- end
prepare_cache_control!
@@ -199,7 +182,27 @@ module ActionDispatch # :nodoc:
# Sets the HTTP content type.
def content_type=(content_type)
- @content_type = content_type.to_s
+ header_info = parse_content_type
+ set_content_type content_type.to_s, header_info.charset || self.class.default_charset
+ 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.
+
+ def content_type
+ parse_content_type.mime_type
+ end
+
+ def sending_file=(v)
+ if true == v
+ self.charset = false
+ end
end
# Sets the HTTP character set. In case of nil parameter
@@ -208,7 +211,20 @@ module ActionDispatch # :nodoc:
# response.charset = 'utf-16' # => 'utf-16'
# response.charset = nil # => 'utf-8'
def charset=(charset)
- @charset = charset.nil? ? self.class.default_charset : charset
+ header_info = parse_content_type
+ if false == charset
+ set_header CONTENT_TYPE, header_info.mime_type
+ else
+ content_type = header_info.mime_type
+ set_content_type content_type, charset || self.class.default_charset
+ end
+ end
+
+ # The charset of the response. HTML wants to know the encoding of the
+ # content you're giving them, so we need to send that along.
+ def charset
+ header_info = parse_content_type
+ header_info.charset || self.class.default_charset
end
# The response code of the request.
@@ -308,6 +324,26 @@ module ActionDispatch # :nodoc:
private
+ ContentTypeHeader = Struct.new :mime_type, :charset
+ NullContentTypeHeader = ContentTypeHeader.new nil, nil
+
+ def parse_content_type
+ content_type = get_header CONTENT_TYPE
+ if content_type
+ type, charset = content_type.split(/;\s*charset=/)
+ type = nil if type.empty?
+ ContentTypeHeader.new(type, charset)
+ else
+ NullContentTypeHeader
+ end
+ end
+
+ def set_content_type(content_type, charset)
+ type = (content_type || '').dup
+ type << "; charset=#{charset}" if charset
+ set_header CONTENT_TYPE, type
+ end
+
def before_committed
return if committed?
assign_default_content_type_and_charset!
@@ -317,10 +353,6 @@ module ActionDispatch # :nodoc:
def before_sending
end
- def merge_default_headers(original, default)
- default.respond_to?(:merge) ? default.merge(original) : original
- end
-
def build_buffer(response, body)
Buffer.new response, body
end
@@ -330,18 +362,11 @@ module ActionDispatch # :nodoc:
end
def assign_default_content_type_and_charset!
- return if get_header(CONTENT_TYPE).present?
-
- @content_type ||= Mime::HTML
-
- type = @content_type.to_s.dup
- type << "; charset=#{charset}" if append_charset?
-
- set_header CONTENT_TYPE, type
- end
+ return if content_type
- def append_charset?
- !@sending_file && @charset != false
+ ct = parse_content_type
+ set_content_type(ct.mime_type || Mime::Type[:HTML].to_s,
+ ct.charset || self.class.default_charset)
end
class RackBody
@@ -381,7 +406,7 @@ module ActionDispatch # :nodoc:
end
def rack_response(status, header)
- if NO_CONTENT_CODES.include?(@status)
+ if NO_CONTENT_CODES.include?(status)
header.delete CONTENT_TYPE
header.delete 'Content-Length'
[status, header, []]
diff --git a/actionpack/lib/action_dispatch/journey/nfa/dot.rb b/actionpack/lib/action_dispatch/journey/nfa/dot.rb
index 47bf76bdbf..7063b44bb5 100644
--- a/actionpack/lib/action_dispatch/journey/nfa/dot.rb
+++ b/actionpack/lib/action_dispatch/journey/nfa/dot.rb
@@ -1,5 +1,3 @@
-# encoding: utf-8
-
module ActionDispatch
module Journey # :nodoc:
module NFA # :nodoc:
diff --git a/actionpack/lib/action_dispatch/journey/visitors.rb b/actionpack/lib/action_dispatch/journey/visitors.rb
index 537c9b2f5c..306d2e674a 100644
--- a/actionpack/lib/action_dispatch/journey/visitors.rb
+++ b/actionpack/lib/action_dispatch/journey/visitors.rb
@@ -1,5 +1,3 @@
-# encoding: utf-8
-
module ActionDispatch
module Journey # :nodoc:
class Format
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index f37439e4d7..b653e4eacd 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -221,19 +221,11 @@ module ActionDispatch
end
end
- protected
-
- def request; @parent_jar.request; end
-
private
def upgrade_legacy_signed_cookies?
request.secret_token.present? && request.secret_key_base.present?
end
-
- def key_generator
- request.key_generator
- end
end
# Passing the ActiveSupport::MessageEncryptor::NullSerializer downstream
@@ -253,6 +245,11 @@ module ActionDispatch
rescue ActiveSupport::MessageVerifier::InvalidSignature
nil
end
+
+ private
+ def parse(name, signed_message)
+ super || verify_and_upgrade_legacy_signed_message(name, signed_message)
+ end
end
class CookieJar #:nodoc:
@@ -412,7 +409,7 @@ module ActionDispatch
end
end
- class PermanentCookieJar #:nodoc:
+ class AbstractCookieJar # :nodoc:
include ChainedCookieJars
def initialize(parent_jar)
@@ -420,19 +417,35 @@ module ActionDispatch
end
def [](name)
- @parent_jar[name.to_s]
+ if data = @parent_jar[name.to_s]
+ parse name, data
+ end
end
def []=(name, options)
if options.is_a?(Hash)
options.symbolize_keys!
else
- options = { :value => options }
+ options = { value: options }
end
- options[:expires] = 20.years.from_now
+ commit(options)
@parent_jar[name] = options
end
+
+ protected
+ def request; @parent_jar.request; end
+
+ private
+ def parse(name, data); data; end
+ def commit(options); end
+ end
+
+ class PermanentCookieJar < AbstractCookieJar # :nodoc:
+ private
+ def commit(options)
+ options[:expires] = 20.years.from_now
+ end
end
class JsonSerializer # :nodoc:
@@ -484,45 +497,30 @@ module ActionDispatch
def digest
request.cookies_digest || 'SHA1'
end
+
+ def key_generator
+ request.key_generator
+ end
end
- class SignedCookieJar #:nodoc:
- include ChainedCookieJars
+ class SignedCookieJar < AbstractCookieJar # :nodoc:
include SerializedCookieJars
def initialize(parent_jar)
- @parent_jar = parent_jar
+ super
secret = key_generator.generate_key(request.signed_cookie_salt)
@verifier = ActiveSupport::MessageVerifier.new(secret, digest: digest, serializer: ActiveSupport::MessageEncryptor::NullSerializer)
end
- # Returns the value of the cookie by +name+ if it is untampered,
- # returns +nil+ otherwise or if no such cookie exists.
- def [](name)
- if signed_message = @parent_jar[name]
- deserialize name, verify(signed_message)
+ private
+ def parse(name, signed_message)
+ deserialize name, @verifier.verified(signed_message)
end
- end
- # Signs and sets the cookie named +name+. The second argument may be the cookie's
- # value or a hash of options as documented above.
- def []=(name, options)
- if options.is_a?(Hash)
- options.symbolize_keys!
+ def commit(options)
options[:value] = @verifier.generate(serialize(options[:value]))
- else
- options = { :value => @verifier.generate(serialize(options)) }
- end
- raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
- @parent_jar[name] = options
- end
-
- private
- def verify(signed_message)
- @verifier.verify(signed_message)
- rescue ActiveSupport::MessageVerifier::InvalidSignature
- nil
+ raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
end
end
@@ -532,20 +530,13 @@ module ActionDispatch
# re-saves them using the new key generator to provide a smooth upgrade path.
class UpgradeLegacySignedCookieJar < SignedCookieJar #:nodoc:
include VerifyAndUpgradeLegacySignedMessage
-
- def [](name)
- if signed_message = @parent_jar[name]
- deserialize(name, verify(signed_message)) || verify_and_upgrade_legacy_signed_message(name, signed_message)
- end
- end
end
- class EncryptedCookieJar #:nodoc:
- include ChainedCookieJars
+ class EncryptedCookieJar < AbstractCookieJar # :nodoc:
include SerializedCookieJars
def initialize(parent_jar)
- @parent_jar = parent_jar
+ super
if ActiveSupport::LegacyKeyGenerator === key_generator
raise "You didn't set secrets.secret_key_base, which is required for this cookie jar. " +
@@ -557,35 +548,18 @@ module ActionDispatch
@encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, digest: digest, serializer: ActiveSupport::MessageEncryptor::NullSerializer)
end
- # Returns the value of the cookie by +name+ if it is untampered,
- # returns +nil+ otherwise or if no such cookie exists.
- def [](name)
- if encrypted_message = @parent_jar[name]
- deserialize name, decrypt_and_verify(encrypted_message)
- end
- end
-
- # Encrypts and sets the cookie named +name+. The second argument may be the cookie's
- # value or a hash of options as documented above.
- def []=(name, options)
- if options.is_a?(Hash)
- options.symbolize_keys!
- else
- options = { :value => options }
- end
-
- options[:value] = @encryptor.encrypt_and_sign(serialize(options[:value]))
-
- raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
- @parent_jar[name] = options
- end
-
private
- def decrypt_and_verify(encrypted_message)
- @encryptor.decrypt_and_verify(encrypted_message)
+ def parse(name, encrypted_message)
+ deserialize name, @encryptor.decrypt_and_verify(encrypted_message)
rescue ActiveSupport::MessageVerifier::InvalidSignature, ActiveSupport::MessageEncryptor::InvalidMessage
nil
end
+
+ def commit(options)
+ options[:value] = @encryptor.encrypt_and_sign(serialize(options[:value]))
+
+ raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
+ end
end
# UpgradeLegacyEncryptedCookieJar is used by ActionDispatch::Session::CookieStore
@@ -594,12 +568,6 @@ module ActionDispatch
# encrypts and re-saves them using the new key generator to provide a smooth upgrade path.
class UpgradeLegacyEncryptedCookieJar < EncryptedCookieJar #:nodoc:
include VerifyAndUpgradeLegacySignedMessage
-
- def [](name)
- if encrypted_or_signed_message = @parent_jar[name]
- deserialize(name, decrypt_and_verify(encrypted_or_signed_message)) || verify_and_upgrade_legacy_signed_message(name, encrypted_or_signed_message)
- end
- end
end
def initialize(app)
diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
index 039efc3af8..5fd984cd07 100644
--- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
+++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
@@ -61,7 +61,7 @@ module ActionDispatch
end
def traces
- appplication_trace_with_ids = []
+ application_trace_with_ids = []
framework_trace_with_ids = []
full_trace_with_ids = []
@@ -69,7 +69,7 @@ module ActionDispatch
trace_with_id = { id: idx, trace: trace }
if application_trace.include?(trace)
- appplication_trace_with_ids << trace_with_id
+ application_trace_with_ids << trace_with_id
else
framework_trace_with_ids << trace_with_id
end
@@ -78,7 +78,7 @@ module ActionDispatch
end
{
- "Application Trace" => appplication_trace_with_ids,
+ "Application Trace" => application_trace_with_ids,
"Framework Trace" => framework_trace_with_ids,
"Full Trace" => full_trace_with_ids
}
diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb
index c482b1c5e7..014b7bee61 100644
--- a/actionpack/lib/action_dispatch/middleware/flash.rb
+++ b/actionpack/lib/action_dispatch/middleware/flash.rb
@@ -276,7 +276,7 @@ module ActionDispatch
req = ActionDispatch::Request.new env
@app.call(env)
ensure
- session = Request::Session.find(req) || {}
+ session = req.session || {}
flash_hash = req.flash_hash
if flash_hash && (flash_hash.present? || session.key?('flash'))
diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb
index 9cde9c9b98..18af0a583a 100644
--- a/actionpack/lib/action_dispatch/middleware/params_parser.rb
+++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb
@@ -18,48 +18,13 @@ module ActionDispatch
end
end
- DEFAULT_PARSERS = {
- Mime::JSON => lambda { |raw_post|
- data = ActiveSupport::JSON.decode(raw_post)
- data = {:_json => data} unless data.is_a?(Hash)
- Request::Utils.normalize_encode_params(data)
- }
- }
-
# Create a new +ParamsParser+ middleware instance.
#
# The +parsers+ argument can take Hash of parsers where key is identifying
# content mime type, and value is a lambda that is going to process data.
- def initialize(app, parsers = {})
- @app, @parsers = app, DEFAULT_PARSERS.merge(parsers)
+ def self.new(app, parsers = {})
+ ActionDispatch::Request.parameter_parsers = ActionDispatch::Request::DEFAULT_PARSERS.merge(parsers)
+ app
end
-
- def call(env)
- request = Request.new(env)
-
- parse_formatted_parameters(request, @parsers) do |params|
- request.request_parameters = params
- end
-
- @app.call(env)
- end
-
- private
- def parse_formatted_parameters(request, parsers)
- return if request.content_length.zero?
-
- strategy = parsers.fetch(request.content_mime_type) { return nil }
-
- yield strategy.call(request.raw_post)
-
- rescue => e # JSON or Ruby code block errors
- logger(request).debug "Error occurred while parsing request parameters.\nContents:\n\n#{request.raw_post}"
-
- raise ParseError.new(e.message, e)
- end
-
- def logger(request)
- request.logger || ActiveSupport::Logger.new($stderr)
- end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
index 3f7011d100..02b6cfe727 100644
--- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
@@ -53,7 +53,7 @@ module ActionDispatch
#
# Note that changing the secret key will invalidate all existing sessions!
#
- # Because CookieStore extends Rack::Session::Abstract::ID, many of the
+ # Because CookieStore extends Rack::Session::Abstract::Persisted, many of the
# options described there can be used to customize the session cookie that
# is generated. For example:
#
diff --git a/actionpack/lib/action_dispatch/middleware/ssl.rb b/actionpack/lib/action_dispatch/middleware/ssl.rb
index b72953f1d1..47f475559a 100644
--- a/actionpack/lib/action_dispatch/middleware/ssl.rb
+++ b/actionpack/lib/action_dispatch/middleware/ssl.rb
@@ -15,7 +15,8 @@ module ActionDispatch
#
# Configure HSTS with `hsts: { … }`:
# * `expires`: How long, in seconds, these settings will stick. Defaults to
- # `18.weeks`, the minimum required to qualify for browser preload lists.
+ # `180.days` (recommended). The minimum required to qualify for browser
+ # preload lists is `18.weeks`.
# * `subdomains`: Set to `true` to tell the browser to apply these settings
# to all subdomains. This protects your cookies from interception by a
# vulnerable site on a subdomain. Defaults to `false`.
diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb
index 8757c9ea7f..f3c6be864f 100644
--- a/actionpack/lib/action_dispatch/routing.rb
+++ b/actionpack/lib/action_dispatch/routing.rb
@@ -1,5 +1,3 @@
-# encoding: UTF-8
-
module ActionDispatch
# The routing module provides URL rewriting in native Ruby. It's a way to
# redirect incoming requests to controllers and actions. This replaces
@@ -148,6 +146,7 @@ module ActionDispatch
# get 'geocode/:postalcode' => :show, constraints: {
# postalcode: /\d{5}(-\d{4})?/
# }
+ # end
#
# Constraints can include the 'ignorecase' and 'extended syntax' regular
# expression modifiers:
diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb
index 967bbd62f8..883cd9c2c3 100644
--- a/actionpack/lib/action_dispatch/routing/url_for.rb
+++ b/actionpack/lib/action_dispatch/routing/url_for.rb
@@ -180,7 +180,8 @@ module ActionDispatch
when Symbol
HelperMethodBuilder.url.handle_string_call self, options
when Array
- polymorphic_url(options, options.extract_options!)
+ components = options.dup
+ polymorphic_url(components, components.extract_options!)
when Class
HelperMethodBuilder.url.handle_class_call self, options
else
diff --git a/actionpack/lib/action_dispatch/testing/assertions.rb b/actionpack/lib/action_dispatch/testing/assertions.rb
index 21b3b89d22..81fa10a613 100644
--- a/actionpack/lib/action_dispatch/testing/assertions.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions.rb
@@ -12,7 +12,7 @@ module ActionDispatch
include Rails::Dom::Testing::Assertions
def html_document
- @html_document ||= if @response.content_type === Mime::XML
+ @html_document ||= if @response.content_type === Mime::Type[:XML]
Nokogiri::XML::Document.parse(@response.body)
else
Nokogiri::HTML::Document.parse(@response.body)
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 4dfd4f3f71..753cd2073b 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -354,7 +354,7 @@ module ActionDispatch
if xhr
headers ||= {}
headers['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
- headers['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
+ headers['HTTP_ACCEPT'] ||= [Mime::Type[:JS], Mime::Type[:HTML], Mime::Type[:XML], 'text/xml', Mime::Type[:ALL]].join(', ')
end
# this modifies the passed request_env directly
diff --git a/actionpack/lib/action_dispatch/testing/test_response.rb b/actionpack/lib/action_dispatch/testing/test_response.rb
index 6a31d6243f..4b79a90242 100644
--- a/actionpack/lib/action_dispatch/testing/test_response.rb
+++ b/actionpack/lib/action_dispatch/testing/test_response.rb
@@ -7,7 +7,7 @@ module ActionDispatch
# See Response for more information on controller response objects.
class TestResponse < Response
def self.from_response(response)
- new response.status, response.headers, response.body, default_headers: nil
+ new response.status, response.headers, response.body
end
# Was the response successful?
diff --git a/actionpack/test/abstract/collector_test.rb b/actionpack/test/abstract/collector_test.rb
index fc59bf19c4..3b36e43c0b 100644
--- a/actionpack/test/abstract/collector_test.rb
+++ b/actionpack/test/abstract/collector_test.rb
@@ -53,9 +53,9 @@ module AbstractController
collector.html
collector.text(:foo)
collector.js(:bar) { :baz }
- assert_equal [Mime::HTML, [], nil], collector.responses[0]
- assert_equal [Mime::TEXT, [:foo], nil], collector.responses[1]
- assert_equal [Mime::JS, [:bar]], collector.responses[2][0,2]
+ assert_equal [Mime::Type[:HTML], [], nil], collector.responses[0]
+ assert_equal [Mime::Type[:TEXT], [:foo], nil], collector.responses[1]
+ assert_equal [Mime::Type[:JS], [:bar]], collector.responses[2][0,2]
assert_equal :baz, collector.responses[2][2].call
end
end
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 3c498960e4..ef7aab72c6 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -104,7 +104,6 @@ class ActionDispatch::IntegrationTest < ActiveSupport::TestCase
middleware.use ActionDispatch::ShowExceptions, ActionDispatch::PublicExceptions.new("#{FIXTURE_LOAD_PATH}/public")
middleware.use ActionDispatch::DebugExceptions
middleware.use ActionDispatch::Callbacks
- middleware.use ActionDispatch::ParamsParser
middleware.use ActionDispatch::Cookies
middleware.use ActionDispatch::Flash
middleware.use Rack::Head
diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb
index beeafc2e53..7dfeadceb0 100644
--- a/actionpack/test/controller/action_pack_assertions_test.rb
+++ b/actionpack/test/controller/action_pack_assertions_test.rb
@@ -65,7 +65,7 @@ class ActionPackAssertionsController < ActionController::Base
end
def render_text_with_custom_content_type
- render body: "Hello!", content_type: Mime::RSS
+ render body: "Hello!", content_type: Mime::Type[:RSS]
end
def session_stuffing
diff --git a/actionpack/test/controller/content_type_test.rb b/actionpack/test/controller/content_type_test.rb
index c5bbc479c9..4a86f1bad3 100644
--- a/actionpack/test/controller/content_type_test.rb
+++ b/actionpack/test/controller/content_type_test.rb
@@ -3,7 +3,7 @@ require 'abstract_unit'
class OldContentTypeController < ActionController::Base
# :ported:
def render_content_type_from_body
- response.content_type = Mime::RSS
+ response.content_type = Mime::Type[:RSS]
render body: "hello world!"
end
@@ -14,7 +14,7 @@ class OldContentTypeController < ActionController::Base
# :ported:
def render_content_type_from_render
- render body: "hello world!", :content_type => Mime::RSS
+ render body: "hello world!", :content_type => Mime::Type[:RSS]
end
# :ported:
@@ -36,7 +36,7 @@ class OldContentTypeController < ActionController::Base
end
def render_change_for_builder
- response.content_type = Mime::HTML
+ response.content_type = Mime::Type[:HTML]
render :action => "render_default_for_builder"
end
@@ -45,7 +45,7 @@ class OldContentTypeController < ActionController::Base
format.html { render body: "hello world!" }
format.xml { render action: "render_default_content_types_for_respond_to" }
format.js { render body: "hello world!" }
- format.rss { render body: "hello world!", content_type: Mime::XML }
+ format.rss { render body: "hello world!", content_type: Mime::Type[:XML] }
end
end
end
@@ -64,68 +64,68 @@ class ContentTypeTest < ActionController::TestCase
def test_render_defaults
get :render_defaults
assert_equal "utf-8", @response.charset
- assert_equal Mime::TEXT, @response.content_type
+ assert_equal Mime::Type[:TEXT], @response.content_type
end
def test_render_changed_charset_default
with_default_charset "utf-16" do
get :render_defaults
assert_equal "utf-16", @response.charset
- assert_equal Mime::TEXT, @response.content_type
+ assert_equal Mime::Type[:TEXT], @response.content_type
end
end
# :ported:
def test_content_type_from_body
get :render_content_type_from_body
- assert_equal Mime::RSS, @response.content_type
+ assert_equal Mime::Type[:RSS], @response.content_type
assert_equal "utf-8", @response.charset
end
# :ported:
def test_content_type_from_render
get :render_content_type_from_render
- assert_equal Mime::RSS, @response.content_type
+ assert_equal Mime::Type[:RSS], @response.content_type
assert_equal "utf-8", @response.charset
end
# :ported:
def test_charset_from_body
get :render_charset_from_body
- assert_equal Mime::TEXT, @response.content_type
+ assert_equal Mime::Type[:TEXT], @response.content_type
assert_equal "utf-16", @response.charset
end
# :ported:
def test_nil_charset_from_body
get :render_nil_charset_from_body
- assert_equal Mime::TEXT, @response.content_type
+ assert_equal Mime::Type[:TEXT], @response.content_type
assert_equal "utf-8", @response.charset, @response.headers.inspect
end
def test_nil_default_for_erb
with_default_charset nil do
get :render_default_for_erb
- assert_equal Mime::HTML, @response.content_type
+ assert_equal Mime::Type[:HTML], @response.content_type
assert_nil @response.charset, @response.headers.inspect
end
end
def test_default_for_erb
get :render_default_for_erb
- assert_equal Mime::HTML, @response.content_type
+ assert_equal Mime::Type[:HTML], @response.content_type
assert_equal "utf-8", @response.charset
end
def test_default_for_builder
get :render_default_for_builder
- assert_equal Mime::XML, @response.content_type
+ assert_equal Mime::Type[:XML], @response.content_type
assert_equal "utf-8", @response.charset
end
def test_change_for_builder
get :render_change_for_builder
- assert_equal Mime::HTML, @response.content_type
+ assert_equal Mime::Type[:HTML], @response.content_type
assert_equal "utf-8", @response.charset
end
@@ -144,24 +144,24 @@ class AcceptBasedContentTypeTest < ActionController::TestCase
tests OldContentTypeController
def test_render_default_content_types_for_respond_to
- @request.accept = Mime::HTML.to_s
+ @request.accept = Mime::Type[:HTML].to_s
get :render_default_content_types_for_respond_to
- assert_equal Mime::HTML, @response.content_type
+ assert_equal Mime::Type[:HTML], @response.content_type
- @request.accept = Mime::JS.to_s
+ @request.accept = Mime::Type[:JS].to_s
get :render_default_content_types_for_respond_to
- assert_equal Mime::JS, @response.content_type
+ assert_equal Mime::Type[:JS], @response.content_type
end
def test_render_default_content_types_for_respond_to_with_template
- @request.accept = Mime::XML.to_s
+ @request.accept = Mime::Type[:XML].to_s
get :render_default_content_types_for_respond_to
- assert_equal Mime::XML, @response.content_type
+ assert_equal Mime::Type[:XML], @response.content_type
end
def test_render_default_content_types_for_respond_to_with_overwrite
- @request.accept = Mime::RSS.to_s
+ @request.accept = Mime::Type[:RSS].to_s
get :render_default_content_types_for_respond_to
- assert_equal Mime::XML, @response.content_type
+ assert_equal Mime::Type[:XML], @response.content_type
end
end
diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb
index e9c19b7acf..4d1c23cbee 100644
--- a/actionpack/test/controller/live_stream_test.rb
+++ b/actionpack/test/controller/live_stream_test.rb
@@ -112,7 +112,7 @@ module ActionController
class TestController < ActionController::Base
include ActionController::Live
- attr_accessor :latch, :tc
+ attr_accessor :latch, :tc, :error_latch
def self.controller_path
'test'
@@ -204,6 +204,12 @@ module ActionController
end
def overfill_buffer_and_die
+ logger = ActionController::Base.logger || Logger.new($stdout)
+ response.stream.on_error do
+ logger.warn 'Error while streaming'
+ error_latch.count_down
+ end
+
# Write until the buffer is full. It doesn't expose that
# information directly, so we must hard-code its size:
10.times do
@@ -256,20 +262,12 @@ module ActionController
end
def test_set_cookie
- @controller = TestController.new
get :set_cookie
assert_equal({'hello' => 'world'}, @response.cookies)
assert_equal "hello world", @response.body
end
- def test_set_response!
- @controller.set_response!(@request)
- assert_kind_of(Live::Response, @controller.response)
- assert_equal @request, @controller.response.request
- end
-
def test_write_to_stream
- @controller = TestController.new
get :basic_stream
assert_equal "helloworld", @response.body
assert_equal 'text/event-stream', @response.headers['Content-Type']
@@ -281,10 +279,9 @@ module ActionController
@controller.latch = Concurrent::CountDownLatch.new
parts = ['hello', 'world']
- @controller.request = @request
- @controller.response = @response
+ get :blocking_stream
- t = Thread.new(@response) { |resp|
+ t = Thread.new(response) { |resp|
resp.await_commit
resp.stream.each do |part|
assert_equal parts.shift, part
@@ -294,38 +291,28 @@ module ActionController
end
}
- @controller.process :blocking_stream
-
assert t.join(3), 'timeout expired before the thread terminated'
end
def test_abort_with_full_buffer
@controller.latch = Concurrent::CountDownLatch.new
-
- @request.parameters[:format] = 'plain'
- @controller.request = @request
- @controller.response = @response
-
- got_error = Concurrent::CountDownLatch.new
- @response.stream.on_error do
- ActionController::Base.logger.warn 'Error while streaming'
- got_error.count_down
- end
-
- t = Thread.new(@response) { |resp|
- resp.await_commit
- _, _, body = resp.to_a
- body.each do
- @controller.latch.wait
- body.close
- break
- end
- }
+ @controller.error_latch = Concurrent::CountDownLatch.new
capture_log_output do |output|
- @controller.process :overfill_buffer_and_die
+ get :overfill_buffer_and_die, :format => 'plain'
+
+ t = Thread.new(response) { |resp|
+ resp.await_commit
+ _, _, body = resp.to_a
+ body.each do
+ @controller.latch.wait
+ body.close
+ break
+ end
+ }
+
t.join
- got_error.wait
+ @controller.error_latch.wait
assert_match 'Error while streaming', output.rewind && output.read
end
end
@@ -333,20 +320,18 @@ module ActionController
def test_ignore_client_disconnect
@controller.latch = Concurrent::CountDownLatch.new
- @controller.request = @request
- @controller.response = @response
+ capture_log_output do |output|
+ get :ignore_client_disconnect
- t = Thread.new(@response) { |resp|
- resp.await_commit
- _, _, body = resp.to_a
- body.each do
- body.close
- break
- end
- }
+ t = Thread.new(response) { |resp|
+ resp.await_commit
+ _, _, body = resp.to_a
+ body.each do
+ body.close
+ break
+ end
+ }
- capture_log_output do |output|
- @controller.process :ignore_client_disconnect
t.join
Timeout.timeout(3) do
@controller.latch.wait
@@ -364,11 +349,8 @@ module ActionController
end
def test_live_stream_default_header
- @controller.request = @request
- @controller.response = @response
- @controller.process :default_header
- _, headers, _ = @response.prepare!
- assert headers['Content-Type']
+ get :default_header
+ assert response.headers['Content-Type']
end
def test_render_text
@@ -437,13 +419,13 @@ module ActionController
def test_stale_without_etag
get :with_stale
- assert_equal 200, @response.status.to_i
+ assert_equal 200, response.status.to_i
end
def test_stale_with_etag
@request.if_none_match = Digest::MD5.hexdigest("123")
get :with_stale
- assert_equal 304, @response.status.to_i
+ assert_equal 304, response.status.to_i
end
end
diff --git a/actionpack/test/controller/new_base/content_type_test.rb b/actionpack/test/controller/new_base/content_type_test.rb
index 0445a837ca..d9899fe01f 100644
--- a/actionpack/test/controller/new_base/content_type_test.rb
+++ b/actionpack/test/controller/new_base/content_type_test.rb
@@ -7,12 +7,12 @@ module ContentType
end
def set_on_response_obj
- response.content_type = Mime::RSS
+ response.content_type = Mime::Type[:RSS]
render body: "Hello world!"
end
def set_on_render
- render body: "Hello world!", content_type: Mime::RSS
+ render body: "Hello world!", content_type: Mime::Type[:RSS]
end
end
diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb
index 91b30ede6a..631ff7d02a 100644
--- a/actionpack/test/controller/redirect_test.rb
+++ b/actionpack/test/controller/redirect_test.rb
@@ -266,15 +266,17 @@ class RedirectTest < ActionController::TestCase
end
def test_redirect_to_nil
- assert_raise(ActionController::ActionControllerError) do
+ error = assert_raise(ActionController::ActionControllerError) do
get :redirect_to_nil
end
+ assert_equal "Cannot redirect to nil!", error.message
end
def test_redirect_to_params
- assert_raise(ActionController::ActionControllerError) do
+ error = assert_raise(ActionController::ActionControllerError) do
get :redirect_to_params
end
+ assert_equal "Cannot redirect to a parameter hash!", error.message
end
def test_redirect_to_with_block
diff --git a/actionpack/test/controller/render_other_test.rb b/actionpack/test/controller/render_other_test.rb
index af50e11261..8891f6177f 100644
--- a/actionpack/test/controller/render_other_test.rb
+++ b/actionpack/test/controller/render_other_test.rb
@@ -12,7 +12,7 @@ class RenderOtherTest < ActionController::TestCase
def test_using_custom_render_option
ActionController.add_renderer :simon do |says, options|
- self.content_type = Mime::TEXT
+ self.content_type = Mime::Type[:TEXT]
self.response_body = "Simon says: #{says}"
end
diff --git a/actionpack/test/controller/render_xml_test.rb b/actionpack/test/controller/render_xml_test.rb
index 7a91577b17..094d3ea1d2 100644
--- a/actionpack/test/controller/render_xml_test.rb
+++ b/actionpack/test/controller/render_xml_test.rb
@@ -92,6 +92,6 @@ class RenderXmlTest < ActionController::TestCase
def test_should_use_implicit_content_type
get :implicit_content_type, format: 'atom'
- assert_equal Mime::ATOM, @response.content_type
+ assert_equal Mime::Type[:ATOM], @response.content_type
end
end
diff --git a/actionpack/test/controller/renderer_test.rb b/actionpack/test/controller/renderer_test.rb
index b55a25430b..16d24fa82a 100644
--- a/actionpack/test/controller/renderer_test.rb
+++ b/actionpack/test/controller/renderer_test.rb
@@ -1,6 +1,10 @@
require 'abstract_unit'
class RendererTest < ActiveSupport::TestCase
+ test 'action controller base has a renderer' do
+ assert ActionController::Base.renderer
+ end
+
test 'creating with a controller' do
controller = CommentsController
renderer = ActionController::Renderer.for controller
@@ -57,8 +61,7 @@ class RendererTest < ActiveSupport::TestCase
end
test 'rendering with defaults' do
- renderer = ApplicationController.renderer
- renderer.defaults[:https] = true
+ renderer = ApplicationController.renderer.new https: true
content = renderer.render inline: '<%= request.ssl? %>'
assert_equal 'true', content
@@ -67,8 +70,8 @@ class RendererTest < ActiveSupport::TestCase
test 'same defaults from the same controller' do
renderer_defaults = ->(controller) { controller.renderer.defaults }
- assert renderer_defaults[AccountsController].equal? renderer_defaults[AccountsController]
- assert_not renderer_defaults[AccountsController].equal? renderer_defaults[CommentsController]
+ assert_equal renderer_defaults[AccountsController], renderer_defaults[AccountsController]
+ assert_equal renderer_defaults[AccountsController], renderer_defaults[CommentsController]
end
test 'rendering with different formats' do
@@ -83,18 +86,6 @@ class RendererTest < ActiveSupport::TestCase
test 'rendering with helpers' do
assert_equal "<p>1\n<br />2</p>", render[inline: '<%= simple_format "1\n2" %>']
end
-
- test 'rendering from inherited renderer' do
- inherited = Class.new ApplicationController.renderer do
- defaults[:script_name] = 'script'
- def render(options)
- super options.merge(locals: { param: :value })
- end
- end
-
- template = '<%= url_for controller: :foo, action: :bar, param: param %>'
- assert_equal 'script/foo/bar?param=value', inherited.render(inline: template)
- end
private
def render
diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb
index c0ddcf7f50..c712c75c88 100644
--- a/actionpack/test/controller/send_file_test.rb
+++ b/actionpack/test/controller/send_file_test.rb
@@ -20,6 +20,47 @@ class SendFileController < ActionController::Base
send_file(file_path, options)
end
+ def test_send_file_headers_bang
+ options = {
+ :type => Mime::Type[:PNG],
+ :disposition => 'disposition',
+ :filename => 'filename'
+ }
+
+ send_data "foo", options
+ end
+
+ def test_send_file_headers_with_disposition_as_a_symbol
+ options = {
+ :type => Mime::Type[:PNG],
+ :disposition => :disposition,
+ :filename => 'filename'
+ }
+
+ send_data "foo", options
+ end
+
+ def test_send_file_headers_with_mime_lookup_with_symbol
+ options = { :type => :png }
+
+ send_data "foo", options
+ end
+
+ def test_send_file_headers_with_bad_symbol
+ options = { :type => :this_type_is_not_registered }
+ send_data "foo", options
+ end
+
+ def test_send_file_headers_with_nil_content_type
+ options = { :type => nil }
+ send_data "foo", options
+ end
+
+ def test_send_file_headers_guess_type_from_extension
+ options = { :filename => params[:filename] }
+ send_data "foo", options
+ end
+
def data
send_data(file_data, options)
end
@@ -88,62 +129,39 @@ class SendFileTest < ActionController::TestCase
# Test that send_file_headers! is setting the correct HTTP headers.
def test_send_file_headers_bang
- options = {
- :type => Mime::PNG,
- :disposition => 'disposition',
- :filename => 'filename'
- }
-
# Do it a few times: the resulting headers should be identical
# no matter how many times you send with the same options.
# Test resolving Ticket #458.
- @controller.headers = {}
- @controller.send(:send_file_headers!, options)
- @controller.send(:send_file_headers!, options)
- @controller.send(:send_file_headers!, options)
-
- h = @controller.headers
- assert_equal 'image/png', @controller.content_type
- assert_equal 'disposition; filename="filename"', h['Content-Disposition']
- assert_equal 'binary', h['Content-Transfer-Encoding']
+ 5.times do
+ get :test_send_file_headers_bang
- # test overriding Cache-Control: no-cache header to fix IE open/save dialog
- @controller.send(:send_file_headers!, options)
- @controller.response.prepare!
- assert_equal 'private', h['Cache-Control']
+ assert_equal 'image/png', response.content_type
+ assert_equal 'disposition; filename="filename"', response.get_header('Content-Disposition')
+ assert_equal 'binary', response.get_header('Content-Transfer-Encoding')
+ assert_equal 'private', response.get_header('Cache-Control')
+ end
end
def test_send_file_headers_with_disposition_as_a_symbol
- options = {
- :type => Mime::PNG,
- :disposition => :disposition,
- :filename => 'filename'
- }
+ get :test_send_file_headers_with_disposition_as_a_symbol
- @controller.headers = {}
- @controller.send(:send_file_headers!, options)
- assert_equal 'disposition; filename="filename"', @controller.headers['Content-Disposition']
+ assert_equal 'disposition; filename="filename"', response.get_header('Content-Disposition')
end
def test_send_file_headers_with_mime_lookup_with_symbol
- options = {
- :type => :png
- }
-
- @controller.headers = {}
- @controller.send(:send_file_headers!, options)
-
- assert_equal 'image/png', @controller.content_type
+ get __method__
+ assert_equal 'image/png', response.content_type
end
def test_send_file_headers_with_bad_symbol
- options = {
- :type => :this_type_is_not_registered
- }
+ error = assert_raise(ArgumentError) { get __method__ }
+ assert_equal "Unknown MIME type this_type_is_not_registered", error.message
+ end
- @controller.headers = {}
- assert_raise(ArgumentError) { @controller.send(:send_file_headers!, options) }
+ def test_send_file_headers_with_nil_content_type
+ error = assert_raise(ArgumentError) { get __method__ }
+ assert_equal ":type option required", error.message
end
def test_send_file_headers_guess_type_from_extension
@@ -158,10 +176,8 @@ class SendFileTest < ActionController::TestCase
'file.unk' => 'application/octet-stream',
'zip' => 'application/octet-stream'
}.each do |filename,expected_type|
- options = { :filename => filename }
- @controller.headers = {}
- @controller.send(:send_file_headers!, options)
- assert_equal expected_type, @controller.content_type
+ get __method__, params: { filename: filename }
+ assert_equal expected_type, response.content_type
end
end
diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb
index b3c3979c84..40c97abd35 100644
--- a/actionpack/test/controller/test_case_test.rb
+++ b/actionpack/test/controller/test_case_test.rb
@@ -627,6 +627,31 @@ XML
assert_equal "application/json", parsed_env["CONTENT_TYPE"]
end
+ def test_mutating_content_type_headers_for_plain_text_files_sets_the_header
+ @request.headers['Content-Type'] = 'text/plain'
+ post :render_body, params: { name: 'foo.txt' }
+
+ assert_equal 'text/plain', @request.headers['Content-type']
+ assert_equal 'foo.txt', @request.request_parameters[:name]
+ assert_equal 'render_body', @request.path_parameters[:action]
+ end
+
+ def test_mutating_content_type_headers_for_html_files_sets_the_header
+ @request.headers['Content-Type'] = 'text/html'
+ post :render_body, params: { name: 'foo.html' }
+
+ assert_equal 'text/html', @request.headers['Content-type']
+ assert_equal 'foo.html', @request.request_parameters[:name]
+ assert_equal 'render_body', @request.path_parameters[:action]
+ end
+
+ def test_mutating_content_type_headers_for_non_registered_mime_type_raises_an_error
+ assert_raises(RuntimeError) do
+ @request.headers['Content-Type'] = 'type/fake'
+ post :render_body, params: { name: 'foo.fake' }
+ end
+ end
+
def test_id_converted_to_string
get :test_params, params: {
id: 20, foo: Object.new
@@ -949,6 +974,11 @@ class ResponseDefaultHeadersTest < ActionController::TestCase
headers.delete params[:header]
head :ok, 'C' => '3'
end
+
+ # Render a head response, but don't touch default headers
+ def leave_alone
+ head :ok
+ end
end
def before_setup
@@ -974,9 +1004,13 @@ class ResponseDefaultHeadersTest < ActionController::TestCase
end
test "response contains default headers" do
+ get :leave_alone
+
# Response headers start out with the defaults
- assert_equal @defaults, response.headers
+ assert_equal @defaults.merge('Content-Type' => 'text/html'), response.headers
+ end
+ test "response deletes a default header" do
get :remove_header, params: { header: 'A' }
assert_response :ok
diff --git a/actionpack/test/controller/url_for_test.rb b/actionpack/test/controller/url_for_test.rb
index 31677f202d..78e883f134 100644
--- a/actionpack/test/controller/url_for_test.rb
+++ b/actionpack/test/controller/url_for_test.rb
@@ -451,6 +451,26 @@ module AbstractController
end
end
+ def test_url_for_with_array_is_unmodified
+ with_routing do |set|
+ set.draw do
+ namespace :admin do
+ resources :posts
+ end
+ end
+
+ kls = Class.new { include set.url_helpers }
+ kls.default_url_options[:host] = 'www.basecamphq.com'
+
+ original_components = [:new, :admin, :post, { param: 'value' }]
+ components = original_components.dup
+
+ kls.new.url_for(components)
+
+ assert_equal(original_components, components)
+ end
+ end
+
private
def extract_params(url)
url.split('?', 2).last.split('&').sort
diff --git a/actionpack/test/controller/webservice_test.rb b/actionpack/test/controller/webservice_test.rb
index b26f037c36..2aee914a24 100644
--- a/actionpack/test/controller/webservice_test.rb
+++ b/actionpack/test/controller/webservice_test.rb
@@ -65,7 +65,7 @@ class WebServiceTest < ActionDispatch::IntegrationTest
def test_register_and_use_json_simple
with_test_route_set do
- with_params_parsers Mime::JSON => Proc.new { |data| ActiveSupport::JSON.decode(data)['request'].with_indifferent_access } do
+ with_params_parsers Mime::Type[:JSON] => Proc.new { |data| ActiveSupport::JSON.decode(data)['request'].with_indifferent_access } do
post "/",
params: '{"request":{"summary":"content...","title":"JSON"}}',
headers: { 'CONTENT_TYPE' => 'application/json' }
@@ -97,24 +97,28 @@ class WebServiceTest < ActionDispatch::IntegrationTest
end
def test_parsing_json_doesnot_rescue_exception
- with_test_route_set do
- with_params_parsers Mime::JSON => Proc.new { |data| raise Interrupt } do
- assert_raises(Interrupt) do
- post "/",
- params: '{"title":"JSON"}}',
- headers: { 'CONTENT_TYPE' => 'application/json' }
- end
+ req = Class.new(ActionDispatch::Request) do
+ def params_parsers
+ { Mime::Type[:JSON] => Proc.new { |data| raise Interrupt } }
end
+
+ def content_length; get_header('rack.input').length; end
+ end.new({ 'rack.input' => StringIO.new('{"title":"JSON"}}'), 'CONTENT_TYPE' => 'application/json' })
+
+ assert_raises(Interrupt) do
+ req.request_parameters
end
end
private
def with_params_parsers(parsers = {})
old_session = @integration_session
- @app = ActionDispatch::ParamsParser.new(app.routes, parsers)
+ original_parsers = ActionDispatch::Request.parameter_parsers
+ ActionDispatch::Request.parameter_parsers = original_parsers.merge parsers
reset!
yield
ensure
+ ActionDispatch::Request.parameter_parsers = original_parsers
@integration_session = old_session
end
diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb
index 3017a9c2d6..d9fb44f06d 100644
--- a/actionpack/test/dispatch/mime_type_test.rb
+++ b/actionpack/test/dispatch/mime_type_test.rb
@@ -13,76 +13,75 @@ class MimeTypeTest < ActiveSupport::TestCase
test "unregister" do
begin
Mime::Type.register("text/x-mobile", :mobile)
- assert defined?(Mime::MOBILE)
- assert_equal Mime::MOBILE, Mime::LOOKUP['text/x-mobile']
- assert_equal Mime::MOBILE, Mime::EXTENSION_LOOKUP['mobile']
+ assert Mime::Type.registered?(:MOBILE)
+ assert_equal Mime::Type[:MOBILE], Mime::LOOKUP['text/x-mobile']
+ assert_equal Mime::Type[:MOBILE], Mime::EXTENSION_LOOKUP['mobile']
Mime::Type.unregister(:mobile)
- assert !defined?(Mime::MOBILE), "Mime::MOBILE should not be defined"
+ assert !Mime.const_defined?(:MOBILE), "Mime::MOBILE should not be defined"
assert !Mime::LOOKUP.has_key?('text/x-mobile'), "Mime::LOOKUP should not have key ['text/x-mobile]"
assert !Mime::EXTENSION_LOOKUP.has_key?('mobile'), "Mime::EXTENSION_LOOKUP should not have key ['mobile]"
ensure
- Mime.module_eval { remove_const :MOBILE if const_defined?(:MOBILE) }
Mime::LOOKUP.reject!{|key,_| key == 'text/x-mobile'}
end
end
test "parse text with trailing star at the beginning" do
accept = "text/*, text/html, application/json, multipart/form-data"
- expect = [Mime::HTML, Mime::TEXT, Mime::JS, Mime::CSS, Mime::ICS, Mime::CSV, Mime::VCF, Mime::XML, Mime::YAML, Mime::JSON, Mime::MULTIPART_FORM]
+ expect = [Mime::Type[:HTML], Mime::Type[:TEXT], Mime::Type[:JS], Mime::Type[:CSS], Mime::Type[:ICS], Mime::Type[:CSV], Mime::Type[:VCF], Mime::Type[:XML], Mime::Type[:YAML], Mime::Type[:JSON], Mime::Type[:MULTIPART_FORM]]
parsed = Mime::Type.parse(accept)
assert_equal expect, parsed
end
test "parse text with trailing star in the end" do
accept = "text/html, application/json, multipart/form-data, text/*"
- expect = [Mime::HTML, Mime::JSON, Mime::MULTIPART_FORM, Mime::TEXT, Mime::JS, Mime::CSS, Mime::ICS, Mime::CSV, Mime::VCF, Mime::XML, Mime::YAML]
+ expect = [Mime::Type[:HTML], Mime::Type[:JSON], Mime::Type[:MULTIPART_FORM], Mime::Type[:TEXT], Mime::Type[:JS], Mime::Type[:CSS], Mime::Type[:ICS], Mime::Type[:CSV], Mime::Type[:VCF], Mime::Type[:XML], Mime::Type[:YAML]]
parsed = Mime::Type.parse(accept)
assert_equal expect, parsed
end
test "parse text with trailing star" do
accept = "text/*"
- expect = [Mime::HTML, Mime::TEXT, Mime::JS, Mime::CSS, Mime::ICS, Mime::CSV, Mime::VCF, Mime::XML, Mime::YAML, Mime::JSON]
+ expect = [Mime::Type[:HTML], Mime::Type[:TEXT], Mime::Type[:JS], Mime::Type[:CSS], Mime::Type[:ICS], Mime::Type[:CSV], Mime::Type[:VCF], Mime::Type[:XML], Mime::Type[:YAML], Mime::Type[:JSON]]
parsed = Mime::Type.parse(accept)
assert_equal expect, parsed
end
test "parse application with trailing star" do
accept = "application/*"
- expect = [Mime::HTML, Mime::JS, Mime::XML, Mime::RSS, Mime::ATOM, Mime::YAML, Mime::URL_ENCODED_FORM, Mime::JSON, Mime::PDF, Mime::ZIP]
+ expect = [Mime::Type[:HTML], Mime::Type[:JS], Mime::Type[:XML], Mime::Type[:RSS], Mime::Type[:ATOM], Mime::Type[:YAML], Mime::Type[:URL_ENCODED_FORM], Mime::Type[:JSON], Mime::Type[:PDF], Mime::Type[:ZIP]]
parsed = Mime::Type.parse(accept)
assert_equal expect, parsed
end
test "parse without q" do
accept = "text/xml,application/xhtml+xml,text/yaml,application/xml,text/html,image/png,text/plain,application/pdf,*/*"
- expect = [Mime::HTML, Mime::XML, Mime::YAML, Mime::PNG, Mime::TEXT, Mime::PDF, Mime::ALL]
+ expect = [Mime::Type[:HTML], Mime::Type[:XML], Mime::Type[:YAML], Mime::Type[:PNG], Mime::Type[:TEXT], Mime::Type[:PDF], Mime::Type[:ALL]]
assert_equal expect, Mime::Type.parse(accept)
end
test "parse with q" do
accept = "text/xml,application/xhtml+xml,text/yaml; q=0.3,application/xml,text/html; q=0.8,image/png,text/plain; q=0.5,application/pdf,*/*; q=0.2"
- expect = [Mime::HTML, Mime::XML, Mime::PNG, Mime::PDF, Mime::TEXT, Mime::YAML, Mime::ALL]
+ expect = [Mime::Type[:HTML], Mime::Type[:XML], Mime::Type[:PNG], Mime::Type[:PDF], Mime::Type[:TEXT], Mime::Type[:YAML], Mime::Type[:ALL]]
assert_equal expect, Mime::Type.parse(accept)
end
test "parse single media range with q" do
accept = "text/html;q=0.9"
- expect = [Mime::HTML]
+ expect = [Mime::Type[:HTML]]
assert_equal expect, Mime::Type.parse(accept)
end
test "parse arbitrary media type parameters" do
accept = 'multipart/form-data; boundary="simple boundary"'
- expect = [Mime::MULTIPART_FORM]
+ expect = [Mime::Type[:MULTIPART_FORM]]
assert_equal expect, Mime::Type.parse(accept)
end
# Accept header send with user HTTP_USER_AGENT: Sunrise/0.42j (Windows XP)
test "parse broken acceptlines" do
accept = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/*,,*/*;q=0.5"
- expect = [Mime::HTML, Mime::XML, "image/*", Mime::TEXT, Mime::ALL]
+ expect = [Mime::Type[:HTML], Mime::Type[:XML], "image/*", Mime::Type[:TEXT], Mime::Type[:ALL]]
assert_equal expect, Mime::Type.parse(accept).collect(&:to_s)
end
@@ -90,16 +89,15 @@ class MimeTypeTest < ActiveSupport::TestCase
# (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; InfoPath.1)
test "parse other broken acceptlines" do
accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, , pronto/1.00.00, sslvpn/1.00.00.00, */*"
- expect = ['image/gif', 'image/x-xbitmap', 'image/jpeg','image/pjpeg', 'application/x-shockwave-flash', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/msword', 'pronto/1.00.00', 'sslvpn/1.00.00.00', Mime::ALL]
+ expect = ['image/gif', 'image/x-xbitmap', 'image/jpeg','image/pjpeg', 'application/x-shockwave-flash', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/msword', 'pronto/1.00.00', 'sslvpn/1.00.00.00', Mime::Type[:ALL]]
assert_equal expect, Mime::Type.parse(accept).collect(&:to_s)
end
test "custom type" do
begin
- Mime::Type.register("image/foo", :foo)
- assert_nothing_raised do
- assert_equal Mime::FOO, Mime::SET.last
- end
+ type = Mime::Type.register("image/foo", :foo)
+ assert_equal Mime::Type[:FOO], type
+ assert Mime::Type.registered?(:FOO)
ensure
Mime::Type.unregister(:FOO)
end
@@ -109,7 +107,7 @@ class MimeTypeTest < ActiveSupport::TestCase
begin
Mime::Type.register "text/foobar", :foobar, ["text/foo", "text/bar"]
%w[text/foobar text/foo text/bar].each do |type|
- assert_equal Mime::FOOBAR, type
+ assert_equal Mime::Type[:FOOBAR], type
end
ensure
Mime::Type.unregister(:FOOBAR)
@@ -124,7 +122,7 @@ class MimeTypeTest < ActiveSupport::TestCase
end
Mime::Type.register("text/foo", :foo)
- assert_equal [Mime::FOO], registered_mimes
+ assert_equal [Mime::Type[:FOO]], registered_mimes
ensure
Mime::Type.unregister(:FOO)
end
@@ -134,7 +132,7 @@ class MimeTypeTest < ActiveSupport::TestCase
begin
Mime::Type.register "text/foobar", :foobar, [], [:foo, "bar"]
%w[foobar foo bar].each do |extension|
- assert_equal Mime::FOOBAR, Mime::EXTENSION_LOOKUP[extension]
+ assert_equal Mime::Type[:FOOBAR], Mime::EXTENSION_LOOKUP[extension]
end
ensure
Mime::Type.unregister(:FOOBAR)
@@ -144,15 +142,15 @@ class MimeTypeTest < ActiveSupport::TestCase
test "register alias" do
begin
Mime::Type.register_alias "application/xhtml+xml", :foobar
- assert_equal Mime::HTML, Mime::EXTENSION_LOOKUP['foobar']
+ assert_equal Mime::Type[:HTML], Mime::EXTENSION_LOOKUP['foobar']
ensure
Mime::Type.unregister(:FOOBAR)
end
end
test "type should be equal to symbol" do
- assert_equal Mime::HTML, 'application/xhtml+xml'
- assert_equal Mime::HTML, :html
+ assert_equal Mime::Type[:HTML], 'application/xhtml+xml'
+ assert_equal Mime::Type[:HTML], :html
end
test "type convenience methods" do
@@ -160,44 +158,51 @@ class MimeTypeTest < ActiveSupport::TestCase
types = Mime::SET.symbols.uniq - [:all, :iphone]
# Remove custom Mime::Type instances set in other tests, like Mime::GIF and Mime::IPHONE
- types.delete_if { |type| !Mime.const_defined?(type.upcase) }
-
+ types.delete_if { |type| !Mime::Type.registered?(type.upcase) }
types.each do |type|
- mime = Mime.const_get(type.upcase)
+ mime = Mime::Type[type.upcase]
assert mime.respond_to?("#{type}?"), "#{mime.inspect} does not respond to #{type}?"
- assert mime.send("#{type}?"), "#{mime.inspect} is not #{type}?"
+ assert_equal type, mime.symbol, "#{mime.inspect} is not #{type}?"
invalid_types = types - [type]
- invalid_types.delete(:html) if Mime::Type.html_types.include?(type)
- invalid_types.each { |other_type| assert !mime.send("#{other_type}?"), "#{mime.inspect} is #{other_type}?" }
+ invalid_types.delete(:html)
+ invalid_types.each { |other_type|
+ assert_not_equal mime.symbol, other_type, "#{mime.inspect} is #{other_type}?"
+ }
end
end
test "mime all is html" do
- assert Mime::ALL.all?, "Mime::ALL is not all?"
- assert Mime::ALL.html?, "Mime::ALL is not html?"
+ assert Mime::Type[:ALL].all?, "Mime::ALL is not all?"
+ assert Mime::Type[:ALL].html?, "Mime::ALL is not html?"
+ end
+
+ test "deprecated lookup" do
+ assert_deprecated do
+ assert Mime::ALL.all?, "Mime::ALL is not all?"
+ end
end
test "verifiable mime types" do
all_types = Mime::SET.symbols
all_types.uniq!
# Remove custom Mime::Type instances set in other tests, like Mime::GIF and Mime::IPHONE
- all_types.delete_if { |type| !Mime.const_defined?(type.upcase) }
+ all_types.delete_if { |type| !Mime::Type.registered?(type.upcase) }
end
test "references gives preference to symbols before strings" do
- assert_equal :html, Mime::HTML.ref
+ assert_equal :html, Mime::Type[:HTML].ref
another = Mime::Type.lookup("foo/bar")
assert_nil another.to_sym
assert_equal "foo/bar", another.ref
end
test "regexp matcher" do
- assert Mime::JS =~ "text/javascript"
- assert Mime::JS =~ "application/javascript"
- assert Mime::JS !~ "text/html"
- assert !(Mime::JS !~ "text/javascript")
- assert !(Mime::JS !~ "application/javascript")
- assert Mime::HTML =~ 'application/xhtml+xml'
+ assert Mime::Type[:JS] =~ "text/javascript"
+ assert Mime::Type[:JS] =~ "application/javascript"
+ assert Mime::Type[:JS] !~ "text/html"
+ assert !(Mime::Type[:JS] !~ "text/javascript")
+ assert !(Mime::Type[:JS] !~ "application/javascript")
+ assert Mime::Type[:HTML] =~ 'application/xhtml+xml'
end
end
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index 258d097b7c..40866595ed 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -750,33 +750,33 @@ class RequestFormat < BaseRequestTest
test "xml format" do
request = stub_request
assert_called(request, :parameters, times: 2, returns: {format: :xml}) do
- assert_equal Mime::XML, request.format
+ assert_equal Mime::Type[:XML], request.format
end
end
test "xhtml format" do
request = stub_request
assert_called(request, :parameters, times: 2, returns: {format: :xhtml}) do
- assert_equal Mime::HTML, request.format
+ assert_equal Mime::Type[:HTML], request.format
end
end
test "txt format" do
request = stub_request
assert_called(request, :parameters, times: 2, returns: {format: :txt}) do
- assert_equal Mime::TEXT, request.format
+ assert_equal Mime::Type[:TEXT], request.format
end
end
test "XMLHttpRequest" do
request = stub_request(
'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest',
- 'HTTP_ACCEPT' => [Mime::JS, Mime::HTML, Mime::XML, "text/xml", Mime::ALL].join(",")
+ 'HTTP_ACCEPT' => [Mime::Type[:JS], Mime::Type[:HTML], Mime::Type[:XML], "text/xml", Mime::Type[:ALL]].join(",")
)
assert_called(request, :parameters, times: 1, returns: {}) do
assert request.xhr?
- assert_equal Mime::JS, request.format
+ assert_equal Mime::Type[:JS], request.format
end
end
@@ -796,29 +796,29 @@ class RequestFormat < BaseRequestTest
test "formats text/html with accept header" do
request = stub_request 'HTTP_ACCEPT' => 'text/html'
- assert_equal [Mime::HTML], request.formats
+ assert_equal [Mime::Type[:HTML]], request.formats
end
test "formats blank with accept header" do
request = stub_request 'HTTP_ACCEPT' => ''
- assert_equal [Mime::HTML], request.formats
+ assert_equal [Mime::Type[:HTML]], request.formats
end
test "formats XMLHttpRequest with accept header" do
request = stub_request 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
- assert_equal [Mime::JS], request.formats
+ assert_equal [Mime::Type[:JS]], request.formats
end
test "formats application/xml with accept header" do
request = stub_request('CONTENT_TYPE' => 'application/xml; charset=UTF-8',
'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest")
- assert_equal [Mime::XML], request.formats
+ assert_equal [Mime::Type[:XML]], request.formats
end
test "formats format:text with accept header" do
request = stub_request
assert_called(request, :parameters, times: 2, returns: {format: :txt}) do
- assert_equal [Mime::TEXT], request.formats
+ assert_equal [Mime::Type[:TEXT]], request.formats
end
end
@@ -848,7 +848,7 @@ class RequestFormat < BaseRequestTest
test "formats with xhr request" do
request = stub_request 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
assert_called(request, :parameters, times: 1, returns: {}) do
- assert_equal [Mime::JS], request.formats
+ assert_equal [Mime::Type[:JS]], request.formats
end
end
@@ -859,35 +859,35 @@ class RequestFormat < BaseRequestTest
begin
request = stub_request 'HTTP_ACCEPT' => 'application/xml'
assert_called(request, :parameters, times: 1, returns: {}) do
- assert_equal [ Mime::HTML ], request.formats
+ assert_equal [ Mime::Type[:HTML] ], request.formats
end
request = stub_request 'HTTP_ACCEPT' => 'koz-asked/something-crazy'
assert_called(request, :parameters, times: 1, returns: {}) do
- assert_equal [ Mime::HTML ], request.formats
+ assert_equal [ Mime::Type[:HTML] ], request.formats
end
request = stub_request 'HTTP_ACCEPT' => '*/*;q=0.1'
assert_called(request, :parameters, times: 1, returns: {}) do
- assert_equal [ Mime::HTML ], request.formats
+ assert_equal [ Mime::Type[:HTML] ], request.formats
end
request = stub_request 'HTTP_ACCEPT' => 'application/jxw'
assert_called(request, :parameters, times: 1, returns: {}) do
- assert_equal [ Mime::HTML ], request.formats
+ assert_equal [ Mime::Type[:HTML] ], request.formats
end
request = stub_request 'HTTP_ACCEPT' => 'application/xml',
'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
assert_called(request, :parameters, times: 1, returns: {}) do
- assert_equal [ Mime::JS ], request.formats
+ assert_equal [ Mime::Type[:JS] ], request.formats
end
request = stub_request 'HTTP_ACCEPT' => 'application/xml',
'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
assert_called(request, :parameters, times: 2, returns: {format: :json}) do
- assert_equal [ Mime::JSON ], request.formats
+ assert_equal [ Mime::Type[:JSON] ], request.formats
end
ensure
ActionDispatch::Request.ignore_accept_header = old_ignore_accept_header
@@ -897,7 +897,7 @@ end
class RequestMimeType < BaseRequestTest
test "content type" do
- assert_equal Mime::HTML, stub_request('CONTENT_TYPE' => 'text/html').content_mime_type
+ assert_equal Mime::Type[:HTML], stub_request('CONTENT_TYPE' => 'text/html').content_mime_type
end
test "no content type" do
@@ -905,11 +905,11 @@ class RequestMimeType < BaseRequestTest
end
test "content type is XML" do
- assert_equal Mime::XML, stub_request('CONTENT_TYPE' => 'application/xml').content_mime_type
+ assert_equal Mime::Type[:XML], stub_request('CONTENT_TYPE' => 'application/xml').content_mime_type
end
test "content type with charset" do
- assert_equal Mime::XML, stub_request('CONTENT_TYPE' => 'application/xml; charset=UTF-8').content_mime_type
+ assert_equal Mime::Type[:XML], stub_request('CONTENT_TYPE' => 'application/xml; charset=UTF-8').content_mime_type
end
test "user agent" do
@@ -922,9 +922,9 @@ class RequestMimeType < BaseRequestTest
'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
)
- assert_equal nil, request.negotiate_mime([Mime::XML, Mime::JSON])
- assert_equal Mime::HTML, request.negotiate_mime([Mime::XML, Mime::HTML])
- assert_equal Mime::HTML, request.negotiate_mime([Mime::XML, Mime::ALL])
+ assert_equal nil, request.negotiate_mime([Mime::Type[:XML], Mime::Type[:JSON]])
+ assert_equal Mime::Type[:HTML], request.negotiate_mime([Mime::Type[:XML], Mime::Type[:HTML]])
+ assert_equal Mime::Type[:HTML], request.negotiate_mime([Mime::Type[:XML], Mime::Type[:ALL]])
end
test "negotiate_mime with content_type" do
@@ -933,7 +933,7 @@ class RequestMimeType < BaseRequestTest
'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
)
- assert_equal Mime::XML, request.negotiate_mime([Mime::XML, Mime::CSV])
+ assert_equal Mime::Type[:XML], request.negotiate_mime([Mime::Type[:XML], Mime::Type[:CSV]])
end
end
diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb
index 780e7dc3e2..85cdcda655 100644
--- a/actionpack/test/dispatch/response_test.rb
+++ b/actionpack/test/dispatch/response_test.rb
@@ -4,7 +4,7 @@ require 'rack/content_length'
class ResponseTest < ActiveSupport::TestCase
def setup
- @response = ActionDispatch::Response.new
+ @response = ActionDispatch::Response.create
end
def test_can_wait_until_commit
@@ -49,6 +49,11 @@ class ResponseTest < ActiveSupport::TestCase
assert_equal 'utf-8', @response.charset
end
+ def test_setting_content_type_header_impacts_content_type_method
+ @response.headers['Content-Type'] = "application/aaron"
+ assert_equal 'application/aaron', @response.content_type
+ end
+
test "simple output" do
@response.body = "Hello, World!"
@@ -67,6 +72,13 @@ class ResponseTest < ActiveSupport::TestCase
assert_equal 200, ActionDispatch::Response.new('200 OK').status
end
+ def test_only_set_charset_still_defaults_to_text_html
+ response = ActionDispatch::Response.new
+ response.charset = "utf-16"
+ _,headers,_ = response.to_a
+ assert_equal "text/html; charset=utf-16", headers['Content-Type']
+ end
+
test "utf8 output" do
@response.body = [1090, 1077, 1089, 1090].pack("U*")
@@ -137,12 +149,19 @@ class ResponseTest < ActiveSupport::TestCase
status, headers, body = @response.to_a
assert_equal "user_name=david; path=/", headers["Set-Cookie"]
assert_equal({"user_name" => "david"}, @response.cookies)
+ end
+ test "multiple cookies" do
+ @response.set_cookie("user_name", :value => "david", :path => "/")
@response.set_cookie("login", :value => "foo&bar", :path => "/", :expires => Time.utc(2005, 10, 10,5))
status, headers, body = @response.to_a
assert_equal "user_name=david; path=/\nlogin=foo%26bar; path=/; expires=Mon, 10 Oct 2005 05:00:00 -0000", headers["Set-Cookie"]
assert_equal({"login" => "foo&bar", "user_name" => "david"}, @response.cookies)
+ end
+ test "delete cookies" do
+ @response.set_cookie("user_name", :value => "david", :path => "/")
+ @response.set_cookie("login", :value => "foo&bar", :path => "/", :expires => Time.utc(2005, 10, 10,5))
@response.delete_cookie("login")
status, headers, body = @response.to_a
assert_equal({"user_name" => "david", "login" => nil}, @response.cookies)
@@ -166,13 +185,13 @@ class ResponseTest < ActiveSupport::TestCase
test "read charset and content type" do
resp = ActionDispatch::Response.new.tap { |response|
response.charset = 'utf-16'
- response.content_type = Mime::XML
+ response.content_type = Mime::Type[:XML]
response.body = 'Hello'
}
resp.to_a
assert_equal('utf-16', resp.charset)
- assert_equal(Mime::XML, resp.content_type)
+ assert_equal(Mime::Type[:XML], resp.content_type)
assert_equal('application/xml; charset=utf-16', resp.headers['Content-Type'])
end
@@ -198,7 +217,7 @@ class ResponseTest < ActiveSupport::TestCase
'X-Content-Type-Options' => 'nosniff',
'X-XSS-Protection' => '1;'
}
- resp = ActionDispatch::Response.new.tap { |response|
+ resp = ActionDispatch::Response.create.tap { |response|
response.body = 'Hello'
}
resp.to_a
@@ -217,7 +236,7 @@ class ResponseTest < ActiveSupport::TestCase
ActionDispatch::Response.default_headers = {
'X-XX-XXXX' => 'Here is my phone number'
}
- resp = ActionDispatch::Response.new.tap { |response|
+ resp = ActionDispatch::Response.create.tap { |response|
response.body = 'Hello'
}
resp.to_a
@@ -305,7 +324,7 @@ class ResponseIntegrationTest < ActionDispatch::IntegrationTest
@app = lambda { |env|
ActionDispatch::Response.new.tap { |resp|
resp.charset = 'utf-16'
- resp.content_type = Mime::XML
+ resp.content_type = Mime::Type[:XML]
resp.body = 'Hello'
}.to_a
}
@@ -314,7 +333,7 @@ class ResponseIntegrationTest < ActionDispatch::IntegrationTest
assert_response :success
assert_equal('utf-16', @response.charset)
- assert_equal(Mime::XML, @response.content_type)
+ assert_equal(Mime::Type[:XML], @response.content_type)
assert_equal('application/xml; charset=utf-16', @response.headers['Content-Type'])
end
@@ -330,7 +349,7 @@ class ResponseIntegrationTest < ActionDispatch::IntegrationTest
assert_response :success
assert_equal('utf-16', @response.charset)
- assert_equal(Mime::XML, @response.content_type)
+ assert_equal(Mime::Type[:XML], @response.content_type)
assert_equal('application/xml; charset=utf-16', @response.headers['Content-Type'])
end
diff --git a/actionpack/test/journey/router_test.rb b/actionpack/test/journey/router_test.rb
index d512dae4e7..6a3af32946 100644
--- a/actionpack/test/journey/router_test.rb
+++ b/actionpack/test/journey/router_test.rb
@@ -1,4 +1,3 @@
-# encoding: UTF-8
require 'abstract_unit'
module ActionDispatch