actionpack 7.2.2.1 → 8.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +228 -101
- data/README.rdoc +1 -1
- data/lib/abstract_controller/base.rb +1 -12
- data/lib/abstract_controller/collector.rb +1 -1
- data/lib/abstract_controller/helpers.rb +1 -1
- data/lib/abstract_controller/rendering.rb +0 -1
- data/lib/action_controller/base.rb +1 -1
- data/lib/action_controller/form_builder.rb +3 -3
- data/lib/action_controller/metal/allow_browser.rb +11 -1
- data/lib/action_controller/metal/conditional_get.rb +5 -1
- data/lib/action_controller/metal/data_streaming.rb +4 -2
- data/lib/action_controller/metal/instrumentation.rb +1 -2
- data/lib/action_controller/metal/live.rb +59 -11
- data/lib/action_controller/metal/params_wrapper.rb +3 -3
- data/lib/action_controller/metal/rate_limiting.rb +13 -4
- data/lib/action_controller/metal/redirecting.rb +4 -3
- data/lib/action_controller/metal/renderers.rb +2 -3
- data/lib/action_controller/metal/rendering.rb +1 -1
- data/lib/action_controller/metal/request_forgery_protection.rb +3 -1
- data/lib/action_controller/metal/streaming.rb +5 -84
- data/lib/action_controller/metal/strong_parameters.rb +277 -92
- data/lib/action_controller/railtie.rb +6 -7
- data/lib/action_controller/renderer.rb +0 -1
- data/lib/action_controller/test_case.rb +12 -2
- data/lib/action_dispatch/constants.rb +6 -0
- data/lib/action_dispatch/http/cache.rb +27 -10
- data/lib/action_dispatch/http/content_security_policy.rb +14 -1
- data/lib/action_dispatch/http/mime_negotiation.rb +8 -3
- data/lib/action_dispatch/http/param_builder.rb +186 -0
- data/lib/action_dispatch/http/param_error.rb +26 -0
- data/lib/action_dispatch/http/permissions_policy.rb +2 -0
- data/lib/action_dispatch/http/query_parser.rb +53 -0
- data/lib/action_dispatch/http/request.rb +64 -19
- data/lib/action_dispatch/http/response.rb +49 -14
- data/lib/action_dispatch/http/url.rb +2 -2
- data/lib/action_dispatch/journey/formatter.rb +8 -3
- data/lib/action_dispatch/journey/gtg/transition_table.rb +4 -4
- data/lib/action_dispatch/journey/parser.rb +99 -196
- data/lib/action_dispatch/journey/scanner.rb +44 -42
- data/lib/action_dispatch/middleware/cookies.rb +4 -2
- data/lib/action_dispatch/middleware/debug_exceptions.rb +19 -4
- data/lib/action_dispatch/middleware/debug_view.rb +0 -5
- data/lib/action_dispatch/middleware/exception_wrapper.rb +3 -9
- data/lib/action_dispatch/middleware/executor.rb +5 -2
- data/lib/action_dispatch/middleware/public_exceptions.rb +5 -1
- data/lib/action_dispatch/middleware/request_id.rb +2 -1
- data/lib/action_dispatch/middleware/ssl.rb +13 -3
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +0 -3
- data/lib/action_dispatch/railtie.rb +8 -0
- data/lib/action_dispatch/request/session.rb +1 -0
- data/lib/action_dispatch/request/utils.rb +9 -3
- data/lib/action_dispatch/routing/inspector.rb +1 -1
- data/lib/action_dispatch/routing/mapper.rb +96 -67
- data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -2
- data/lib/action_dispatch/routing/route_set.rb +21 -10
- data/lib/action_dispatch/routing/routes_proxy.rb +1 -0
- data/lib/action_dispatch/system_testing/browser.rb +12 -21
- data/lib/action_dispatch/testing/assertion_response.rb +1 -1
- data/lib/action_dispatch/testing/assertions/response.rb +12 -2
- data/lib/action_dispatch/testing/assertions/routing.rb +16 -12
- data/lib/action_dispatch/testing/integration.rb +20 -10
- data/lib/action_dispatch/testing/request_encoder.rb +9 -9
- data/lib/action_dispatch/testing/test_process.rb +1 -2
- data/lib/action_dispatch.rb +6 -4
- data/lib/action_pack/gem_version.rb +4 -4
- metadata +16 -38
- data/lib/action_dispatch/journey/parser.y +0 -50
- data/lib/action_dispatch/journey/parser_extras.rb +0 -33
|
@@ -272,7 +272,7 @@ module ActionDispatch
|
|
|
272
272
|
end
|
|
273
273
|
end
|
|
274
274
|
|
|
275
|
-
# Returns whether this request is using the standard port
|
|
275
|
+
# Returns whether this request is using the standard port.
|
|
276
276
|
#
|
|
277
277
|
# req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
|
|
278
278
|
# req.standard_port? # => true
|
|
@@ -307,7 +307,7 @@ module ActionDispatch
|
|
|
307
307
|
standard_port? ? "" : ":#{port}"
|
|
308
308
|
end
|
|
309
309
|
|
|
310
|
-
# Returns the requested port, such as 8080, based on SERVER_PORT
|
|
310
|
+
# Returns the requested port, such as 8080, based on SERVER_PORT.
|
|
311
311
|
#
|
|
312
312
|
# req = ActionDispatch::Request.new 'SERVER_PORT' => '80'
|
|
313
313
|
# req.server_port # => 80
|
|
@@ -60,8 +60,13 @@ module ActionDispatch
|
|
|
60
60
|
|
|
61
61
|
def generate(name, options, path_parameters)
|
|
62
62
|
original_options = options.dup
|
|
63
|
-
path_params = options.delete(:path_params)
|
|
64
|
-
|
|
63
|
+
path_params = options.delete(:path_params)
|
|
64
|
+
if path_params.is_a?(Hash)
|
|
65
|
+
options = path_params.merge(options)
|
|
66
|
+
else
|
|
67
|
+
path_params = nil
|
|
68
|
+
options = options.dup
|
|
69
|
+
end
|
|
65
70
|
constraints = path_parameters.merge(options)
|
|
66
71
|
missing_keys = nil
|
|
67
72
|
|
|
@@ -79,7 +84,7 @@ module ActionDispatch
|
|
|
79
84
|
# top-level params' normal behavior of generating query_params should be
|
|
80
85
|
# preserved even if the same key is also a bind_param
|
|
81
86
|
parameterized_parts.key?(key) || route.defaults.key?(key) ||
|
|
82
|
-
(path_params
|
|
87
|
+
(path_params&.key?(key) && !original_options.key?(key))
|
|
83
88
|
end
|
|
84
89
|
|
|
85
90
|
defaults = route.defaults
|
|
@@ -107,10 +107,10 @@ module ActionDispatch
|
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
{
|
|
110
|
-
regexp_states: simple_regexp,
|
|
111
|
-
string_states: @string_states,
|
|
112
|
-
stdparam_states: @stdparam_states,
|
|
113
|
-
accepting: @accepting
|
|
110
|
+
regexp_states: simple_regexp.stringify_keys,
|
|
111
|
+
string_states: @string_states.stringify_keys,
|
|
112
|
+
stdparam_states: @stdparam_states.stringify_keys,
|
|
113
|
+
accepting: @accepting.stringify_keys
|
|
114
114
|
}
|
|
115
115
|
end
|
|
116
116
|
|
|
@@ -1,200 +1,103 @@
|
|
|
1
|
-
#
|
|
2
|
-
# DO NOT MODIFY!!!!
|
|
3
|
-
# This file is automatically generated by Racc 1.4.16 from
|
|
4
|
-
# Racc grammar file "".
|
|
1
|
+
# frozen_string_literal: true
|
|
5
2
|
|
|
6
|
-
|
|
3
|
+
require "action_dispatch/journey/scanner"
|
|
4
|
+
require "action_dispatch/journey/nodes/node"
|
|
7
5
|
|
|
8
|
-
require 'racc/parser.rb'
|
|
9
|
-
|
|
10
|
-
# :stopdoc:
|
|
11
|
-
|
|
12
|
-
require "action_dispatch/journey/parser_extras"
|
|
13
6
|
module ActionDispatch
|
|
14
|
-
module Journey
|
|
15
|
-
class Parser
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
"$end",
|
|
111
|
-
"error",
|
|
112
|
-
"SLASH",
|
|
113
|
-
"LITERAL",
|
|
114
|
-
"SYMBOL",
|
|
115
|
-
"LPAREN",
|
|
116
|
-
"RPAREN",
|
|
117
|
-
"DOT",
|
|
118
|
-
"STAR",
|
|
119
|
-
"OR",
|
|
120
|
-
"$start",
|
|
121
|
-
"expressions",
|
|
122
|
-
"expression",
|
|
123
|
-
"or",
|
|
124
|
-
"terminal",
|
|
125
|
-
"group",
|
|
126
|
-
"star",
|
|
127
|
-
"symbol",
|
|
128
|
-
"literal",
|
|
129
|
-
"slash",
|
|
130
|
-
"dot" ]
|
|
131
|
-
|
|
132
|
-
Racc_debug_parser = false
|
|
133
|
-
|
|
134
|
-
##### State transition tables end #####
|
|
135
|
-
|
|
136
|
-
# reduce 0 omitted
|
|
137
|
-
|
|
138
|
-
def _reduce_1(val, _values)
|
|
139
|
-
Cat.new(val.first, val.last)
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def _reduce_2(val, _values)
|
|
143
|
-
val.first
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
# reduce 3 omitted
|
|
147
|
-
|
|
148
|
-
# reduce 4 omitted
|
|
149
|
-
|
|
150
|
-
# reduce 5 omitted
|
|
151
|
-
|
|
152
|
-
# reduce 6 omitted
|
|
153
|
-
|
|
154
|
-
def _reduce_7(val, _values)
|
|
155
|
-
Group.new(val[1])
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
def _reduce_8(val, _values)
|
|
159
|
-
Or.new([val.first, val.last])
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
def _reduce_9(val, _values)
|
|
163
|
-
Or.new([val.first, val.last])
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
def _reduce_10(val, _values)
|
|
167
|
-
Star.new(Symbol.new(val.last, Symbol::GREEDY_EXP))
|
|
7
|
+
module Journey # :nodoc:
|
|
8
|
+
class Parser # :nodoc:
|
|
9
|
+
include Journey::Nodes
|
|
10
|
+
|
|
11
|
+
def self.parse(string)
|
|
12
|
+
new.parse string
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
@scanner = Scanner.new
|
|
17
|
+
@next_token = nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def parse(string)
|
|
21
|
+
@scanner.scan_setup(string)
|
|
22
|
+
advance_token
|
|
23
|
+
do_parse
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
def advance_token
|
|
28
|
+
@next_token = @scanner.next_token
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def do_parse
|
|
32
|
+
parse_expressions
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def parse_expressions
|
|
36
|
+
node = parse_expression
|
|
37
|
+
|
|
38
|
+
while @next_token
|
|
39
|
+
case @next_token
|
|
40
|
+
when :RPAREN
|
|
41
|
+
break
|
|
42
|
+
when :OR
|
|
43
|
+
node = parse_or(node)
|
|
44
|
+
else
|
|
45
|
+
node = Cat.new(node, parse_expressions)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
node
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def parse_or(lhs)
|
|
53
|
+
advance_token
|
|
54
|
+
node = parse_expression
|
|
55
|
+
Or.new([lhs, node])
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def parse_expression
|
|
59
|
+
if @next_token == :STAR
|
|
60
|
+
parse_star
|
|
61
|
+
elsif @next_token == :LPAREN
|
|
62
|
+
parse_group
|
|
63
|
+
else
|
|
64
|
+
parse_terminal
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def parse_star
|
|
69
|
+
node = Star.new(Symbol.new(@scanner.last_string, Symbol::GREEDY_EXP))
|
|
70
|
+
advance_token
|
|
71
|
+
node
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def parse_group
|
|
75
|
+
advance_token
|
|
76
|
+
node = parse_expressions
|
|
77
|
+
if @next_token == :RPAREN
|
|
78
|
+
node = Group.new(node)
|
|
79
|
+
advance_token
|
|
80
|
+
node
|
|
81
|
+
else
|
|
82
|
+
raise ArgumentError, "missing right parenthesis."
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def parse_terminal
|
|
87
|
+
node = case @next_token
|
|
88
|
+
when :SYMBOL
|
|
89
|
+
Symbol.new(@scanner.last_string)
|
|
90
|
+
when :LITERAL
|
|
91
|
+
Literal.new(@scanner.last_literal)
|
|
92
|
+
when :SLASH
|
|
93
|
+
Slash.new("/")
|
|
94
|
+
when :DOT
|
|
95
|
+
Dot.new(".")
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
advance_token
|
|
99
|
+
node
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
168
103
|
end
|
|
169
|
-
|
|
170
|
-
# reduce 11 omitted
|
|
171
|
-
|
|
172
|
-
# reduce 12 omitted
|
|
173
|
-
|
|
174
|
-
# reduce 13 omitted
|
|
175
|
-
|
|
176
|
-
# reduce 14 omitted
|
|
177
|
-
|
|
178
|
-
def _reduce_15(val, _values)
|
|
179
|
-
Slash.new(val.first)
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
def _reduce_16(val, _values)
|
|
183
|
-
Symbol.new(val.first)
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
def _reduce_17(val, _values)
|
|
187
|
-
Literal.new(val.first)
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
def _reduce_18(val, _values)
|
|
191
|
-
Dot.new(val.first)
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
def _reduce_none(val, _values)
|
|
195
|
-
val[0]
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
end # class Parser
|
|
199
|
-
end # module Journey
|
|
200
|
-
end # module ActionDispatch
|
|
@@ -7,66 +7,68 @@ require "strscan"
|
|
|
7
7
|
module ActionDispatch
|
|
8
8
|
module Journey # :nodoc:
|
|
9
9
|
class Scanner # :nodoc:
|
|
10
|
+
STATIC_TOKENS = Array.new(150)
|
|
11
|
+
STATIC_TOKENS[".".ord] = :DOT
|
|
12
|
+
STATIC_TOKENS["/".ord] = :SLASH
|
|
13
|
+
STATIC_TOKENS["(".ord] = :LPAREN
|
|
14
|
+
STATIC_TOKENS[")".ord] = :RPAREN
|
|
15
|
+
STATIC_TOKENS["|".ord] = :OR
|
|
16
|
+
STATIC_TOKENS[":".ord] = :SYMBOL
|
|
17
|
+
STATIC_TOKENS["*".ord] = :STAR
|
|
18
|
+
STATIC_TOKENS.freeze
|
|
19
|
+
|
|
20
|
+
class Scanner < StringScanner
|
|
21
|
+
unless method_defined?(:peek_byte) # https://github.com/ruby/strscan/pull/89
|
|
22
|
+
def peek_byte
|
|
23
|
+
string.getbyte(pos)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
10
28
|
def initialize
|
|
11
|
-
@
|
|
29
|
+
@scanner = nil
|
|
30
|
+
@length = nil
|
|
12
31
|
end
|
|
13
32
|
|
|
14
33
|
def scan_setup(str)
|
|
15
|
-
@
|
|
34
|
+
@scanner = Scanner.new(str)
|
|
16
35
|
end
|
|
17
36
|
|
|
18
|
-
def
|
|
19
|
-
@
|
|
20
|
-
end
|
|
37
|
+
def next_token
|
|
38
|
+
return if @scanner.eos?
|
|
21
39
|
|
|
22
|
-
|
|
23
|
-
|
|
40
|
+
until token = scan || @scanner.eos?; end
|
|
41
|
+
token
|
|
24
42
|
end
|
|
25
43
|
|
|
26
|
-
def
|
|
27
|
-
@
|
|
44
|
+
def last_string
|
|
45
|
+
-@scanner.string.byteslice(@scanner.pos - @length, @length)
|
|
28
46
|
end
|
|
29
47
|
|
|
30
|
-
def
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
token
|
|
48
|
+
def last_literal
|
|
49
|
+
last_str = @scanner.string.byteslice(@scanner.pos - @length, @length)
|
|
50
|
+
last_str.tr! "\\", ""
|
|
51
|
+
-last_str
|
|
35
52
|
end
|
|
36
53
|
|
|
37
54
|
private
|
|
38
|
-
# takes advantage of String @- deduping capabilities in Ruby 2.5 upwards see:
|
|
39
|
-
# https://bugs.ruby-lang.org/issues/13077
|
|
40
|
-
def dedup_scan(regex)
|
|
41
|
-
r = @ss.scan(regex)
|
|
42
|
-
r ? -r : nil
|
|
43
|
-
end
|
|
44
|
-
|
|
45
55
|
def scan
|
|
56
|
+
next_byte = @scanner.peek_byte
|
|
46
57
|
case
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
[:OR, "|"]
|
|
56
|
-
when @ss.skip(/\./)
|
|
57
|
-
[:DOT, "."]
|
|
58
|
-
when text = dedup_scan(/:\w+/)
|
|
59
|
-
[:SYMBOL, text]
|
|
60
|
-
when text = dedup_scan(/\*\w+/)
|
|
61
|
-
[:STAR, text]
|
|
62
|
-
when text = @ss.scan(/(?:[\w%\-~!$&'*+,;=@]|\\[:()])+/)
|
|
63
|
-
text.tr! "\\", ""
|
|
64
|
-
[:LITERAL, -text]
|
|
65
|
-
# any char
|
|
66
|
-
when text = dedup_scan(/./)
|
|
67
|
-
[:LITERAL, text]
|
|
58
|
+
when (token = STATIC_TOKENS[next_byte]) && (token != :SYMBOL || next_byte_is_not_a_token?)
|
|
59
|
+
@scanner.pos += 1
|
|
60
|
+
@length = @scanner.skip(/\w+/).to_i + 1 if token == :SYMBOL || token == :STAR
|
|
61
|
+
token
|
|
62
|
+
when @length = @scanner.skip(/(?:[\w%\-~!$&'*+,;=@]|\\[:()])+/)
|
|
63
|
+
:LITERAL
|
|
64
|
+
when @length = @scanner.skip(/./)
|
|
65
|
+
:LITERAL
|
|
68
66
|
end
|
|
69
67
|
end
|
|
68
|
+
|
|
69
|
+
def next_byte_is_not_a_token?
|
|
70
|
+
!STATIC_TOKENS[@scanner.string.getbyte(@scanner.pos + 1)]
|
|
71
|
+
end
|
|
70
72
|
end
|
|
71
73
|
end
|
|
72
74
|
end
|
|
@@ -116,13 +116,15 @@ module ActionDispatch
|
|
|
116
116
|
# cookies[:login] = { value: "XJ-122", expires: Time.utc(2020, 10, 15, 5) }
|
|
117
117
|
#
|
|
118
118
|
# # Sets a signed cookie, which prevents users from tampering with its value.
|
|
119
|
-
# # It can be read using the signed method `cookies.signed[:name]`
|
|
120
119
|
# cookies.signed[:user_id] = current_user.id
|
|
120
|
+
# # It can be read using the signed method.
|
|
121
|
+
# cookies.signed[:user_id] # => 123
|
|
121
122
|
#
|
|
122
123
|
# # Sets an encrypted cookie value before sending it to the client which
|
|
123
124
|
# # prevent users from reading and tampering with its value.
|
|
124
|
-
# # It can be read using the encrypted method `cookies.encrypted[:name]`
|
|
125
125
|
# cookies.encrypted[:discount] = 45
|
|
126
|
+
# # It can be read using the encrypted method.
|
|
127
|
+
# cookies.encrypted[:discount] # => 45
|
|
126
128
|
#
|
|
127
129
|
# # Sets a "permanent" cookie (which expires in 20 years from now).
|
|
128
130
|
# cookies.permanent[:login] = "XJ-122"
|
|
@@ -65,7 +65,9 @@ module ActionDispatch
|
|
|
65
65
|
content_type = Mime[:text]
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
if
|
|
68
|
+
if request.raw_request_method == "HEAD"
|
|
69
|
+
render(wrapper.status_code, "", content_type)
|
|
70
|
+
elsif api_request?(content_type)
|
|
69
71
|
render_for_api_request(content_type, wrapper)
|
|
70
72
|
else
|
|
71
73
|
render_for_browser_request(request, wrapper)
|
|
@@ -142,17 +144,30 @@ module ActionDispatch
|
|
|
142
144
|
|
|
143
145
|
message = []
|
|
144
146
|
message << " "
|
|
145
|
-
message << "#{wrapper.exception_class_name} (#{wrapper.message}):"
|
|
146
147
|
if wrapper.has_cause?
|
|
147
|
-
message << "
|
|
148
|
+
message << "#{wrapper.exception_class_name} (#{wrapper.message})"
|
|
148
149
|
wrapper.wrapped_causes.each do |wrapped_cause|
|
|
149
|
-
message << "#{wrapped_cause.exception_class_name} (#{wrapped_cause.message})"
|
|
150
|
+
message << "Caused by: #{wrapped_cause.exception_class_name} (#{wrapped_cause.message})"
|
|
150
151
|
end
|
|
152
|
+
|
|
153
|
+
message << "\nInformation for: #{wrapper.exception_class_name} (#{wrapper.message}):"
|
|
154
|
+
else
|
|
155
|
+
message << "#{wrapper.exception_class_name} (#{wrapper.message}):"
|
|
151
156
|
end
|
|
157
|
+
|
|
152
158
|
message.concat(wrapper.annotated_source_code)
|
|
153
159
|
message << " "
|
|
154
160
|
message.concat(trace)
|
|
155
161
|
|
|
162
|
+
if wrapper.has_cause?
|
|
163
|
+
wrapper.wrapped_causes.each do |wrapped_cause|
|
|
164
|
+
message << "\nInformation for cause: #{wrapped_cause.exception_class_name} (#{wrapped_cause.message}):"
|
|
165
|
+
message.concat(wrapped_cause.annotated_source_code)
|
|
166
|
+
message << " "
|
|
167
|
+
message.concat(wrapped_cause.exception_trace)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
156
171
|
log_array(logger, message, request)
|
|
157
172
|
end
|
|
158
173
|
|
|
@@ -15,17 +15,12 @@ module ActionDispatch
|
|
|
15
15
|
paths = RESCUES_TEMPLATE_PATHS.dup
|
|
16
16
|
lookup_context = ActionView::LookupContext.new(paths)
|
|
17
17
|
super(lookup_context, assigns, nil)
|
|
18
|
-
@exception_wrapper = assigns[:exception_wrapper]
|
|
19
18
|
end
|
|
20
19
|
|
|
21
20
|
def compiled_method_container
|
|
22
21
|
self.class
|
|
23
22
|
end
|
|
24
23
|
|
|
25
|
-
def error_highlight_available?
|
|
26
|
-
@exception_wrapper.error_highlight_available?
|
|
27
|
-
end
|
|
28
|
-
|
|
29
24
|
def debug_params(params)
|
|
30
25
|
clean_params = params.clone
|
|
31
26
|
clean_params.delete("action")
|
|
@@ -18,8 +18,8 @@ module ActionDispatch
|
|
|
18
18
|
"ActionController::UnknownFormat" => :not_acceptable,
|
|
19
19
|
"ActionDispatch::Http::MimeNegotiation::InvalidType" => :not_acceptable,
|
|
20
20
|
"ActionController::MissingExactTemplate" => :not_acceptable,
|
|
21
|
-
"ActionController::InvalidAuthenticityToken" =>
|
|
22
|
-
"ActionController::InvalidCrossOriginRequest" =>
|
|
21
|
+
"ActionController::InvalidAuthenticityToken" => ActionDispatch::Constants::UNPROCESSABLE_CONTENT,
|
|
22
|
+
"ActionController::InvalidCrossOriginRequest" => ActionDispatch::Constants::UNPROCESSABLE_CONTENT,
|
|
23
23
|
"ActionDispatch::Http::Parameters::ParseError" => :bad_request,
|
|
24
24
|
"ActionController::BadRequest" => :bad_request,
|
|
25
25
|
"ActionController::ParameterMissing" => :bad_request,
|
|
@@ -173,7 +173,7 @@ module ActionDispatch
|
|
|
173
173
|
end
|
|
174
174
|
|
|
175
175
|
def self.status_code_for_exception(class_name)
|
|
176
|
-
|
|
176
|
+
ActionDispatch::Response.rack_status_code(@@rescue_responses[class_name])
|
|
177
177
|
end
|
|
178
178
|
|
|
179
179
|
def show?(request)
|
|
@@ -201,12 +201,6 @@ module ActionDispatch
|
|
|
201
201
|
end
|
|
202
202
|
end
|
|
203
203
|
|
|
204
|
-
def error_highlight_available?
|
|
205
|
-
# ErrorHighlight.spot with backtrace_location keyword is available since
|
|
206
|
-
# error_highlight 0.4.0
|
|
207
|
-
defined?(ErrorHighlight) && Gem::Version.new(ErrorHighlight::VERSION) >= Gem::Version.new("0.4.0")
|
|
208
|
-
end
|
|
209
|
-
|
|
210
204
|
def trace_to_show
|
|
211
205
|
if traces["Application Trace"].empty? && rescue_template != "routing_error"
|
|
212
206
|
"Full Trace"
|
|
@@ -21,8 +21,11 @@ module ActionDispatch
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
returned = response << ::Rack::BodyProxy.new(response.pop) { state.complete! }
|
|
24
|
-
rescue => error
|
|
25
|
-
|
|
24
|
+
rescue Exception => error
|
|
25
|
+
request = ActionDispatch::Request.new env
|
|
26
|
+
backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner")
|
|
27
|
+
wrapper = ExceptionWrapper.new(backtrace_cleaner, error)
|
|
28
|
+
@executor.error_reporter.report(wrapper.unwrapped_exception, handled: false, source: "application.action_dispatch")
|
|
26
29
|
raise
|
|
27
30
|
ensure
|
|
28
31
|
state.complete! unless returned
|
|
@@ -32,7 +32,11 @@ module ActionDispatch
|
|
|
32
32
|
end
|
|
33
33
|
body = { status: status, error: Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500]) }
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
if env["action_dispatch.original_request_method"] == "HEAD"
|
|
36
|
+
render_format(status, content_type, "")
|
|
37
|
+
else
|
|
38
|
+
render(status, content_type, body)
|
|
39
|
+
end
|
|
36
40
|
end
|
|
37
41
|
|
|
38
42
|
private
|
|
@@ -25,11 +25,12 @@ module ActionDispatch
|
|
|
25
25
|
def initialize(app, header:)
|
|
26
26
|
@app = app
|
|
27
27
|
@header = header
|
|
28
|
+
@env_header = "HTTP_#{header.upcase.tr("-", "_")}"
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
def call(env)
|
|
31
32
|
req = ActionDispatch::Request.new env
|
|
32
|
-
req.request_id = make_request_id(req.
|
|
33
|
+
req.request_id = make_request_id(req.get_header(@env_header))
|
|
33
34
|
@app.call(env).tap { |_status, headers, _body| headers[@header] = req.request_id }
|
|
34
35
|
end
|
|
35
36
|
|
|
@@ -11,9 +11,11 @@ module ActionDispatch
|
|
|
11
11
|
#
|
|
12
12
|
# 1. **TLS redirect**: Permanently redirects `http://` requests to `https://`
|
|
13
13
|
# with the same URL host, path, etc. Enabled by default. Set
|
|
14
|
-
# `config.ssl_options` to modify the destination URL
|
|
15
|
-
#
|
|
16
|
-
#
|
|
14
|
+
# `config.ssl_options` to modify the destination URL:
|
|
15
|
+
#
|
|
16
|
+
# config.ssl_options = { redirect: { host: "secure.widgets.com", port: 8080 }`
|
|
17
|
+
#
|
|
18
|
+
# Or set `redirect: false` to disable redirection.
|
|
17
19
|
#
|
|
18
20
|
# Requests can opt-out of redirection with `exclude`:
|
|
19
21
|
#
|
|
@@ -21,6 +23,14 @@ module ActionDispatch
|
|
|
21
23
|
#
|
|
22
24
|
# Cookies will not be flagged as secure for excluded requests.
|
|
23
25
|
#
|
|
26
|
+
# When proxying through a load balancer that terminates SSL, the forwarded
|
|
27
|
+
# request will appear as though it's HTTP instead of HTTPS to the application.
|
|
28
|
+
# This makes redirects and cookie security target HTTP instead of HTTPS.
|
|
29
|
+
# To make the server assume that the proxy already terminated SSL, and
|
|
30
|
+
# that the request really is HTTPS, set `config.assume_ssl` to `true`:
|
|
31
|
+
#
|
|
32
|
+
# config.assume_ssl = true
|
|
33
|
+
#
|
|
24
34
|
# 2. **Secure cookies**: Sets the `secure` flag on cookies to tell browsers
|
|
25
35
|
# they must not be sent along with `http://` requests. Enabled by default.
|
|
26
36
|
# Set `config.ssl_options` with `secure_cookies: false` to disable this
|
|
@@ -28,9 +28,6 @@
|
|
|
28
28
|
</tr>
|
|
29
29
|
</table>
|
|
30
30
|
</div>
|
|
31
|
-
<%- unless self.error_highlight_available? -%>
|
|
32
|
-
<p class="error_highlight_tip">Tip: You may want to add <code>gem "error_highlight", ">= 0.4.0"</code> into your Gemfile, which will display the fine-grained error location.</p>
|
|
33
|
-
<%- end -%>
|
|
34
31
|
</div>
|
|
35
32
|
<% end %>
|
|
36
33
|
<% end %>
|