actionpack 6.0.0.beta1 → 6.0.1.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +125 -13
- data/README.rdoc +2 -1
- data/lib/abstract_controller/caching/fragments.rb +0 -1
- data/lib/abstract_controller/translation.rb +1 -0
- data/lib/action_controller.rb +4 -1
- data/lib/action_controller/metal.rb +3 -3
- data/lib/action_controller/metal/basic_implicit_render.rb +1 -1
- data/lib/action_controller/metal/etag_with_template_digest.rb +1 -1
- data/lib/action_controller/metal/exceptions.rb +2 -2
- data/lib/action_controller/metal/force_ssl.rb +1 -2
- data/lib/action_controller/metal/helpers.rb +2 -2
- data/lib/action_controller/metal/implicit_render.rb +2 -2
- data/lib/action_controller/metal/live.rb +2 -2
- data/lib/action_controller/metal/mime_responds.rb +1 -1
- data/lib/action_controller/metal/params_wrapper.rb +2 -2
- data/lib/action_controller/metal/redirecting.rb +6 -27
- data/lib/action_controller/metal/renderers.rb +4 -4
- data/lib/action_controller/metal/rendering.rb +1 -1
- data/lib/action_controller/metal/request_forgery_protection.rb +2 -2
- data/lib/action_controller/metal/strong_parameters.rb +6 -12
- data/lib/action_controller/renderer.rb +2 -2
- data/lib/action_controller/template_assertions.rb +1 -1
- data/lib/action_controller/test_case.rb +3 -2
- data/lib/action_dispatch.rb +1 -1
- data/lib/action_dispatch/http/content_security_policy.rb +20 -9
- data/lib/action_dispatch/http/mime_negotiation.rb +5 -0
- data/lib/action_dispatch/http/mime_type.rb +13 -1
- data/lib/action_dispatch/http/response.rb +27 -7
- data/lib/action_dispatch/http/upload.rb +4 -1
- data/lib/action_dispatch/journey/formatter.rb +1 -1
- data/lib/action_dispatch/journey/path/pattern.rb +6 -1
- data/lib/action_dispatch/journey/route.rb +5 -4
- data/lib/action_dispatch/journey/routes.rb +0 -1
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +39 -0
- data/lib/action_dispatch/middleware/cookies.rb +9 -10
- data/lib/action_dispatch/middleware/debug_exceptions.rb +8 -2
- data/lib/action_dispatch/middleware/debug_view.rb +19 -1
- data/lib/action_dispatch/middleware/exception_wrapper.rb +15 -10
- data/lib/action_dispatch/middleware/host_authorization.rb +2 -2
- data/lib/action_dispatch/middleware/public_exceptions.rb +6 -2
- data/lib/action_dispatch/middleware/remote_ip.rb +3 -3
- data/lib/action_dispatch/middleware/session/cookie_store.rb +4 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +1 -1
- data/lib/action_dispatch/middleware/stack.rb +34 -2
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +3 -1
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +6 -2
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +4 -1
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +3 -1
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -0
- data/lib/action_dispatch/railtie.rb +6 -2
- data/lib/action_dispatch/routing.rb +18 -18
- data/lib/action_dispatch/routing/mapper.rb +26 -11
- data/lib/action_dispatch/routing/route_set.rb +13 -15
- data/lib/action_dispatch/system_test_case.rb +43 -5
- data/lib/action_dispatch/system_testing/browser.rb +38 -7
- data/lib/action_dispatch/system_testing/driver.rb +10 -1
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +3 -2
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +7 -6
- data/lib/action_dispatch/testing/assertions.rb +1 -1
- data/lib/action_dispatch/testing/assertions/routing.rb +8 -1
- data/lib/action_dispatch/testing/integration.rb +2 -2
- data/lib/action_dispatch/testing/request_encoder.rb +2 -2
- data/lib/action_dispatch/testing/test_response.rb +1 -1
- data/lib/action_pack/gem_version.rb +2 -2
- metadata +20 -15
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +0 -26
@@ -157,24 +157,24 @@ module ActionController
|
|
157
157
|
json = json.to_json(options) unless json.kind_of?(String)
|
158
158
|
|
159
159
|
if options[:callback].present?
|
160
|
-
if
|
160
|
+
if media_type.nil? || media_type == Mime[:json]
|
161
161
|
self.content_type = Mime[:js]
|
162
162
|
end
|
163
163
|
|
164
164
|
"/**/#{options[:callback]}(#{json})"
|
165
165
|
else
|
166
|
-
self.content_type
|
166
|
+
self.content_type = Mime[:json] if media_type.nil?
|
167
167
|
json
|
168
168
|
end
|
169
169
|
end
|
170
170
|
|
171
171
|
add :js do |js, options|
|
172
|
-
self.content_type
|
172
|
+
self.content_type = Mime[:js] if media_type.nil?
|
173
173
|
js.respond_to?(:to_js) ? js.to_js(options) : js
|
174
174
|
end
|
175
175
|
|
176
176
|
add :xml do |xml, options|
|
177
|
-
self.content_type
|
177
|
+
self.content_type = Mime[:xml] if media_type.nil?
|
178
178
|
xml.respond_to?(:to_xml) ? xml.to_xml(options) : xml
|
179
179
|
end
|
180
180
|
end
|
@@ -282,7 +282,7 @@ module ActionController #:nodoc:
|
|
282
282
|
|
283
283
|
# Check for cross-origin JavaScript responses.
|
284
284
|
def non_xhr_javascript_response? # :doc:
|
285
|
-
|
285
|
+
%r(\A(?:text|application)/javascript).match?(media_type) && !request.xhr?
|
286
286
|
end
|
287
287
|
|
288
288
|
AUTHENTICITY_TOKEN_LENGTH = 32
|
@@ -431,7 +431,7 @@ module ActionController #:nodoc:
|
|
431
431
|
The browser returned a 'null' origin for a request with origin-based forgery protection turned on. This usually
|
432
432
|
means you have the 'no-referrer' Referrer-Policy header enabled, or that the request came from a site that
|
433
433
|
refused to give its origin. This makes it impossible for Rails to verify the source of the requests. Likely the
|
434
|
-
best solution is to change your referrer policy to something less strict like same-origin or strict-
|
434
|
+
best solution is to change your referrer policy to something less strict like same-origin or strict-origin.
|
435
435
|
If you cannot change the referrer policy, you can disable origin checking with the
|
436
436
|
Rails.application.config.action_controller.forgery_protection_origin_check setting.
|
437
437
|
MSG
|
@@ -4,7 +4,6 @@ require "active_support/core_ext/hash/indifferent_access"
|
|
4
4
|
require "active_support/core_ext/array/wrap"
|
5
5
|
require "active_support/core_ext/string/filters"
|
6
6
|
require "active_support/core_ext/object/to_query"
|
7
|
-
require "active_support/rescuable"
|
8
7
|
require "action_dispatch/http/upload"
|
9
8
|
require "rack/test"
|
10
9
|
require "stringio"
|
@@ -674,18 +673,16 @@ module ActionController
|
|
674
673
|
# Returns a new <tt>ActionController::Parameters</tt> instance with the
|
675
674
|
# results of running +block+ once for every key. The values are unchanged.
|
676
675
|
def transform_keys(&block)
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
else
|
682
|
-
@parameters.transform_keys
|
683
|
-
end
|
676
|
+
return to_enum(:transform_keys) unless block_given?
|
677
|
+
new_instance_with_inherited_permitted_status(
|
678
|
+
@parameters.transform_keys(&block)
|
679
|
+
)
|
684
680
|
end
|
685
681
|
|
686
682
|
# Performs keys transformation and returns the altered
|
687
683
|
# <tt>ActionController::Parameters</tt> instance.
|
688
684
|
def transform_keys!(&block)
|
685
|
+
return to_enum(:transform_keys!) unless block_given?
|
689
686
|
@parameters.transform_keys!(&block)
|
690
687
|
self
|
691
688
|
end
|
@@ -795,7 +792,7 @@ module ActionController
|
|
795
792
|
@permitted = coder.map["ivars"][:@permitted]
|
796
793
|
when "!ruby/object:ActionController::Parameters"
|
797
794
|
# YAML's Object format. Only needed because of the format
|
798
|
-
#
|
795
|
+
# backwards compatibility above, otherwise equivalent to YAML's initialization.
|
799
796
|
@parameters, @permitted = coder.map["parameters"], coder.map["permitted"]
|
800
797
|
end
|
801
798
|
end
|
@@ -1092,9 +1089,6 @@ module ActionController
|
|
1092
1089
|
# See ActionController::Parameters.require and ActionController::Parameters.permit
|
1093
1090
|
# for more information.
|
1094
1091
|
module StrongParameters
|
1095
|
-
extend ActiveSupport::Concern
|
1096
|
-
include ActiveSupport::Rescuable
|
1097
|
-
|
1098
1092
|
# Returns a new ActionController::Parameters object that
|
1099
1093
|
# has been instantiated with the <tt>request.parameters</tt>.
|
1100
1094
|
def params
|
@@ -74,7 +74,7 @@ module ActionController
|
|
74
74
|
# * <tt>:partial</tt> - See <tt>ActionView::PartialRenderer</tt> for details.
|
75
75
|
# * <tt>:file</tt> - Renders an explicit template file. Add <tt>:locals</tt> to pass in, if so desired.
|
76
76
|
# It shouldn’t be used directly with unsanitized user input due to lack of validation.
|
77
|
-
# * <tt>:inline</tt> - Renders
|
77
|
+
# * <tt>:inline</tt> - Renders an ERB template string.
|
78
78
|
# * <tt>:plain</tt> - Renders provided text and sets the content type as <tt>text/plain</tt>.
|
79
79
|
# * <tt>:html</tt> - Renders the provided HTML safe string, otherwise
|
80
80
|
# performs HTML escape on the string first. Sets the content type as <tt>text/html</tt>.
|
@@ -116,7 +116,7 @@ module ActionController
|
|
116
116
|
|
117
117
|
RACK_VALUE_TRANSLATION = {
|
118
118
|
https: ->(v) { v ? "on" : "off" },
|
119
|
-
method: ->(v) { v.upcase },
|
119
|
+
method: ->(v) { -v.upcase },
|
120
120
|
}
|
121
121
|
|
122
122
|
def rack_key_for(key)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActionController
|
4
|
-
module TemplateAssertions
|
4
|
+
module TemplateAssertions # :nodoc:
|
5
5
|
def assert_template(options = {}, message = nil)
|
6
6
|
raise NoMethodError,
|
7
7
|
"assert_template has been extracted to a gem. To continue using it,
|
@@ -457,6 +457,7 @@ module ActionController
|
|
457
457
|
def process(action, method: "GET", params: nil, session: nil, body: nil, flash: {}, format: nil, xhr: false, as: nil)
|
458
458
|
check_required_ivars
|
459
459
|
|
460
|
+
action = +action.to_s
|
460
461
|
http_method = method.to_s.upcase
|
461
462
|
|
462
463
|
@html_document = nil
|
@@ -488,11 +489,11 @@ module ActionController
|
|
488
489
|
parameters[:format] = format
|
489
490
|
end
|
490
491
|
|
491
|
-
generated_extras = @routes.generate_extras(parameters.merge(controller: controller_class_name, action: action
|
492
|
+
generated_extras = @routes.generate_extras(parameters.merge(controller: controller_class_name, action: action))
|
492
493
|
generated_path = generated_path(generated_extras)
|
493
494
|
query_string_keys = query_parameter_names(generated_extras)
|
494
495
|
|
495
|
-
@request.assign_parameters(@routes, controller_class_name, action
|
496
|
+
@request.assign_parameters(@routes, controller_class_name, action, parameters, generated_path, query_string_keys)
|
496
497
|
|
497
498
|
@request.session.update(session) if session
|
498
499
|
@request.flash.update(flash || {})
|
data/lib/action_dispatch.rb
CHANGED
@@ -53,6 +53,7 @@ module ActionDispatch
|
|
53
53
|
autoload :RequestId
|
54
54
|
autoload :Callbacks
|
55
55
|
autoload :Cookies
|
56
|
+
autoload :ActionableExceptions
|
56
57
|
autoload :DebugExceptions
|
57
58
|
autoload :DebugLocks
|
58
59
|
autoload :DebugView
|
@@ -79,7 +80,6 @@ module ActionDispatch
|
|
79
80
|
autoload :MimeNegotiation
|
80
81
|
autoload :Parameters
|
81
82
|
autoload :ParameterFilter
|
82
|
-
autoload :Upload
|
83
83
|
autoload :UploadedFile, "action_dispatch/http/upload"
|
84
84
|
autoload :URL
|
85
85
|
end
|
@@ -22,8 +22,9 @@ module ActionDispatch #:nodoc:
|
|
22
22
|
|
23
23
|
if policy = request.content_security_policy
|
24
24
|
nonce = request.content_security_policy_nonce
|
25
|
+
nonce_directives = request.content_security_policy_nonce_directives
|
25
26
|
context = request.controller_instance || request
|
26
|
-
headers[header_name(request)] = policy.build(context, nonce)
|
27
|
+
headers[header_name(request)] = policy.build(context, nonce, nonce_directives)
|
27
28
|
end
|
28
29
|
|
29
30
|
response
|
@@ -55,6 +56,7 @@ module ActionDispatch #:nodoc:
|
|
55
56
|
POLICY_REPORT_ONLY = "action_dispatch.content_security_policy_report_only"
|
56
57
|
NONCE_GENERATOR = "action_dispatch.content_security_policy_nonce_generator"
|
57
58
|
NONCE = "action_dispatch.content_security_policy_nonce"
|
59
|
+
NONCE_DIRECTIVES = "action_dispatch.content_security_policy_nonce_directives"
|
58
60
|
|
59
61
|
def content_security_policy
|
60
62
|
get_header(POLICY)
|
@@ -80,6 +82,14 @@ module ActionDispatch #:nodoc:
|
|
80
82
|
set_header(NONCE_GENERATOR, generator)
|
81
83
|
end
|
82
84
|
|
85
|
+
def content_security_policy_nonce_directives
|
86
|
+
get_header(NONCE_DIRECTIVES)
|
87
|
+
end
|
88
|
+
|
89
|
+
def content_security_policy_nonce_directives=(generator)
|
90
|
+
set_header(NONCE_DIRECTIVES, generator)
|
91
|
+
end
|
92
|
+
|
83
93
|
def content_security_policy_nonce
|
84
94
|
if content_security_policy_nonce_generator
|
85
95
|
if nonce = get_header(NONCE)
|
@@ -133,9 +143,9 @@ module ActionDispatch #:nodoc:
|
|
133
143
|
worker_src: "worker-src"
|
134
144
|
}.freeze
|
135
145
|
|
136
|
-
|
146
|
+
DEFAULT_NONCE_DIRECTIVES = %w[script-src style-src].freeze
|
137
147
|
|
138
|
-
private_constant :MAPPINGS, :DIRECTIVES, :
|
148
|
+
private_constant :MAPPINGS, :DIRECTIVES, :DEFAULT_NONCE_DIRECTIVES
|
139
149
|
|
140
150
|
attr_reader :directives
|
141
151
|
|
@@ -204,8 +214,9 @@ module ActionDispatch #:nodoc:
|
|
204
214
|
end
|
205
215
|
end
|
206
216
|
|
207
|
-
def build(context = nil, nonce = nil)
|
208
|
-
|
217
|
+
def build(context = nil, nonce = nil, nonce_directives = nil)
|
218
|
+
nonce_directives = DEFAULT_NONCE_DIRECTIVES if nonce_directives.nil?
|
219
|
+
build_directives(context, nonce, nonce_directives).compact.join("; ")
|
209
220
|
end
|
210
221
|
|
211
222
|
private
|
@@ -228,10 +239,10 @@ module ActionDispatch #:nodoc:
|
|
228
239
|
end
|
229
240
|
end
|
230
241
|
|
231
|
-
def build_directives(context, nonce)
|
242
|
+
def build_directives(context, nonce, nonce_directives)
|
232
243
|
@directives.map do |directive, sources|
|
233
244
|
if sources.is_a?(Array)
|
234
|
-
if nonce && nonce_directive?(directive)
|
245
|
+
if nonce && nonce_directive?(directive, nonce_directives)
|
235
246
|
"#{directive} #{build_directive(sources, context).join(' ')} 'nonce-#{nonce}'"
|
236
247
|
else
|
237
248
|
"#{directive} #{build_directive(sources, context).join(' ')}"
|
@@ -266,8 +277,8 @@ module ActionDispatch #:nodoc:
|
|
266
277
|
end
|
267
278
|
end
|
268
279
|
|
269
|
-
def nonce_directive?(directive)
|
270
|
-
|
280
|
+
def nonce_directive?(directive, nonce_directives)
|
281
|
+
nonce_directives.include?(directive)
|
271
282
|
end
|
272
283
|
end
|
273
284
|
end
|
@@ -170,6 +170,7 @@ module Mime
|
|
170
170
|
def parse(accept_header)
|
171
171
|
if !accept_header.include?(",")
|
172
172
|
accept_header = accept_header.split(PARAMETER_SEPARATOR_REGEXP).first
|
173
|
+
return [] unless accept_header
|
173
174
|
parse_trailing_star(accept_header) || [Mime::Type.lookup(accept_header)].compact
|
174
175
|
else
|
175
176
|
list, index = [], 0
|
@@ -221,7 +222,18 @@ module Mime
|
|
221
222
|
|
222
223
|
attr_reader :hash
|
223
224
|
|
225
|
+
MIME_NAME = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
|
226
|
+
MIME_PARAMETER_KEY = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
|
227
|
+
MIME_PARAMETER_VALUE = "#{Regexp.escape('"')}?[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}#{Regexp.escape('"')}?"
|
228
|
+
MIME_PARAMETER = "\s*\;\s+#{MIME_PARAMETER_KEY}(?:\=#{MIME_PARAMETER_VALUE})?"
|
229
|
+
MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?:\s*#{MIME_PARAMETER}\s*)*)\z/
|
230
|
+
|
231
|
+
class InvalidMimeType < StandardError; end
|
232
|
+
|
224
233
|
def initialize(string, symbol = nil, synonyms = [])
|
234
|
+
unless MIME_REGEXP.match?(string)
|
235
|
+
raise InvalidMimeType, "#{string.inspect} is not a valid MIME type"
|
236
|
+
end
|
225
237
|
@symbol, @synonyms = symbol, synonyms
|
226
238
|
@string = string
|
227
239
|
@hash = [@string, @synonyms, @symbol].hash
|
@@ -303,7 +315,7 @@ module Mime
|
|
303
315
|
include Singleton
|
304
316
|
|
305
317
|
def initialize
|
306
|
-
super "*/*",
|
318
|
+
super "*/*", nil
|
307
319
|
end
|
308
320
|
|
309
321
|
def all?; true; end
|
@@ -85,6 +85,7 @@ module ActionDispatch # :nodoc:
|
|
85
85
|
|
86
86
|
cattr_accessor :default_charset, default: "utf-8"
|
87
87
|
cattr_accessor :default_headers
|
88
|
+
cattr_accessor :return_only_media_type_on_content_type, default: false
|
88
89
|
|
89
90
|
include Rack::Response::Helpers
|
90
91
|
# Aliasing these off because AD::Http::Cache::Response defines them.
|
@@ -242,8 +243,22 @@ module ActionDispatch # :nodoc:
|
|
242
243
|
end
|
243
244
|
|
244
245
|
# Content type of response.
|
245
|
-
# It returns just MIME type and does NOT contain charset part.
|
246
246
|
def content_type
|
247
|
+
if self.class.return_only_media_type_on_content_type
|
248
|
+
ActiveSupport::Deprecation.warn(
|
249
|
+
"Rails 6.1 will return Content-Type header without modification." \
|
250
|
+
" If you want just the MIME type, please use `#media_type` instead."
|
251
|
+
)
|
252
|
+
|
253
|
+
content_type = super
|
254
|
+
content_type ? content_type.split(/;\s*charset=/)[0].presence : content_type
|
255
|
+
else
|
256
|
+
super.presence
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
# Media type of response.
|
261
|
+
def media_type
|
247
262
|
parsed_content_type_header.mime_type
|
248
263
|
end
|
249
264
|
|
@@ -404,15 +419,18 @@ module ActionDispatch # :nodoc:
|
|
404
419
|
end
|
405
420
|
|
406
421
|
private
|
407
|
-
|
408
422
|
ContentTypeHeader = Struct.new :mime_type, :charset
|
409
423
|
NullContentTypeHeader = ContentTypeHeader.new nil, nil
|
410
424
|
|
425
|
+
CONTENT_TYPE_PARSER = /
|
426
|
+
\A
|
427
|
+
(?<mime_type>[^;\s]+\s*(?:;\s*(?:(?!charset)[^;\s])+)*)?
|
428
|
+
(?:;\s*charset=(?<quote>"?)(?<charset>[^;\s]+)\k<quote>)?
|
429
|
+
/x # :nodoc:
|
430
|
+
|
411
431
|
def parse_content_type(content_type)
|
412
|
-
if content_type
|
413
|
-
|
414
|
-
type = nil if type && type.empty?
|
415
|
-
ContentTypeHeader.new(type, charset)
|
432
|
+
if content_type && match = CONTENT_TYPE_PARSER.match(content_type)
|
433
|
+
ContentTypeHeader.new(match[:mime_type], match[:charset])
|
416
434
|
else
|
417
435
|
NullContentTypeHeader
|
418
436
|
end
|
@@ -459,7 +477,7 @@ module ActionDispatch # :nodoc:
|
|
459
477
|
end
|
460
478
|
|
461
479
|
def assign_default_content_type_and_charset!
|
462
|
-
return if
|
480
|
+
return if media_type
|
463
481
|
|
464
482
|
ct = parsed_content_type_header
|
465
483
|
set_content_type(ct.mime_type || Mime[:html].to_s,
|
@@ -517,4 +535,6 @@ module ActionDispatch # :nodoc:
|
|
517
535
|
end
|
518
536
|
end
|
519
537
|
end
|
538
|
+
|
539
|
+
ActiveSupport.run_load_hooks(:action_dispatch_response, Response)
|
520
540
|
end
|
@@ -20,7 +20,6 @@ module ActionDispatch
|
|
20
20
|
# A +Tempfile+ object with the actual uploaded file. Note that some of
|
21
21
|
# its interface is available directly.
|
22
22
|
attr_accessor :tempfile
|
23
|
-
alias :to_io :tempfile
|
24
23
|
|
25
24
|
# A string with the headers of the multipart request.
|
26
25
|
attr_accessor :headers
|
@@ -84,6 +83,10 @@ module ActionDispatch
|
|
84
83
|
def eof?
|
85
84
|
@tempfile.eof?
|
86
85
|
end
|
86
|
+
|
87
|
+
def to_io
|
88
|
+
@tempfile.to_io
|
89
|
+
end
|
87
90
|
end
|
88
91
|
end
|
89
92
|
end
|
@@ -67,7 +67,7 @@ module ActionDispatch
|
|
67
67
|
parameterized_parts = recall.merge(options)
|
68
68
|
|
69
69
|
keys_to_keep = route.parts.reverse_each.drop_while { |part|
|
70
|
-
!options.key?(part) || (options[part] || recall[part]).nil?
|
70
|
+
!(options.key?(part) || route.scope_options.key?(part)) || (options[part] || recall[part]).nil?
|
71
71
|
} | route.required_parts
|
72
72
|
|
73
73
|
parameterized_parts.delete_if do |bad_key, _|
|
@@ -119,7 +119,8 @@ module ActionDispatch
|
|
119
119
|
|
120
120
|
class UnanchoredRegexp < AnchoredRegexp # :nodoc:
|
121
121
|
def accept(node)
|
122
|
-
|
122
|
+
path = visit node
|
123
|
+
path == "/" ? %r{\A/} : %r{\A#{path}(?:\b|\Z|/)}
|
123
124
|
end
|
124
125
|
end
|
125
126
|
|
@@ -136,6 +137,10 @@ module ActionDispatch
|
|
136
137
|
Array.new(length - 1) { |i| self[i + 1] }
|
137
138
|
end
|
138
139
|
|
140
|
+
def named_captures
|
141
|
+
@names.zip(captures).to_h
|
142
|
+
end
|
143
|
+
|
139
144
|
def [](x)
|
140
145
|
idx = @offsets[x - 1] + x
|
141
146
|
@match[idx]
|
@@ -4,9 +4,9 @@ module ActionDispatch
|
|
4
4
|
# :stopdoc:
|
5
5
|
module Journey
|
6
6
|
class Route
|
7
|
-
attr_reader :app, :path, :defaults, :name, :precedence
|
7
|
+
attr_reader :app, :path, :defaults, :name, :precedence, :constraints,
|
8
|
+
:internal, :scope_options
|
8
9
|
|
9
|
-
attr_reader :constraints, :internal
|
10
10
|
alias :conditions :constraints
|
11
11
|
|
12
12
|
module VerbMatchers
|
@@ -51,13 +51,13 @@ module ActionDispatch
|
|
51
51
|
|
52
52
|
def self.build(name, app, path, constraints, required_defaults, defaults)
|
53
53
|
request_method_match = verb_matcher(constraints.delete(:request_method))
|
54
|
-
new name, app, path, constraints, required_defaults, defaults, request_method_match, 0
|
54
|
+
new name, app, path, constraints, required_defaults, defaults, request_method_match, 0, {}
|
55
55
|
end
|
56
56
|
|
57
57
|
##
|
58
58
|
# +path+ is a path constraint.
|
59
59
|
# +constraints+ is a hash of constraints to be applied to this route.
|
60
|
-
def initialize(name, app, path, constraints, required_defaults, defaults, request_method_match, precedence, internal = false)
|
60
|
+
def initialize(name, app, path, constraints, required_defaults, defaults, request_method_match, precedence, scope_options, internal = false)
|
61
61
|
@name = name
|
62
62
|
@app = app
|
63
63
|
@path = path
|
@@ -72,6 +72,7 @@ module ActionDispatch
|
|
72
72
|
@decorated_ast = nil
|
73
73
|
@precedence = precedence
|
74
74
|
@path_formatter = @path.build_formatter
|
75
|
+
@scope_options = scope_options
|
75
76
|
@internal = internal
|
76
77
|
end
|
77
78
|
|