diff options
Diffstat (limited to 'actionpack')
42 files changed, 325 insertions, 299 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index bb15edee63..42b4f1d18b 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,19 @@ +* Allow multiple `root` routes in same scope level. Example: + + ```ruby + root 'blog#show', constraints: ->(req) { Hostname.blog_site?(req.host) } + root 'landing#show' + ``` + *Rafael Sales* + +* Fix regression in mounted engine named routes generation for app deployed to + a subdirectory. `relative_url_root` was prepended to the path twice (e.g. + "/subdir/subdir/engine_path" instead of "/subdir/engine_path") + + Fixes #20920. Fixes #21459. + + *Matthew Erhard* + * 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 @@ -10,12 +26,16 @@ To this: - Mime::Type[:HTML] + Mime[: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. + `Mime[:html]` is available in older versions of Rails, too, so you can + safely change libraries and plugins and maintain compatibility with + multiple versions of Rails. + * `url_for` does not modify its arguments when generating polymorphic URLs. *Bernerd Schaefer* diff --git a/actionpack/lib/abstract_controller/collector.rb b/actionpack/lib/abstract_controller/collector.rb index 3b5128cda5..55654be224 100644 --- a/actionpack/lib/abstract_controller/collector.rb +++ b/actionpack/lib/abstract_controller/collector.rb @@ -4,11 +4,10 @@ module AbstractController module Collector def self.generate_method_for_mime(mime) sym = mime.is_a?(Symbol) ? mime : mime.to_sym - const = sym.upcase class_eval <<-RUBY, __FILE__, __LINE__ + 1 - def #{sym}(*args, &block) # def html(*args, &block) - custom(Mime::Type[:#{const}], *args, &block) # custom(Mime::Type[:HTML], *args, &block) - end # end + def #{sym}(*args, &block) + custom(Mime[:#{sym}], *args, &block) + end RUBY end @@ -23,9 +22,7 @@ module AbstractController protected def method_missing(symbol, &block) - const_name = symbol.upcase - - unless Mime::Type.registered?(const_name) + unless mime_constant = Mime[symbol] 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,8 +30,6 @@ module AbstractController "format.html { |html| html.tablet { ... } }" end - mime_constant = Mime::Type[const_name] - if Mime::SET.include?(mime_constant) AbstractController::Collector.generate_method_for_mime(mime_constant) send(symbol, &block) diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index 78b43f2fbe..a73f188623 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -22,13 +22,13 @@ module AbstractController # :api: public def render(*args, &block) options = _normalize_render(*args, &block) - self.response_body = render_to_body(options) + rendered_body = render_to_body(options) if options[:html] _set_html_content_type else _set_rendered_content_type rendered_format end - self.response_body + self.response_body = rendered_body end # Raw rendering of a template to a string. @@ -55,7 +55,7 @@ module AbstractController # Returns Content-Type of rendered content # :api: public def rendered_format - Mime::Type[:TEXT] + Mime[:text] end DEFAULT_PROTECTED_INSTANCE_VARIABLES = Set.new %i( diff --git a/actionpack/lib/action_controller/metal.rb b/actionpack/lib/action_controller/metal.rb index beeaae9d0c..94ec62ec6f 100644 --- a/actionpack/lib/action_controller/metal.rb +++ b/actionpack/lib/action_controller/metal.rb @@ -174,7 +174,11 @@ module ActionController def response_body=(body) body = [body] unless body.nil? || body.respond_to?(:each) - response.body = body + response.reset_body! + body.each { |part| + next if part.empty? + response.write part + } super end diff --git a/actionpack/lib/action_controller/metal/data_streaming.rb b/actionpack/lib/action_controller/metal/data_streaming.rb index e6d7f958bb..957e7a3019 100644 --- a/actionpack/lib/action_controller/metal/data_streaming.rb +++ b/actionpack/lib/action_controller/metal/data_streaming.rb @@ -72,31 +72,7 @@ module ActionController #:nodoc: self.status = options[:status] || 200 self.content_type = options[:content_type] if options.key?(:content_type) - self.response_body = FileBody.new(path) - end - - # Avoid having to pass an open file handle as the response body. - # Rack::Sendfile will usually intercept the response and uses - # the path directly, so there is no reason to open the file. - class FileBody #:nodoc: - attr_reader :to_path - - def initialize(path) - @to_path = path - end - - def body - File.binread(to_path) - end - - # Stream the file's contents if Rack::Sendfile isn't present. - def each - File.open(to_path, 'rb') do |file| - while chunk = file.read(16384) - yield chunk - end - end - end + response.send_file path end # Sends the given binary data to the browser. This method is similar to diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index fe470552b0..0a36fecd27 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::Type[:XML], Mime::Type[:ATOM] + # when Mime[:xml], Mime[: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::Type[:XML], Mime::Type[:ATOM] + # when Mime[:xml], Mime[:atom] # if user = authenticate_with_http_token { |t, o| @account.users.authenticate(t, o) } # @current_user = user # else diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb index fc42fe5c07..58df5c539e 100644 --- a/actionpack/lib/action_controller/metal/mime_responds.rb +++ b/actionpack/lib/action_controller/metal/mime_responds.rb @@ -229,14 +229,14 @@ module ActionController #:nodoc: @responses = {} @variant = variant - mimes.each { |mime| @responses[Mime::Type[mime.upcase.to_sym]] = nil } + mimes.each { |mime| @responses[Mime[mime]] = nil } end def any(*args, &block) if args.any? args.each { |type| send(type, &block) } else - custom(Mime::Type[:ALL], &block) + custom(Mime::ALL, &block) end end alias :all :any @@ -251,7 +251,7 @@ module ActionController #:nodoc: end def response - response = @responses.fetch(format, @responses[Mime::Type[:ALL]]) + response = @responses.fetch(format, @responses[Mime::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/renderers.rb b/actionpack/lib/action_controller/metal/renderers.rb index d867c97b46..22e0bb5955 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::Type[:CSV], + # send_data str, type: Mime[:csv], # disposition: "attachment; filename=#{filename}.csv" # end # - # Note that we used Mime::Type[:CSV] for the csv mime type as it comes with Rails. + # Note that we used Mime[: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::Type[:JSON] - self.content_type = Mime::Type[:JS] + if content_type.nil? || content_type == Mime[:json] + self.content_type = Mime[:js] end "/**/#{options[:callback]}(#{json})" else - self.content_type ||= Mime::Type[:JSON] + self.content_type ||= Mime[:json] json end end add :js do |js, options| - self.content_type ||= Mime::Type[:JS] + self.content_type ||= Mime[:js] js.respond_to?(:to_js) ? js.to_js(options) : js end add :xml do |xml, options| - self.content_type ||= Mime::Type[:XML] + self.content_type ||= Mime[: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 1ecccf9864..172fbdf954 100644 --- a/actionpack/lib/action_controller/metal/rendering.rb +++ b/actionpack/lib/action_controller/metal/rendering.rb @@ -64,7 +64,7 @@ module ActionController end def _set_html_content_type - self.content_type = Mime::Type[:HTML].to_s + self.content_type = Mime[:html].to_s end def _set_rendered_content_type(format) diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index 5674eef67b..64f6f7cf51 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -90,8 +90,10 @@ module ActionController #:nodoc: # # class FooController < ApplicationController # protect_from_forgery except: :index + # end # # You can disable forgery protection on controller by skipping the verification before_action: + # # skip_before_action :verify_authenticity_token # # Valid Options: diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb index 903dba3eb4..130ba61786 100644 --- a/actionpack/lib/action_controller/metal/strong_parameters.rb +++ b/actionpack/lib/action_controller/metal/strong_parameters.rb @@ -540,7 +540,7 @@ module ActionController end alias_method :delete_if, :reject! - # Return values that were assigned to the given +keys+. Note that all the + # Returns values that were assigned to the given +keys+. Note that all the # +Hash+ objects will be converted to <tt>ActionController::Parameters</tt>. def values_at(*keys) convert_value_to_parameters(@parameters.values_at(*keys)) diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index cf78688126..380e9d29b4 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -34,7 +34,7 @@ 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'] } + Mime[:xml] => lambda { |raw_post| Hash.from_xml(raw_post)['hash'] } } end @@ -402,7 +402,7 @@ module ActionController MSG @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' - @request.env['HTTP_ACCEPT'] ||= [Mime::Type[:JS], Mime::Type[:HTML], Mime::Type[:XML], 'text/xml', Mime::Type[:ALL]].join(', ') + @request.env['HTTP_ACCEPT'] ||= [Mime[:js], Mime[:html], Mime[:xml], 'text/xml', '*/*'].join(', ') __send__(*args).tap do @request.env.delete 'HTTP_X_REQUESTED_WITH' @request.env.delete 'HTTP_ACCEPT' @@ -505,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::Type[:JS], Mime::Type[:HTML], Mime::Type[:XML], 'text/xml', Mime::Type[:ALL]].join(', ') + @request.set_header k, [Mime[:js], Mime[:html], Mime[:xml], 'text/xml', '*/*'].join(', ') end end diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb index 1d0a6b6eb3..30ade14c26 100644 --- a/actionpack/lib/action_dispatch/http/cache.rb +++ b/actionpack/lib/action_dispatch/http/cache.rb @@ -59,7 +59,7 @@ module ActionDispatch end def last_modified? - have_header? LAST_MODIFIED + has_header? LAST_MODIFIED end def last_modified=(utc_time) @@ -73,7 +73,7 @@ module ActionDispatch end def date? - have_header? DATE + has_header? DATE end def date=(utc_time) @@ -82,24 +82,19 @@ module ActionDispatch def etag=(etag) key = ActiveSupport::Cache.expand_cache_key(etag) - set_header ETAG, %("#{Digest::MD5.hexdigest(key)}") + super %("#{Digest::MD5.hexdigest(key)}") end - def etag - get_header ETAG - end - alias :etag? :etag + def etag?; etag; end private DATE = 'Date'.freeze LAST_MODIFIED = "Last-Modified".freeze - ETAG = "ETag".freeze - CACHE_CONTROL = "Cache-Control".freeze SPECIAL_KEYS = Set.new(%w[extras no-cache max-age public must-revalidate]) def cache_control_segments - if cache_control = get_header(CACHE_CONTROL) + if cache_control = _cache_control cache_control.delete(' ').split(',') else [] @@ -153,11 +148,11 @@ module ActionDispatch control.merge! cache_control if control.empty? - set_header CACHE_CONTROL, DEFAULT_CACHE_CONTROL + self._cache_control = DEFAULT_CACHE_CONTROL elsif control[:no_cache] - set_header CACHE_CONTROL, NO_CACHE + self._cache_control = NO_CACHE if control[:extras] - set_header(CACHE_CONTROL, get_header(CACHE_CONTROL) + ", #{control[:extras].join(', ')}") + self._cache_control = _cache_control + ", #{control[:extras].join(', ')}" end else extras = control[:extras] @@ -169,7 +164,7 @@ module ActionDispatch options << MUST_REVALIDATE if control[:must_revalidate] options.concat(extras) if extras - set_header CACHE_CONTROL, options.join(", ") + self._cache_control = options.join(", ") end end end diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb index 9c0f39f2e7..9dcab79c3a 100644 --- a/actionpack/lib/action_dispatch/http/filter_parameters.rb +++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb @@ -30,12 +30,12 @@ module ActionDispatch @filtered_path = nil end - # Return a hash of parameters with all sensitive data replaced. + # Returns a hash of parameters with all sensitive data replaced. def filtered_parameters @filtered_parameters ||= parameter_filter.filter(parameters) end - # Return a hash of request.env with all sensitive data replaced. + # Returns a hash of request.env with all sensitive data replaced. def filtered_env @filtered_env ||= env_filter.filter(@env) end diff --git a/actionpack/lib/action_dispatch/http/headers.rb b/actionpack/lib/action_dispatch/http/headers.rb index 9a3aaca3f0..12f81dc1a5 100644 --- a/actionpack/lib/action_dispatch/http/headers.rb +++ b/actionpack/lib/action_dispatch/http/headers.rb @@ -49,6 +49,11 @@ module ActionDispatch @req.set_header env_name(key), value end + # Add a value to a multivalued header like Vary or Accept-Encoding. + def add(key, value) + @req.add_header env_name(key), value + end + def key?(key) @req.has_header? env_name(key) end diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb index a966c5e452..7acf91902d 100644 --- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb +++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb @@ -10,7 +10,7 @@ module ActionDispatch self.ignore_accept_header = false end - # The MIME type of the HTTP request, such as Mime::Type[:XML]. + # The MIME type of the HTTP request, such as Mime[:xml]. # # For backward compatibility, the post \format is extracted from the # X-Post-Data-Format HTTP header if present. @@ -49,9 +49,9 @@ module ActionDispatch # Returns the MIME type for the \format used in the request. # - # GET /posts/5.xml | request.format => Mime::Type[:XML] - # GET /posts/5.xhtml | request.format => Mime::Type[:HTML] - # GET /posts/5 | request.format => Mime::Type[:HTML] or Mime::Type[:JS], or request.accepts.first + # GET /posts/5.xml | request.format => Mime[:xml] + # GET /posts/5.xhtml | request.format => Mime[:html] + # GET /posts/5 | request.format => Mime[:html] or Mime[:js], or request.accepts.first # def format(view_path = []) formats.first || Mime::NullType.instance @@ -70,9 +70,9 @@ module ActionDispatch elsif use_accept_header && valid_accept_header accepts elsif xhr? - [Mime::Type[:JS]] + [Mime[:js]] else - [Mime::Type[:HTML]] + [Mime[:html]] end set_header k, v end @@ -138,14 +138,14 @@ module ActionDispatch # def negotiate_mime(order) formats.each do |priority| - if priority == Mime::Type[:ALL] + if priority == Mime::ALL return order.first elsif order.include?(priority) return priority end end - order.include?(Mime::Type[:ALL]) ? format : nil + order.include?(Mime::ALL) ? format : nil end protected diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb index 36e90e5855..95094c25c0 100644 --- a/actionpack/lib/action_dispatch/http/mime_type.rb +++ b/actionpack/lib/action_dispatch/http/mime_type.rb @@ -46,7 +46,8 @@ module Mime end def const_missing(sym) - if Mime::Type.registered?(sym) + ext = sym.downcase + if Mime[ext] ActiveSupport::Deprecation.warn <<-eow Accessing mime types via constants is deprecated. Please change: @@ -54,16 +55,17 @@ Accessing mime types via constants is deprecated. Please change: to: - `Mime::Type[:#{sym}]` + `Mime[:#{ext}]` eow - Mime::Type[sym] + Mime[ext] else super end end def const_defined?(sym, inherit = true) - if Mime::Type.registered?(sym) + ext = sym.downcase + if Mime[ext] ActiveSupport::Deprecation.warn <<-eow Accessing mime types via constants is deprecated. Please change: @@ -71,7 +73,7 @@ Accessing mime types via constants is deprecated. Please change: to: - `Mime::Type.registered?(:#{sym})` + `Mime[:#{ext}]` eow true else @@ -106,7 +108,7 @@ to: def initialize(index, name, q = nil) @index = index @name = name - q ||= 0.0 if @name == Mime::Type[:ALL].to_s # default wildcard match to end of list + q ||= 0.0 if @name == '*/*'.freeze # default wildcard match to end of list @q = ((q || 1.0).to_f * 100).to_i end @@ -131,7 +133,7 @@ to: exchange_xml_items if app_xml_idx > text_xml_idx # make sure app_xml is ahead of text_xml in the list delete_at(text_xml_idx) # delete text_xml from the list elsif text_xml_idx - text_xml.name = Mime::Type[:XML].to_s + text_xml.name = Mime[:xml].to_s end # Look for more specific XML-based types and sort them ahead of app/xml @@ -160,7 +162,7 @@ to: end def app_xml_idx - @app_xml_idx ||= index(Mime::Type[:XML].to_s) + @app_xml_idx ||= index(Mime[:xml].to_s) end def text_xml @@ -177,8 +179,6 @@ to: end end - TYPES = {} - class << self TRAILING_STAR_REGEXP = /(text|application)\/\*/ PARAMETER_SEPARATOR_REGEXP = /;\s*\w+="?\w+"?/ @@ -187,18 +187,6 @@ to: @register_callbacks << block end - def registered?(symbol) - TYPES.key? symbol - end - - def [](symbol) - TYPES[symbol] - end - - def add_type(symbol, type) - TYPES[symbol] = type - end - def lookup(string) LOOKUP[string] end @@ -215,7 +203,6 @@ to: def register(string, symbol, mime_type_synonyms = [], extension_synonyms = [], skip_lookup = false) new_mime = Type.new(string, symbol, mime_type_synonyms) - add_type symbol.upcase, new_mime SET << new_mime @@ -255,13 +242,13 @@ to: parse_data_with_trailing_star($1) if accept_header =~ TRAILING_STAR_REGEXP end - # For an input of <tt>'text'</tt>, returns <tt>[Mime::Type[:JSON], Mime::Type[:XML], Mime::Type[:ICS], - # Mime::Type[:HTML], Mime::Type[:CSS], Mime::Type[:CSV], Mime::Type[:JS], Mime::Type[:YAML], Mime::Type[:TEXT]</tt>. + # For an input of <tt>'text'</tt>, returns <tt>[Mime[:json], Mime[:xml], Mime[:ics], + # Mime[:html], Mime[:css], Mime[:csv], Mime[:js], Mime[:yaml], Mime[:text]</tt>. # - # For an input of <tt>'application'</tt>, returns <tt>[Mime::Type[:HTML], Mime::Type[:JS], - # Mime::Type[:XML], Mime::Type[:YAML], Mime::Type[:ATOM], Mime::Type[:JSON], Mime::Type[:RSS], Mime::Type[:URL_ENCODED_FORM]</tt>. - def parse_data_with_trailing_star(input) - Mime::SET.select { |m| m =~ input } + # For an input of <tt>'application'</tt>, returns <tt>[Mime[:html], Mime[:js], + # Mime[:xml], Mime[:yaml], Mime[:atom], Mime[:json], Mime[:rss], Mime[:url_encoded_form]</tt>. + def parse_data_with_trailing_star(type) + Mime::SET.select { |m| m =~ type } end # This method is opposite of register method. @@ -270,12 +257,12 @@ to: # # Mime::Type.unregister(:mobile) def unregister(symbol) - symbol = symbol.upcase - mime = TYPES.delete symbol - - SET.delete_if { |v| v.eql?(mime) } - LOOKUP.delete_if { |_,v| v.eql?(mime) } - EXTENSION_LOOKUP.delete_if { |_,v| v.eql?(mime) } + symbol = symbol.downcase + if mime = Mime[symbol] + SET.delete_if { |v| v.eql?(mime) } + LOOKUP.delete_if { |_, v| v.eql?(mime) } + EXTENSION_LOOKUP.delete_if { |_, v| v.eql?(mime) } + end end end @@ -343,13 +330,24 @@ to: def respond_to_missing?(method, include_private = false) #:nodoc: method.to_s.ends_with? '?' end + end + + class AllType < Type + include Singleton - class All < Type - def all?; true; end - def html?; true; end + def initialize + super '*/*', :all end + + def all?; true; end + def html?; true; end end + # ALL isn't a real MIME type, so we don't register it for lookup with the + # other concrete types. It's a wildcard match that we use for `respond_to` + # negotiation internals. + ALL = AllType.instance + class NullType include Singleton diff --git a/actionpack/lib/action_dispatch/http/mime_types.rb b/actionpack/lib/action_dispatch/http/mime_types.rb index 04828f7c87..87715205d9 100644 --- a/actionpack/lib/action_dispatch/http/mime_types.rb +++ b/actionpack/lib/action_dispatch/http/mime_types.rb @@ -31,6 +31,3 @@ Mime::Type.register "application/json", :json, %w( text/x-json application/jsonr Mime::Type.register "application/pdf", :pdf, [], %w(pdf) Mime::Type.register "application/zip", :zip, [], %w(zip) - -# Create Mime::Type[:ALL] but do not add it to the SET. -Mime::Type.add_type :ALL, Mime::Type::All.new("*/*", :all, []) diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb index e3c4392760..248ecfd676 100644 --- a/actionpack/lib/action_dispatch/http/parameters.rb +++ b/actionpack/lib/action_dispatch/http/parameters.rb @@ -4,7 +4,7 @@ module ActionDispatch PARAMETERS_KEY = 'action_dispatch.request.path_parameters' DEFAULT_PARSERS = { - Mime::Type[:JSON] => lambda { |raw_post| + Mime[:json] => lambda { |raw_post| data = ActiveSupport::JSON.decode(raw_post) data.is_a?(Hash) ? data : {:_json => data} } diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index f6f63f1f32..c54efb6541 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -39,7 +39,7 @@ module ActionDispatch # :nodoc: end def []=(k,v) - if @response.committed? + if @response.sending? || @response.sent? raise ActionDispatch::IllegalStateError, 'header already sent' end @@ -78,6 +78,10 @@ module ActionDispatch # :nodoc: cattr_accessor(:default_headers) include Rack::Response::Helpers + # Aliasing these off because AD::Http::Cache::Response defines them + alias :_cache_control :cache_control + alias :_cache_control= :cache_control= + include ActionDispatch::Http::FilterRedirect include ActionDispatch::Http::Cache::Response include MonitorMixin @@ -156,31 +160,11 @@ module ActionDispatch # :nodoc: yield self if block_given? end - def have_header?(key); headers.key? key; end + def has_header?(key); headers.key? key; end def get_header(key); headers[key]; end def set_header(key, v); headers[key] = v; end def delete_header(key); headers.delete key; end - # Add a header that may have multiple values. - # - # Example: - # response.add_header 'Vary', 'Accept' - # response.add_header 'Vary', 'Accept-Encoding' - # response.add_header 'Vary', 'Cookie' - # - # assert_equal 'Accept,Accept-Encoding,Cookie', response.get_header 'Vary' - # - # http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 - def add_header(key, v) - if v.nil? - get_header key - elsif have_header? key - set_header key, "#{get_header key},#{v}" - else - set_header key, v - end - end - def await_commit synchronize do @cv.wait_until { @committed } @@ -299,6 +283,10 @@ module ActionDispatch # :nodoc: @stream.body end + def write(string) + @stream.write string + end + EMPTY = " " # Allows you to manually set or override the response body. @@ -314,6 +302,40 @@ module ActionDispatch # :nodoc: end end + # Avoid having to pass an open file handle as the response body. + # Rack::Sendfile will usually intercept the response and uses + # the path directly, so there is no reason to open the file. + class FileBody #:nodoc: + attr_reader :to_path + + def initialize(path) + @to_path = path + end + + def body + File.binread(to_path) + end + + # Stream the file's contents if Rack::Sendfile isn't present. + def each + File.open(to_path, 'rb') do |file| + while chunk = file.read(16384) + yield chunk + end + end + end + end + + # Send the file stored at +path+ as the response body. + def send_file(path) + commit! + @stream = FileBody.new(path) + end + + def reset_body! + @stream = build_buffer(self, []) + end + def body_parts parts = [] @stream.each { |x| parts << x } @@ -409,7 +431,7 @@ module ActionDispatch # :nodoc: return if content_type ct = parse_content_type - set_content_type(ct.mime_type || Mime::Type[:HTML].to_s, + set_content_type(ct.mime_type || Mime[:html].to_s, ct.charset || self.class.default_charset) end diff --git a/actionpack/lib/action_dispatch/journey/nodes/node.rb b/actionpack/lib/action_dispatch/journey/nodes/node.rb index d069bf0205..2793c5668d 100644 --- a/actionpack/lib/action_dispatch/journey/nodes/node.rb +++ b/actionpack/lib/action_dispatch/journey/nodes/node.rb @@ -42,6 +42,7 @@ module ActionDispatch def terminal?; false; end def star?; false; end def cat?; false; end + def group?; false; end end class Terminal < Node # :nodoc: @@ -95,6 +96,7 @@ module ActionDispatch class Group < Unary # :nodoc: def type; :GROUP; end + def group?; true; end end class Star < Unary # :nodoc: diff --git a/actionpack/lib/action_dispatch/journey/path/pattern.rb b/actionpack/lib/action_dispatch/journey/path/pattern.rb index e93970046c..5ee8810066 100644 --- a/actionpack/lib/action_dispatch/journey/path/pattern.rb +++ b/actionpack/lib/action_dispatch/journey/path/pattern.rb @@ -46,7 +46,7 @@ module ActionDispatch end def names - @names ||= spec.grep(Nodes::Symbol).map(&:name) + @names ||= spec.find_all(&:symbol?).map(&:name) end def required_names @@ -54,8 +54,8 @@ module ActionDispatch end def optional_names - @optional_names ||= spec.grep(Nodes::Group).flat_map { |group| - group.grep(Nodes::Symbol) + @optional_names ||= spec.find_all(&:group?).flat_map { |group| + group.find_all(&:symbol?) }.map(&:name).uniq end diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb index f3c6be864f..59c3f9248f 100644 --- a/actionpack/lib/action_dispatch/routing.rb +++ b/actionpack/lib/action_dispatch/routing.rb @@ -53,7 +53,7 @@ module ActionDispatch # resources :posts, :comments # end # - # Alternately, you can add prefixes to your path without using a separate + # Alternatively, you can add prefixes to your path without using a separate # directory by using +scope+. +scope+ takes additional options which # apply to all enclosed routes. # diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 87b826f7d0..921cda91ee 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -402,7 +402,8 @@ module ActionDispatch # because this means it will be matched first. As this is the most popular route # of most Rails applications, this is beneficial. def root(options = {}) - match '/', { :as => :root, :via => :get }.merge!(options) + name = has_named_route?(:root) ? nil : :root + match '/', { as: name, via: :get }.merge!(options) end # Matches a url pattern to one or more routes. @@ -482,7 +483,7 @@ module ActionDispatch # resources :user, param: :name # # You can override <tt>ActiveRecord::Base#to_param</tt> of a related - # model to construct an URL: + # model to construct a URL: # # class User < ActiveRecord::Base # def to_param @@ -665,6 +666,7 @@ module ActionDispatch super(options) else prefix_options = options.slice(*_route.segment_keys) + prefix_options[:relative_url_root] = ''.freeze # we must actually delete prefix segment keys to avoid passing them to next url_for _route.segment_keys.each { |k| options.delete(k) } _routes.url_helpers.send("#{name}_path", prefix_options) @@ -1866,7 +1868,7 @@ to this: # and return nil in case it isn't. Otherwise, we pass the invalid name # forward so the underlying router engine treats it and raises an exception. if as.nil? - candidate unless candidate !~ /\A[_a-z]/i || @set.named_routes.key?(candidate) + candidate unless candidate !~ /\A[_a-z]/i || has_named_route?(candidate) else candidate end diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index e4b8d5993e..339e2b7c4a 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -656,14 +656,18 @@ module ActionDispatch RESERVED_OPTIONS = [:host, :protocol, :port, :subdomain, :domain, :tld_length, :trailing_slash, :anchor, :params, :only_path, :script_name, - :original_script_name] + :original_script_name, :relative_url_root] def optimize_routes_generation? default_url_options.empty? end def find_script_name(options) - options.delete(:script_name) || relative_url_root || '' + options.delete(:script_name) || find_relative_url_root(options) || '' + end + + def find_relative_url_root(options) + options.delete(:relative_url_root) || relative_url_root end def path_for(options, route_name = nil) diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index 883cd9c2c3..b6c031dcf4 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -1,7 +1,7 @@ module ActionDispatch module Routing # In <tt>config/routes.rb</tt> you define URL-to-controller mappings, but the reverse - # is also possible: an URL can be generated from one of your routing definitions. + # is also possible: a URL can be generated from one of your routing definitions. # URL generation functionality is centralized in this module. # # See ActionDispatch::Routing for general information about routing and routes.rb. diff --git a/actionpack/lib/action_dispatch/testing/assertions.rb b/actionpack/lib/action_dispatch/testing/assertions.rb index 81fa10a613..8dd0bd63ad 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::Type[:XML] + @html_document ||= if @response.content_type === Mime[: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 753cd2073b..7e59bb68cf 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::Type[:JS], Mime::Type[:HTML], Mime::Type[:XML], 'text/xml', Mime::Type[:ALL]].join(', ') + headers['HTTP_ACCEPT'] ||= [Mime[:js], Mime[:html], Mime[:xml], 'text/xml', '*/*'].join(', ') end # this modifies the passed request_env directly diff --git a/actionpack/test/abstract/collector_test.rb b/actionpack/test/abstract/collector_test.rb index 3b36e43c0b..edbb84d462 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::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 [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 :baz, collector.responses[2][2].call end end diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index 7dfeadceb0..899d92f815 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::Type[:RSS] + render body: "Hello!", content_type: Mime[:rss] end def session_stuffing diff --git a/actionpack/test/controller/content_type_test.rb b/actionpack/test/controller/content_type_test.rb index 4a86f1bad3..c02607b55e 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::Type[:RSS] + response.content_type = Mime[: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::Type[:RSS] + render body: "hello world!", :content_type => Mime[:rss] end # :ported: @@ -36,7 +36,7 @@ class OldContentTypeController < ActionController::Base end def render_change_for_builder - response.content_type = Mime::Type[:HTML] + response.content_type = Mime[: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::Type[:XML] } + format.rss { render body: "hello world!", content_type: Mime[: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::Type[:TEXT], @response.content_type + assert_equal Mime[: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::Type[:TEXT], @response.content_type + assert_equal Mime[:text], @response.content_type end end # :ported: def test_content_type_from_body get :render_content_type_from_body - assert_equal Mime::Type[:RSS], @response.content_type + assert_equal Mime[: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::Type[:RSS], @response.content_type + assert_equal Mime[: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::Type[:TEXT], @response.content_type + assert_equal Mime[: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::Type[:TEXT], @response.content_type + assert_equal Mime[: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::Type[:HTML], @response.content_type + assert_equal Mime[: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::Type[:HTML], @response.content_type + assert_equal Mime[:html], @response.content_type assert_equal "utf-8", @response.charset end def test_default_for_builder get :render_default_for_builder - assert_equal Mime::Type[:XML], @response.content_type + assert_equal Mime[:xml], @response.content_type assert_equal "utf-8", @response.charset end def test_change_for_builder get :render_change_for_builder - assert_equal Mime::Type[:HTML], @response.content_type + assert_equal Mime[: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::Type[:HTML].to_s + @request.accept = Mime[:html].to_s get :render_default_content_types_for_respond_to - assert_equal Mime::Type[:HTML], @response.content_type + assert_equal Mime[:html], @response.content_type - @request.accept = Mime::Type[:JS].to_s + @request.accept = Mime[:js].to_s get :render_default_content_types_for_respond_to - assert_equal Mime::Type[:JS], @response.content_type + assert_equal Mime[:js], @response.content_type end def test_render_default_content_types_for_respond_to_with_template - @request.accept = Mime::Type[:XML].to_s + @request.accept = Mime[:xml].to_s get :render_default_content_types_for_respond_to - assert_equal Mime::Type[:XML], @response.content_type + assert_equal Mime[:xml], @response.content_type end def test_render_default_content_types_for_respond_to_with_overwrite - @request.accept = Mime::Type[:RSS].to_s + @request.accept = Mime[:rss].to_s get :render_default_content_types_for_respond_to - assert_equal Mime::Type[:XML], @response.content_type + assert_equal Mime[:xml], @response.content_type end end diff --git a/actionpack/test/controller/mime/respond_to_test.rb b/actionpack/test/controller/mime/respond_to_test.rb index 64eb33f78f..c025c7fa00 100644 --- a/actionpack/test/controller/mime/respond_to_test.rb +++ b/actionpack/test/controller/mime/respond_to_test.rb @@ -81,7 +81,7 @@ class RespondToController < ActionController::Base def using_defaults_with_all respond_to do |type| type.html - type.all{ render body: "ALL" } + type.all { render body: "ALL" } 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 d9899fe01f..a9dcdde4b8 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::Type[:RSS] + response.content_type = Mime[:rss] render body: "Hello world!" end def set_on_render - render body: "Hello world!", content_type: Mime::Type[:RSS] + render body: "Hello world!", content_type: Mime[:rss] end end diff --git a/actionpack/test/controller/render_other_test.rb b/actionpack/test/controller/render_other_test.rb index 8891f6177f..1f5215ac55 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::Type[:TEXT] + self.content_type = Mime[: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 094d3ea1d2..f0fd7ddc5e 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::Type[:ATOM], @response.content_type + assert_equal Mime[:atom], @response.content_type end end diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb index c712c75c88..2820425c31 100644 --- a/actionpack/test/controller/send_file_test.rb +++ b/actionpack/test/controller/send_file_test.rb @@ -22,7 +22,7 @@ class SendFileController < ActionController::Base def test_send_file_headers_bang options = { - :type => Mime::Type[:PNG], + :type => Mime[:png], :disposition => 'disposition', :filename => 'filename' } @@ -32,7 +32,7 @@ class SendFileController < ActionController::Base def test_send_file_headers_with_disposition_as_a_symbol options = { - :type => Mime::Type[:PNG], + :type => Mime[:png], :disposition => :disposition, :filename => 'filename' } @@ -195,7 +195,7 @@ class SendFileTest < ActionController::TestCase %w(file data).each do |method| define_method "test_send_#{method}_status" do @controller.options = { :stream => false, :status => 500 } - assert_nothing_raised { assert_not_nil process(method) } + assert_not_nil process(method) assert_equal 500, @response.status end diff --git a/actionpack/test/controller/webservice_test.rb b/actionpack/test/controller/webservice_test.rb index 2aee914a24..6d377c4691 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::Type[:JSON] => Proc.new { |data| ActiveSupport::JSON.decode(data)['request'].with_indifferent_access } do + with_params_parsers Mime[: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' } @@ -99,7 +99,7 @@ class WebServiceTest < ActionDispatch::IntegrationTest def test_parsing_json_doesnot_rescue_exception req = Class.new(ActionDispatch::Request) do def params_parsers - { Mime::Type[:JSON] => Proc.new { |data| raise Interrupt } } + { Mime[:json] => Proc.new { |data| raise Interrupt } } end def content_length; get_header('rack.input').length; end diff --git a/actionpack/test/dispatch/header_test.rb b/actionpack/test/dispatch/header_test.rb index 79600b654b..7f1ef121b7 100644 --- a/actionpack/test/dispatch/header_test.rb +++ b/actionpack/test/dispatch/header_test.rb @@ -42,6 +42,24 @@ class HeaderTest < ActiveSupport::TestCase assert_equal "127.0.0.1", @headers["HTTP_HOST"] end + test "add to multivalued headers" do + # Sets header when not present + @headers.add 'Foo', '1' + assert_equal '1', @headers['Foo'] + + # Ignores nil values + @headers.add 'Foo', nil + assert_equal '1', @headers['Foo'] + + # Converts value to string + @headers.add 'Foo', 1 + assert_equal '1,1', @headers['Foo'] + + # Case-insensitive + @headers.add 'fOo', 2 + assert_equal '1,1,2', @headers['foO'] + end + test "headers can contain numbers" do @headers["Content-MD5"] = "Q2hlY2sgSW50ZWdyaXR5IQ==" diff --git a/actionpack/test/dispatch/live_response_test.rb b/actionpack/test/dispatch/live_response_test.rb index 1c128365c7..55becc1c91 100644 --- a/actionpack/test/dispatch/live_response_test.rb +++ b/actionpack/test/dispatch/live_response_test.rb @@ -83,6 +83,8 @@ module ActionController def test_headers_cannot_be_written_after_close @response.stream.close + # we can add data until it's actually written, which happens on `each` + @response.each { |x| } e = assert_raises(ActionDispatch::IllegalStateError) do @response.headers['Content-Length'] = "zomg" diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index 68083ed747..149e37bf3d 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -1,7 +1,6 @@ require 'abstract_unit' class MimeTypeTest < ActiveSupport::TestCase - test "parse single" do Mime::LOOKUP.each_key do |mime_type| unless mime_type == 'image/*' @@ -11,95 +10,95 @@ class MimeTypeTest < ActiveSupport::TestCase end test "unregister" do + assert_nil Mime[:mobile] + begin - Mime::Type.register("text/x-mobile", :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 = Mime::Type.register("text/x-mobile", :mobile) + assert_equal mime, Mime[:mobile] + assert_equal mime, Mime::Type.lookup('text/x-mobile') + assert_equal mime, Mime::Type.lookup_by_extension(:mobile) Mime::Type.unregister(:mobile) - assert !Mime::Type.registered?(: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]" + assert_nil Mime[:mobile], "Mime[:mobile] should be nil after unregistering :mobile" + assert_nil Mime::Type.lookup_by_extension(:mobile), "Should be missing MIME extension lookup for :mobile" ensure - Mime::LOOKUP.reject!{|key,_| key == 'text/x-mobile'} + Mime::Type.unregister :mobile end end test "parse text with trailing star at the beginning" do accept = "text/*, text/html, application/json, multipart/form-data" - 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]] + expect = [Mime[:html], Mime[:text], Mime[:js], Mime[:css], Mime[:ics], Mime[:csv], Mime[:vcf], Mime[:xml], Mime[:yaml], Mime[:json], Mime[: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::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]] + expect = [Mime[:html], Mime[:json], Mime[:multipart_form], Mime[:text], Mime[:js], Mime[:css], Mime[:ics], Mime[:csv], Mime[:vcf], Mime[:xml], Mime[:yaml]] parsed = Mime::Type.parse(accept) assert_equal expect, parsed end test "parse text with trailing star" do accept = "text/*" - 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]] + expect = [Mime[:html], Mime[:text], Mime[:js], Mime[:css], Mime[:ics], Mime[:csv], Mime[:vcf], Mime[:xml], Mime[:yaml], Mime[:json]] parsed = Mime::Type.parse(accept) assert_equal expect, parsed end test "parse application with trailing star" do accept = "application/*" - 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]] + expect = [Mime[:html], Mime[:js], Mime[:xml], Mime[:rss], Mime[:atom], Mime[:yaml], Mime[:url_encoded_form], Mime[:json], Mime[:pdf], Mime[: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::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) + expect = [Mime[:html], Mime[:xml], Mime[:yaml], Mime[:png], Mime[:text], Mime[:pdf], '*/*'] + assert_equal expect.map(&:to_s), Mime::Type.parse(accept).map(&:to_s) 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::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) + expect = [Mime[:html], Mime[:xml], Mime[:png], Mime[:pdf], Mime[:text], Mime[:yaml], '*/*'] + assert_equal expect.map(&:to_s), Mime::Type.parse(accept).map(&:to_s) end test "parse single media range with q" do accept = "text/html;q=0.9" - expect = [Mime::Type[:HTML]] + expect = [Mime[: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::Type[:MULTIPART_FORM]] + expect = [Mime[: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::Type[:HTML], Mime::Type[:XML], "image/*", Mime::Type[:TEXT], Mime::Type[:ALL]] - assert_equal expect, Mime::Type.parse(accept).collect(&:to_s) + expect = [Mime[:html], Mime[:xml], "image/*", Mime[:text], '*/*'] + assert_equal expect.map(&:to_s), Mime::Type.parse(accept).map(&:to_s) end # Accept header send with user HTTP_USER_AGENT: Mozilla/4.0 # (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::Type[:ALL]] - assert_equal expect, Mime::Type.parse(accept).collect(&:to_s) + 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', '*/*'] + assert_equal expect.map(&:to_s), Mime::Type.parse(accept).map(&:to_s) end test "custom type" do begin type = Mime::Type.register("image/foo", :foo) - assert_equal Mime::Type[:FOO], type - assert Mime::Type.registered?(:FOO) + assert_equal type, Mime[:foo] ensure - Mime::Type.unregister(:FOO) + Mime::Type.unregister(:foo) end end @@ -107,10 +106,10 @@ 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::Type[:FOOBAR], type + assert_equal Mime[:foobar], type end ensure - Mime::Type.unregister(:FOOBAR) + Mime::Type.unregister(:foobar) end end @@ -121,10 +120,10 @@ class MimeTypeTest < ActiveSupport::TestCase registered_mimes << mime end - Mime::Type.register("text/foo", :foo) - assert_equal [Mime::Type[:FOO]], registered_mimes + mime = Mime::Type.register("text/foo", :foo) + assert_equal [mime], registered_mimes ensure - Mime::Type.unregister(:FOO) + Mime::Type.unregister(:foo) end end @@ -132,36 +131,32 @@ class MimeTypeTest < ActiveSupport::TestCase begin Mime::Type.register "text/foobar", :foobar, [], [:foo, "bar"] %w[foobar foo bar].each do |extension| - assert_equal Mime::Type[:FOOBAR], Mime::EXTENSION_LOOKUP[extension] + assert_equal Mime[:foobar], Mime::EXTENSION_LOOKUP[extension] end ensure - Mime::Type.unregister(:FOOBAR) + Mime::Type.unregister(:foobar) end end test "register alias" do begin Mime::Type.register_alias "application/xhtml+xml", :foobar - assert_equal Mime::Type[:HTML], Mime::EXTENSION_LOOKUP['foobar'] + assert_equal Mime[:html], Mime::EXTENSION_LOOKUP['foobar'] ensure - Mime::Type.unregister(:FOOBAR) + Mime::Type.unregister(:foobar) end end test "type should be equal to symbol" do - assert_equal Mime::Type[:HTML], 'application/xhtml+xml' - assert_equal Mime::Type[:HTML], :html + assert_equal Mime[:html], 'application/xhtml+xml' + assert_equal Mime[:html], :html end test "type convenience methods" do - # Don't test Mime::Type[:ALL], since it Mime::Type[:ALL].html? == true - types = Mime::SET.symbols.uniq - [:all, :iphone] - - # Remove custom Mime::Type instances set in other tests, like Mime::Type[:GIF] and Mime::Type[:IPHONE] - types.delete_if { |type| !Mime::Type.registered?(type.upcase) } + types = Mime::SET.symbols.uniq - [:iphone] types.each do |type| - mime = Mime::Type[type.upcase] + mime = Mime[type] assert mime.respond_to?("#{type}?"), "#{mime.inspect} does not respond to #{type}?" assert_equal type, mime.symbol, "#{mime.inspect} is not #{type}?" invalid_types = types - [type] @@ -172,41 +167,31 @@ class MimeTypeTest < ActiveSupport::TestCase end end - test "mime all is html" do - 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?" + Mime::HTML end end test "deprecated const_defined?" do - assert_deprecated { Mime.const_defined?(:ALL) } - 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::Type[:GIF] and Mime::Type[:IPHONE] - all_types.delete_if { |type| !Mime::Type.registered?(type.upcase) } + assert_deprecated do + Mime.const_defined? :HTML + end end test "references gives preference to symbols before strings" do - assert_equal :html, Mime::Type[:HTML].ref + assert_equal :html, Mime[: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::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' + 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' end end diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index 40866595ed..af2ed24f43 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::Type[:XML], request.format + assert_equal Mime[: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::Type[:HTML], request.format + assert_equal Mime[: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::Type[:TEXT], request.format + assert_equal Mime[:text], request.format end end test "XMLHttpRequest" do request = stub_request( 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest', - 'HTTP_ACCEPT' => [Mime::Type[:JS], Mime::Type[:HTML], Mime::Type[:XML], "text/xml", Mime::Type[:ALL]].join(",") + 'HTTP_ACCEPT' => [Mime[:js], Mime[:html], Mime[:xml], "text/xml", "*/*"].join(",") ) assert_called(request, :parameters, times: 1, returns: {}) do assert request.xhr? - assert_equal Mime::Type[:JS], request.format + assert_equal Mime[: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::Type[:HTML]], request.formats + assert_equal [Mime[:html]], request.formats end test "formats blank with accept header" do request = stub_request 'HTTP_ACCEPT' => '' - assert_equal [Mime::Type[:HTML]], request.formats + assert_equal [Mime[:html]], request.formats end test "formats XMLHttpRequest with accept header" do request = stub_request 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest" - assert_equal [Mime::Type[:JS]], request.formats + assert_equal [Mime[: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::Type[:XML]], request.formats + assert_equal [Mime[: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::Type[:TEXT]], request.formats + assert_equal [Mime[: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::Type[:JS]], request.formats + assert_equal [Mime[: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::Type[:HTML] ], request.formats + assert_equal [ Mime[:html] ], request.formats end request = stub_request 'HTTP_ACCEPT' => 'koz-asked/something-crazy' assert_called(request, :parameters, times: 1, returns: {}) do - assert_equal [ Mime::Type[:HTML] ], request.formats + assert_equal [ Mime[:html] ], request.formats end request = stub_request 'HTTP_ACCEPT' => '*/*;q=0.1' assert_called(request, :parameters, times: 1, returns: {}) do - assert_equal [ Mime::Type[:HTML] ], request.formats + assert_equal [ Mime[:html] ], request.formats end request = stub_request 'HTTP_ACCEPT' => 'application/jxw' assert_called(request, :parameters, times: 1, returns: {}) do - assert_equal [ Mime::Type[:HTML] ], request.formats + assert_equal [ Mime[: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::Type[:JS] ], request.formats + assert_equal [ Mime[: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::Type[:JSON] ], request.formats + assert_equal [ Mime[: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::Type[:HTML], stub_request('CONTENT_TYPE' => 'text/html').content_mime_type + assert_equal Mime[: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::Type[:XML], stub_request('CONTENT_TYPE' => 'application/xml').content_mime_type + assert_equal Mime[:xml], stub_request('CONTENT_TYPE' => 'application/xml').content_mime_type end test "content type with charset" do - assert_equal Mime::Type[:XML], stub_request('CONTENT_TYPE' => 'application/xml; charset=UTF-8').content_mime_type + assert_equal Mime[: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::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]]) + 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]) end test "negotiate_mime with content_type" do @@ -933,7 +933,7 @@ class RequestMimeType < BaseRequestTest 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest" ) - assert_equal Mime::Type[:XML], request.negotiate_mime([Mime::Type[:XML], Mime::Type[:CSV]]) + assert_equal Mime[:xml], request.negotiate_mime([Mime[:xml], Mime[:csv]]) end end diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index 82cc21b17a..126379a23c 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -146,7 +146,7 @@ class ResponseTest < ActiveSupport::TestCase test "cookies" do @response.set_cookie("user_name", :value => "david", :path => "/") - status, headers, body = @response.to_a + _status, headers, _body = @response.to_a assert_equal "user_name=david; path=/", headers["Set-Cookie"] assert_equal({"user_name" => "david"}, @response.cookies) end @@ -154,7 +154,7 @@ class ResponseTest < ActiveSupport::TestCase 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 + _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 @@ -163,7 +163,6 @@ class ResponseTest < ActiveSupport::TestCase @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) end @@ -185,13 +184,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::Type[:XML] + response.content_type = Mime[:xml] response.body = 'Hello' } resp.to_a assert_equal('utf-16', resp.charset) - assert_equal(Mime::Type[:XML], resp.content_type) + assert_equal(Mime[:xml], resp.content_type) assert_equal('application/xml; charset=utf-16', resp.headers['Content-Type']) end @@ -299,10 +298,10 @@ class ResponseHeadersTest < ActiveSupport::TestCase @response.set_header 'Foo', '1' end - test 'have_header?' do - assert @response.have_header? 'Foo' - assert_not @response.have_header? 'foo' - assert_not @response.have_header? nil + test 'has_header?' do + assert @response.has_header? 'Foo' + assert_not @response.has_header? 'foo' + assert_not @response.has_header? nil end test 'get_header' do @@ -313,11 +312,11 @@ class ResponseHeadersTest < ActiveSupport::TestCase test 'set_header' do assert_equal '2', @response.set_header('Foo', '2') - assert @response.have_header?('Foo') + assert @response.has_header?('Foo') assert_equal '2', @response.get_header('Foo') assert_nil @response.set_header('Foo', nil) - assert @response.have_header?('Foo') + assert @response.has_header?('Foo') assert_nil @response.get_header('Foo') end @@ -325,10 +324,10 @@ class ResponseHeadersTest < ActiveSupport::TestCase assert_nil @response.delete_header(nil) assert_nil @response.delete_header('foo') - assert @response.have_header?('Foo') + assert @response.has_header?('Foo') assert_equal '1', @response.delete_header('Foo') - assert_not @response.have_header?('Foo') + assert_not @response.has_header?('Foo') end test 'add_header' do @@ -342,12 +341,12 @@ class ResponseHeadersTest < ActiveSupport::TestCase # Add nil to a nonexistent header assert_nil @response.add_header('Bar', nil) - assert_not @response.have_header?('Bar') + assert_not @response.has_header?('Bar') assert_nil @response.get_header('Bar') # Add a value to a nonexistent header assert_equal '1', @response.add_header('Bar', '1') - assert @response.have_header?('Bar') + assert @response.has_header?('Bar') assert_equal '1', @response.get_header('Bar') end end @@ -393,7 +392,7 @@ class ResponseIntegrationTest < ActionDispatch::IntegrationTest @app = lambda { |env| ActionDispatch::Response.new.tap { |resp| resp.charset = 'utf-16' - resp.content_type = Mime::Type[:XML] + resp.content_type = Mime[:xml] resp.body = 'Hello' }.to_a } @@ -402,7 +401,7 @@ class ResponseIntegrationTest < ActionDispatch::IntegrationTest assert_response :success assert_equal('utf-16', @response.charset) - assert_equal(Mime::Type[:XML], @response.content_type) + assert_equal(Mime[:xml], @response.content_type) assert_equal('application/xml; charset=utf-16', @response.headers['Content-Type']) end @@ -418,7 +417,7 @@ class ResponseIntegrationTest < ActionDispatch::IntegrationTest assert_response :success assert_equal('utf-16', @response.charset) - assert_equal(Mime::Type[:XML], @response.content_type) + assert_equal(Mime[:xml], @response.content_type) assert_equal('application/xml; charset=utf-16', @response.headers['Content-Type']) end |