aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb113
-rw-r--r--actionpack/test/controller/http_basic_authentication_test.rb8
-rw-r--r--actionpack/test/dispatch/mapper_test.rb4
4 files changed, 73 insertions, 54 deletions
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 032275ac64..bbb38cf8fc 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -94,7 +94,7 @@ module ActionController
end
def has_basic_credentials?(request)
- request.authorization.present? && (auth_scheme(request) == 'Basic')
+ request.authorization.present? && (auth_scheme(request).downcase == 'basic')
end
def user_name_and_password(request)
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 2d281f7e66..a12f60e20d 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -61,7 +61,9 @@ module ActionDispatch
attr_reader :requirements, :conditions, :defaults
attr_reader :to, :default_controller, :default_action, :as, :anchor
- def self.build(scope, set, path, as, options)
+ def self.build(scope, set, path, as, controller, default_action, to, options)
+ formatted = options.delete(:format) { scope[:options] && scope[:options][:format] }
+
options = scope[:options].merge(options) if scope[:options]
options.delete :only
@@ -69,50 +71,50 @@ module ActionDispatch
options.delete :shallow_path
options.delete :shallow_prefix
options.delete :shallow
+ options.delete :format
defaults = (scope[:defaults] || {}).dup
+ scope_constraints = scope[:constraints] || {}
- new scope, set, path, defaults, as, options
+ new set, path, defaults, as, controller, default_action, scope[:module], to, formatted, scope_constraints, scope[:blocks] || [], options
end
- def initialize(scope, set, path, defaults, as, options)
+ def initialize(set, path, defaults, as, controller, default_action, modyoule, to, formatted, scope_constraints, blocks, options)
@requirements, @conditions = {}, {}
@defaults = defaults
@set = set
- @to = options.delete :to
- @default_controller = options.delete(:controller) || scope[:controller]
- @default_action = options.delete(:action) || scope[:action]
+ @to = to
+ @default_controller = controller
+ @default_action = default_action
@as = as
@anchor = options.delete :anchor
- formatted = options.delete :format
via = Array(options.delete(:via) { [] })
- options_constraints = options.delete :constraints
+ options_constraints = options.delete(:constraints) || {}
path = normalize_path! path, formatted
ast = path_ast path
path_params = path_params ast
- options = normalize_options!(options, formatted, path_params, ast, scope[:module])
-
+ options = normalize_options!(options, formatted, path_params, ast, modyoule)
- split_constraints(path_params, scope[:constraints]) if scope[:constraints]
- constraints = constraints(options, path_params)
-
- split_constraints path_params, constraints
-
- @blocks = blocks(options_constraints, scope[:blocks])
+ constraints = scope_constraints.merge constraints(options, path_params)
if options_constraints.is_a?(Hash)
- split_constraints path_params, options_constraints
options_constraints.each do |key, default|
if URL_OPTIONS.include?(key) && (String === default || Fixnum === default)
@defaults[key] ||= default
end
end
+ @blocks = blocks
+ constraints.merge! options_constraints
+ else
+ @blocks = blocks(options_constraints)
end
+ split_constraints path_params, constraints
+
normalize_format!(formatted)
@conditions[:path_info] = path
@@ -217,12 +219,6 @@ module ActionDispatch
end
end
- def verify_callable_constraint(callable_constraint)
- unless callable_constraint.respond_to?(:call) || callable_constraint.respond_to?(:matches?)
- raise ArgumentError, "Invalid constraint: #{callable_constraint.inspect} must respond to :call or :matches?"
- end
- end
-
def add_request_method(via, conditions)
return if via == [:all]
@@ -302,13 +298,11 @@ module ActionDispatch
yield
end
- def blocks(options_constraints, scope_blocks)
- if options_constraints && !options_constraints.is_a?(Hash)
- verify_callable_constraint(options_constraints)
- [options_constraints]
- else
- scope_blocks || []
+ def blocks(callable_constraint)
+ unless callable_constraint.respond_to?(:call) || callable_constraint.respond_to?(:matches?)
+ raise ArgumentError, "Invalid constraint: #{callable_constraint.inspect} must respond to :call or :matches?"
end
+ [callable_constraint]
end
def constraints(options, path_params)
@@ -447,10 +441,10 @@ module ActionDispatch
# resources :user, param: :name
#
# You can override <tt>ActiveRecord::Base#to_param</tt> of a related
- # model to constructe an URL.
+ # model to construct an URL:
#
# class User < ActiveRecord::Base
- # def to_param # overridden
+ # def to_param
# name
# end
# end
@@ -1537,48 +1531,65 @@ module ActionDispatch
options[:to] ||= "#{@scope[:controller]}##{@scope[:action]}"
end
- paths.each do |_path|
- route_options = options.dup
- route_options[:path] ||= _path if _path.is_a?(String)
+ controller = options.delete(:controller) || @scope[:controller]
+ option_path = options.delete :path
+ to = options.delete :to
- path_without_format = _path.to_s.sub(/\(\.:format\)$/, '')
- if using_match_shorthand?(path_without_format, route_options)
- route_options[:to] ||= path_without_format.gsub(%r{^/}, "").sub(%r{/([^/]*)$}, '#\1')
- route_options[:to].tr!("-", "_")
- end
+ path_types = paths.group_by(&:class)
+ path_types.fetch(String, []).each do |_path|
+ route_options = options.dup
+ process_path(route_options, controller, _path, option_path || _path, to)
+ end
- decomposed_match(_path, route_options)
+ path_types.fetch(Symbol, []).each do |action|
+ route_options = options.dup
+ decomposed_match(action, controller, route_options, option_path, to)
end
+
self
end
- def using_match_shorthand?(path, options)
- path && (options[:to] || options[:action]).nil? && path =~ %r{^/?[-\w]+/[-\w/]+$}
+ def process_path(options, controller, path, option_path, to)
+ path_without_format = path.sub(/\(\.:format\)$/, '')
+ if using_match_shorthand?(path_without_format, to, options[:action])
+ to ||= path_without_format.gsub(%r{^/}, "").sub(%r{/([^/]*)$}, '#\1')
+ to.tr!("-", "_")
+ end
+
+ decomposed_match(path, controller, options, option_path, to)
end
- def decomposed_match(path, options) # :nodoc:
+ def using_match_shorthand?(path, to, action)
+ return false if to || action
+
+ path =~ %r{^/?[-\w]+/[-\w/]+$}
+ end
+
+ def decomposed_match(path, controller, options, _path, to) # :nodoc:
if on = options.delete(:on)
- send(on) { decomposed_match(path, options) }
+ send(on) { decomposed_match(path, controller, options, _path, to) }
else
case @scope.scope_level
when :resources
- nested { decomposed_match(path, options) }
+ nested { decomposed_match(path, controller, options, _path, to) }
when :resource
- member { decomposed_match(path, options) }
+ member { decomposed_match(path, controller, options, _path, to) }
else
- add_route(path, options)
+ add_route(path, controller, options, _path, to)
end
end
end
- def add_route(action, options) # :nodoc:
- path = path_for_action(action, options.delete(:path))
+ def add_route(action, controller, options, _path, to) # :nodoc:
+ path = path_for_action(action, _path)
raise ArgumentError, "path is required" if path.blank?
action = action.to_s
+ default_action = options.delete(:action) || @scope[:action]
+
if action =~ /^[\w\-\/]+$/
- options[:action] ||= action.tr('-', '_') unless action.include?("/")
+ default_action ||= action.tr('-', '_') unless action.include?("/")
else
action = nil
end
@@ -1589,7 +1600,7 @@ module ActionDispatch
name_for_action(options.delete(:as), action)
end
- mapping = Mapping.build(@scope, @set, URI.parser.escape(path), as, options)
+ mapping = Mapping.build(@scope, @set, URI.parser.escape(path), as, controller, default_action, to, options)
app, conditions, requirements, defaults, as, anchor = mapping.to_route
@set.add_route(app, conditions, requirements, defaults, as, anchor)
end
diff --git a/actionpack/test/controller/http_basic_authentication_test.rb b/actionpack/test/controller/http_basic_authentication_test.rb
index ed3632007d..0a5e5402b9 100644
--- a/actionpack/test/controller/http_basic_authentication_test.rb
+++ b/actionpack/test/controller/http_basic_authentication_test.rb
@@ -100,6 +100,14 @@ class HttpBasicAuthenticationTest < ActionController::TestCase
assert_no_match(/\n/, result)
end
+ test "succesful authentication with uppercase authorization scheme" do
+ @request.env['HTTP_AUTHORIZATION'] = "BASIC #{::Base64.encode64("lifo:world")}"
+ get :index
+
+ assert_response :success
+ assert_equal 'Hello Secret', @response.body, 'Authentication failed when authorization scheme BASIC'
+ end
+
test "authentication request without credential" do
get :display
diff --git a/actionpack/test/dispatch/mapper_test.rb b/actionpack/test/dispatch/mapper_test.rb
index aed1d914f9..b0815c41c8 100644
--- a/actionpack/test/dispatch/mapper_test.rb
+++ b/actionpack/test/dispatch/mapper_test.rb
@@ -41,8 +41,8 @@ module ActionDispatch
end
def test_mapping_requirements
- options = { :controller => 'foo', :action => 'bar', :via => :get }
- m = Mapper::Mapping.build({}, FakeSet.new, '/store/:name(*rest)', nil, options)
+ options = { :via => :get }
+ m = Mapper::Mapping.build({}, FakeSet.new, '/store/:name(*rest)', nil, 'foo', 'bar', nil, options)
_, _, requirements, _ = m.to_route
assert_equal(/.+?/, requirements[:rest])
end