actionpack 4.2.10 → 5.0.0
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 +553 -401
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -3
- data/lib/abstract_controller/base.rb +28 -38
- data/lib/{action_controller → abstract_controller}/caching/fragments.rb +51 -11
- data/lib/abstract_controller/caching.rb +62 -0
- data/lib/abstract_controller/callbacks.rb +52 -19
- data/lib/abstract_controller/collector.rb +4 -9
- data/lib/abstract_controller/error.rb +4 -0
- data/lib/abstract_controller/helpers.rb +4 -3
- data/lib/abstract_controller/railties/routes_helpers.rb +2 -2
- data/lib/abstract_controller/rendering.rb +28 -18
- data/lib/abstract_controller/translation.rb +8 -7
- data/lib/abstract_controller.rb +6 -2
- data/lib/action_controller/api/api_rendering.rb +14 -0
- data/lib/action_controller/api.rb +147 -0
- data/lib/action_controller/base.rb +10 -13
- data/lib/action_controller/caching.rb +13 -58
- data/lib/action_controller/form_builder.rb +48 -0
- data/lib/action_controller/log_subscriber.rb +3 -10
- data/lib/action_controller/metal/basic_implicit_render.rb +11 -0
- data/lib/action_controller/metal/conditional_get.rb +106 -34
- data/lib/action_controller/metal/cookies.rb +1 -3
- data/lib/action_controller/metal/data_streaming.rb +11 -32
- data/lib/action_controller/metal/etag_with_template_digest.rb +1 -1
- data/lib/action_controller/metal/exceptions.rb +11 -6
- data/lib/action_controller/metal/force_ssl.rb +10 -10
- data/lib/action_controller/metal/head.rb +14 -8
- data/lib/action_controller/metal/helpers.rb +15 -6
- data/lib/action_controller/metal/http_authentication.rb +44 -35
- data/lib/action_controller/metal/implicit_render.rb +61 -6
- data/lib/action_controller/metal/instrumentation.rb +5 -5
- data/lib/action_controller/metal/live.rb +66 -88
- data/lib/action_controller/metal/mime_responds.rb +27 -42
- data/lib/action_controller/metal/params_wrapper.rb +8 -8
- data/lib/action_controller/metal/redirecting.rb +32 -9
- data/lib/action_controller/metal/renderers.rb +85 -40
- data/lib/action_controller/metal/rendering.rb +38 -6
- data/lib/action_controller/metal/request_forgery_protection.rb +126 -48
- data/lib/action_controller/metal/rescue.rb +3 -12
- data/lib/action_controller/metal/streaming.rb +4 -4
- data/lib/action_controller/metal/strong_parameters.rb +293 -90
- data/lib/action_controller/metal/testing.rb +1 -12
- data/lib/action_controller/metal/url_for.rb +12 -5
- data/lib/action_controller/metal.rb +88 -63
- data/lib/action_controller/renderer.rb +111 -0
- data/lib/action_controller/template_assertions.rb +9 -0
- data/lib/action_controller/test_case.rb +288 -368
- data/lib/action_controller.rb +12 -9
- data/lib/action_dispatch/http/cache.rb +73 -34
- data/lib/action_dispatch/http/filter_parameters.rb +15 -11
- data/lib/action_dispatch/http/filter_redirect.rb +7 -8
- data/lib/action_dispatch/http/headers.rb +44 -13
- data/lib/action_dispatch/http/mime_negotiation.rb +41 -23
- data/lib/action_dispatch/http/mime_type.rb +126 -90
- data/lib/action_dispatch/http/mime_types.rb +3 -4
- data/lib/action_dispatch/http/parameter_filter.rb +18 -8
- data/lib/action_dispatch/http/parameters.rb +54 -41
- data/lib/action_dispatch/http/request.rb +149 -82
- data/lib/action_dispatch/http/response.rb +206 -102
- data/lib/action_dispatch/http/url.rb +117 -8
- data/lib/action_dispatch/journey/formatter.rb +39 -28
- data/lib/action_dispatch/journey/gtg/transition_table.rb +1 -1
- data/lib/action_dispatch/journey/nfa/dot.rb +0 -2
- data/lib/action_dispatch/journey/nfa/transition_table.rb +1 -46
- data/lib/action_dispatch/journey/nodes/node.rb +14 -4
- data/lib/action_dispatch/journey/parser_extras.rb +4 -0
- data/lib/action_dispatch/journey/path/pattern.rb +38 -42
- data/lib/action_dispatch/journey/route.rb +74 -19
- data/lib/action_dispatch/journey/router/utils.rb +5 -5
- data/lib/action_dispatch/journey/router.rb +5 -9
- data/lib/action_dispatch/journey/routes.rb +14 -15
- data/lib/action_dispatch/journey/visitors.rb +86 -43
- data/lib/action_dispatch/middleware/callbacks.rb +10 -1
- data/lib/action_dispatch/middleware/cookies.rb +189 -135
- data/lib/action_dispatch/middleware/debug_exceptions.rb +124 -49
- data/lib/action_dispatch/middleware/exception_wrapper.rb +21 -21
- data/lib/action_dispatch/middleware/executor.rb +19 -0
- data/lib/action_dispatch/middleware/flash.rb +66 -45
- data/lib/action_dispatch/middleware/params_parser.rb +32 -46
- data/lib/action_dispatch/middleware/public_exceptions.rb +2 -2
- data/lib/action_dispatch/middleware/reloader.rb +14 -58
- data/lib/action_dispatch/middleware/remote_ip.rb +29 -19
- data/lib/action_dispatch/middleware/request_id.rb +11 -6
- data/lib/action_dispatch/middleware/session/abstract_store.rb +23 -11
- data/lib/action_dispatch/middleware/session/cache_store.rb +9 -6
- data/lib/action_dispatch/middleware/session/cookie_store.rb +30 -24
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +4 -0
- data/lib/action_dispatch/middleware/show_exceptions.rb +11 -9
- data/lib/action_dispatch/middleware/ssl.rb +115 -36
- data/lib/action_dispatch/middleware/stack.rb +44 -40
- data/lib/action_dispatch/middleware/static.rb +51 -35
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +2 -14
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +59 -63
- data/lib/action_dispatch/railtie.rb +2 -2
- data/lib/action_dispatch/request/session.rb +69 -33
- data/lib/action_dispatch/request/utils.rb +51 -19
- data/lib/action_dispatch/routing/inspector.rb +32 -43
- data/lib/action_dispatch/routing/mapper.rb +491 -338
- data/lib/action_dispatch/routing/polymorphic_routes.rb +8 -14
- data/lib/action_dispatch/routing/redirection.rb +3 -3
- data/lib/action_dispatch/routing/route_set.rb +145 -238
- data/lib/action_dispatch/routing/url_for.rb +27 -10
- data/lib/action_dispatch/routing.rb +17 -13
- data/lib/action_dispatch/testing/assertion_response.rb +45 -0
- data/lib/action_dispatch/testing/assertions/response.rb +38 -20
- data/lib/action_dispatch/testing/assertions/routing.rb +11 -10
- data/lib/action_dispatch/testing/assertions.rb +1 -1
- data/lib/action_dispatch/testing/integration.rb +368 -97
- data/lib/action_dispatch/testing/test_process.rb +5 -6
- data/lib/action_dispatch/testing/test_request.rb +22 -31
- data/lib/action_dispatch/testing/test_response.rb +7 -4
- data/lib/action_dispatch.rb +3 -1
- data/lib/action_pack/gem_version.rb +3 -3
- data/lib/action_pack.rb +1 -1
- metadata +30 -34
- data/lib/action_controller/metal/hide_actions.rb +0 -40
- data/lib/action_controller/metal/rack_delegation.rb +0 -32
- data/lib/action_controller/middleware.rb +0 -39
- data/lib/action_controller/model_naming.rb +0 -12
- data/lib/action_dispatch/journey/backwards.rb +0 -5
- data/lib/action_dispatch/journey/router/strexp.rb +0 -27
- data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
- data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
- data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
- /data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +0 -0
@@ -1,6 +1,10 @@
|
|
1
1
|
require 'action_dispatch/http/request'
|
2
2
|
require 'action_dispatch/middleware/exception_wrapper'
|
3
3
|
require 'action_dispatch/routing/inspector'
|
4
|
+
require 'action_view'
|
5
|
+
require 'action_view/base'
|
6
|
+
|
7
|
+
require 'pp'
|
4
8
|
|
5
9
|
module ActionDispatch
|
6
10
|
# This middleware is responsible for logging exceptions and
|
@@ -8,12 +12,40 @@ module ActionDispatch
|
|
8
12
|
class DebugExceptions
|
9
13
|
RESCUES_TEMPLATE_PATH = File.expand_path('../templates', __FILE__)
|
10
14
|
|
11
|
-
|
12
|
-
|
13
|
-
|
15
|
+
class DebugView < ActionView::Base
|
16
|
+
def debug_params(params)
|
17
|
+
clean_params = params.clone
|
18
|
+
clean_params.delete("action")
|
19
|
+
clean_params.delete("controller")
|
20
|
+
|
21
|
+
if clean_params.empty?
|
22
|
+
'None'
|
23
|
+
else
|
24
|
+
PP.pp(clean_params, "", 200)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def debug_headers(headers)
|
29
|
+
if headers.present?
|
30
|
+
headers.inspect.gsub(',', ",\n")
|
31
|
+
else
|
32
|
+
'None'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def debug_hash(object)
|
37
|
+
object.to_hash.sort_by { |k, _| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize(app, routes_app = nil, response_format = :default)
|
42
|
+
@app = app
|
43
|
+
@routes_app = routes_app
|
44
|
+
@response_format = response_format
|
14
45
|
end
|
15
46
|
|
16
47
|
def call(env)
|
48
|
+
request = ActionDispatch::Request.new env
|
17
49
|
_, headers, body = response = @app.call(env)
|
18
50
|
|
19
51
|
if headers['X-Cascade'] == 'pass'
|
@@ -23,61 +55,99 @@ module ActionDispatch
|
|
23
55
|
|
24
56
|
response
|
25
57
|
rescue Exception => exception
|
26
|
-
raise exception
|
27
|
-
render_exception(
|
58
|
+
raise exception unless request.show_exceptions?
|
59
|
+
render_exception(request, exception)
|
28
60
|
end
|
29
61
|
|
30
62
|
private
|
31
63
|
|
32
|
-
def render_exception(
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
64
|
+
def render_exception(request, exception)
|
65
|
+
backtrace_cleaner = request.get_header('action_dispatch.backtrace_cleaner')
|
66
|
+
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
|
67
|
+
log_error(request, wrapper)
|
68
|
+
|
69
|
+
if request.get_header('action_dispatch.show_detailed_exceptions')
|
70
|
+
case @response_format
|
71
|
+
when :api
|
72
|
+
render_for_api_application(request, wrapper)
|
73
|
+
when :default
|
74
|
+
render_for_default_application(request, wrapper)
|
43
75
|
end
|
76
|
+
else
|
77
|
+
raise exception
|
78
|
+
end
|
79
|
+
end
|
44
80
|
|
45
|
-
|
46
|
-
|
47
|
-
|
81
|
+
def render_for_default_application(request, wrapper)
|
82
|
+
template = create_template(request, wrapper)
|
83
|
+
file = "rescues/#{wrapper.rescue_template}"
|
48
84
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
traces: traces,
|
53
|
-
show_source_idx: source_to_show_id,
|
54
|
-
trace_to_show: trace_to_show,
|
55
|
-
routes_inspector: routes_inspector(exception),
|
56
|
-
source_extracts: wrapper.source_extracts,
|
57
|
-
line_number: wrapper.line_number,
|
58
|
-
file: wrapper.file
|
59
|
-
)
|
60
|
-
file = "rescues/#{wrapper.rescue_template}"
|
61
|
-
|
62
|
-
if request.xhr?
|
63
|
-
body = template.render(template: file, layout: false, formats: [:text])
|
64
|
-
format = "text/plain"
|
65
|
-
else
|
66
|
-
body = template.render(template: file, layout: 'rescues/layout')
|
67
|
-
format = "text/html"
|
68
|
-
end
|
69
|
-
render(wrapper.status_code, body, format)
|
85
|
+
if request.xhr?
|
86
|
+
body = template.render(template: file, layout: false, formats: [:text])
|
87
|
+
format = "text/plain"
|
70
88
|
else
|
71
|
-
|
89
|
+
body = template.render(template: file, layout: 'rescues/layout')
|
90
|
+
format = "text/html"
|
91
|
+
end
|
92
|
+
render(wrapper.status_code, body, format)
|
93
|
+
end
|
94
|
+
|
95
|
+
def render_for_api_application(request, wrapper)
|
96
|
+
body = {
|
97
|
+
status: wrapper.status_code,
|
98
|
+
error: Rack::Utils::HTTP_STATUS_CODES.fetch(
|
99
|
+
wrapper.status_code,
|
100
|
+
Rack::Utils::HTTP_STATUS_CODES[500]
|
101
|
+
),
|
102
|
+
exception: wrapper.exception.inspect,
|
103
|
+
traces: wrapper.traces
|
104
|
+
}
|
105
|
+
|
106
|
+
content_type = request.formats.first
|
107
|
+
to_format = "to_#{content_type.to_sym}"
|
108
|
+
|
109
|
+
if content_type && body.respond_to?(to_format)
|
110
|
+
formatted_body = body.public_send(to_format)
|
111
|
+
format = content_type
|
112
|
+
else
|
113
|
+
formatted_body = body.to_json
|
114
|
+
format = Mime[:json]
|
115
|
+
end
|
116
|
+
|
117
|
+
render(wrapper.status_code, formatted_body, format)
|
118
|
+
end
|
119
|
+
|
120
|
+
def create_template(request, wrapper)
|
121
|
+
traces = wrapper.traces
|
122
|
+
|
123
|
+
trace_to_show = 'Application Trace'
|
124
|
+
if traces[trace_to_show].empty? && wrapper.rescue_template != 'routing_error'
|
125
|
+
trace_to_show = 'Full Trace'
|
72
126
|
end
|
127
|
+
|
128
|
+
if source_to_show = traces[trace_to_show].first
|
129
|
+
source_to_show_id = source_to_show[:id]
|
130
|
+
end
|
131
|
+
|
132
|
+
DebugView.new([RESCUES_TEMPLATE_PATH],
|
133
|
+
request: request,
|
134
|
+
exception: wrapper.exception,
|
135
|
+
traces: traces,
|
136
|
+
show_source_idx: source_to_show_id,
|
137
|
+
trace_to_show: trace_to_show,
|
138
|
+
routes_inspector: routes_inspector(wrapper.exception),
|
139
|
+
source_extracts: wrapper.source_extracts,
|
140
|
+
line_number: wrapper.line_number,
|
141
|
+
file: wrapper.file
|
142
|
+
)
|
73
143
|
end
|
74
144
|
|
75
145
|
def render(status, body, format)
|
76
146
|
[status, {'Content-Type' => "#{format}; charset=#{Response.default_charset}", 'Content-Length' => body.bytesize.to_s}, [body]]
|
77
147
|
end
|
78
148
|
|
79
|
-
def log_error(
|
80
|
-
logger = logger(
|
149
|
+
def log_error(request, wrapper)
|
150
|
+
logger = logger(request)
|
81
151
|
return unless logger
|
82
152
|
|
83
153
|
exception = wrapper.exception
|
@@ -86,15 +156,20 @@ module ActionDispatch
|
|
86
156
|
trace = wrapper.framework_trace if trace.empty?
|
87
157
|
|
88
158
|
ActiveSupport::Deprecation.silence do
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
logger.fatal
|
159
|
+
logger.fatal " "
|
160
|
+
logger.fatal "#{exception.class} (#{exception.message}):"
|
161
|
+
log_array logger, exception.annoted_source_code if exception.respond_to?(:annoted_source_code)
|
162
|
+
logger.fatal " "
|
163
|
+
log_array logger, trace
|
93
164
|
end
|
94
165
|
end
|
95
166
|
|
96
|
-
def logger
|
97
|
-
|
167
|
+
def log_array(logger, array)
|
168
|
+
array.map { |line| logger.fatal line }
|
169
|
+
end
|
170
|
+
|
171
|
+
def logger(request)
|
172
|
+
request.logger || ActionView::Base.logger || stderr_logger
|
98
173
|
end
|
99
174
|
|
100
175
|
def stderr_logger
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'action_controller/metal/exceptions'
|
2
1
|
require 'active_support/core_ext/module/attribute_accessors'
|
2
|
+
require 'rack/utils'
|
3
3
|
|
4
4
|
module ActionDispatch
|
5
5
|
class ExceptionWrapper
|
@@ -16,7 +16,9 @@ module ActionDispatch
|
|
16
16
|
'ActionController::InvalidCrossOriginRequest' => :unprocessable_entity,
|
17
17
|
'ActionDispatch::ParamsParser::ParseError' => :bad_request,
|
18
18
|
'ActionController::BadRequest' => :bad_request,
|
19
|
-
'ActionController::ParameterMissing' => :bad_request
|
19
|
+
'ActionController::ParameterMissing' => :bad_request,
|
20
|
+
'Rack::Utils::ParameterTypeError' => :bad_request,
|
21
|
+
'Rack::Utils::InvalidParameterError' => :bad_request
|
20
22
|
)
|
21
23
|
|
22
24
|
cattr_accessor :rescue_templates
|
@@ -28,13 +30,13 @@ module ActionDispatch
|
|
28
30
|
'ActionView::Template::Error' => 'template_error'
|
29
31
|
)
|
30
32
|
|
31
|
-
attr_reader :
|
33
|
+
attr_reader :backtrace_cleaner, :exception, :line_number, :file
|
32
34
|
|
33
|
-
def initialize(
|
34
|
-
@
|
35
|
+
def initialize(backtrace_cleaner, exception)
|
36
|
+
@backtrace_cleaner = backtrace_cleaner
|
35
37
|
@exception = original_exception(exception)
|
36
38
|
|
37
|
-
expand_backtrace if exception.is_a?(SyntaxError) || exception.
|
39
|
+
expand_backtrace if exception.is_a?(SyntaxError) || exception.cause.is_a?(SyntaxError)
|
38
40
|
end
|
39
41
|
|
40
42
|
def rescue_template
|
@@ -58,7 +60,7 @@ module ActionDispatch
|
|
58
60
|
end
|
59
61
|
|
60
62
|
def traces
|
61
|
-
|
63
|
+
application_trace_with_ids = []
|
62
64
|
framework_trace_with_ids = []
|
63
65
|
full_trace_with_ids = []
|
64
66
|
|
@@ -66,7 +68,7 @@ module ActionDispatch
|
|
66
68
|
trace_with_id = { id: idx, trace: trace }
|
67
69
|
|
68
70
|
if application_trace.include?(trace)
|
69
|
-
|
71
|
+
application_trace_with_ids << trace_with_id
|
70
72
|
else
|
71
73
|
framework_trace_with_ids << trace_with_id
|
72
74
|
end
|
@@ -75,7 +77,7 @@ module ActionDispatch
|
|
75
77
|
end
|
76
78
|
|
77
79
|
{
|
78
|
-
"Application Trace" =>
|
80
|
+
"Application Trace" => application_trace_with_ids,
|
79
81
|
"Framework Trace" => framework_trace_with_ids,
|
80
82
|
"Full Trace" => full_trace_with_ids
|
81
83
|
}
|
@@ -87,8 +89,7 @@ module ActionDispatch
|
|
87
89
|
|
88
90
|
def source_extracts
|
89
91
|
backtrace.map do |trace|
|
90
|
-
file,
|
91
|
-
line_number = line.to_i
|
92
|
+
file, line_number = extract_file_and_line_number(trace)
|
92
93
|
|
93
94
|
{
|
94
95
|
code: source_fragment(file, line_number),
|
@@ -104,17 +105,13 @@ module ActionDispatch
|
|
104
105
|
end
|
105
106
|
|
106
107
|
def original_exception(exception)
|
107
|
-
if
|
108
|
-
exception.
|
108
|
+
if @@rescue_responses.has_key?(exception.cause.class.name)
|
109
|
+
exception.cause
|
109
110
|
else
|
110
111
|
exception
|
111
112
|
end
|
112
113
|
end
|
113
114
|
|
114
|
-
def registered_original_exception?(exception)
|
115
|
-
exception.respond_to?(:original_exception) && @@rescue_responses.has_key?(exception.original_exception.class.name)
|
116
|
-
end
|
117
|
-
|
118
115
|
def clean_backtrace(*args)
|
119
116
|
if backtrace_cleaner
|
120
117
|
backtrace_cleaner.clean(backtrace, *args)
|
@@ -123,10 +120,6 @@ module ActionDispatch
|
|
123
120
|
end
|
124
121
|
end
|
125
122
|
|
126
|
-
def backtrace_cleaner
|
127
|
-
@backtrace_cleaner ||= @env['action_dispatch.backtrace_cleaner']
|
128
|
-
end
|
129
|
-
|
130
123
|
def source_fragment(path, line)
|
131
124
|
return unless Rails.respond_to?(:root) && Rails.root
|
132
125
|
full_path = Rails.root.join(path)
|
@@ -139,6 +132,13 @@ module ActionDispatch
|
|
139
132
|
end
|
140
133
|
end
|
141
134
|
|
135
|
+
def extract_file_and_line_number(trace)
|
136
|
+
# Split by the first colon followed by some digits, which works for both
|
137
|
+
# Windows and Unix path styles.
|
138
|
+
file, line = trace.match(/^(.+?):(\d+).*$/, &:captures) || trace
|
139
|
+
[file, line.to_i]
|
140
|
+
end
|
141
|
+
|
142
142
|
def expand_backtrace
|
143
143
|
@exception.backtrace.unshift(
|
144
144
|
@exception.to_s.split("\n")
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rack/body_proxy'
|
2
|
+
|
3
|
+
module ActionDispatch
|
4
|
+
class Executor
|
5
|
+
def initialize(app, executor)
|
6
|
+
@app, @executor = app, executor
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
state = @executor.run!
|
11
|
+
begin
|
12
|
+
response = @app.call(env)
|
13
|
+
returned = response << ::Rack::BodyProxy.new(response.pop) { state.complete! }
|
14
|
+
ensure
|
15
|
+
state.complete! unless returned
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,15 +1,6 @@
|
|
1
1
|
require 'active_support/core_ext/hash/keys'
|
2
2
|
|
3
3
|
module ActionDispatch
|
4
|
-
class Request < Rack::Request
|
5
|
-
# Access the contents of the flash. Use <tt>flash["notice"]</tt> to
|
6
|
-
# read a notice you put there or <tt>flash["notice"] = "hello"</tt>
|
7
|
-
# to put a new one.
|
8
|
-
def flash
|
9
|
-
@env[Flash::KEY] ||= Flash::FlashHash.from_session_value(session["flash"])
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
4
|
# The flash provides a way to pass temporary primitive-types (String, Array, Hash) between actions. Anything you place in the flash will be exposed
|
14
5
|
# to the very next action and then cleared out. This is a great way of doing notices and alerts, such as a create
|
15
6
|
# action that sets <tt>flash[:notice] = "Post successfully created"</tt> before redirecting to a display action that can
|
@@ -47,6 +38,45 @@ module ActionDispatch
|
|
47
38
|
class Flash
|
48
39
|
KEY = 'action_dispatch.request.flash_hash'.freeze
|
49
40
|
|
41
|
+
module RequestMethods
|
42
|
+
# Access the contents of the flash. Use <tt>flash["notice"]</tt> to
|
43
|
+
# read a notice you put there or <tt>flash["notice"] = "hello"</tt>
|
44
|
+
# to put a new one.
|
45
|
+
def flash
|
46
|
+
flash = flash_hash
|
47
|
+
return flash if flash
|
48
|
+
self.flash = Flash::FlashHash.from_session_value(session["flash"])
|
49
|
+
end
|
50
|
+
|
51
|
+
def flash=(flash)
|
52
|
+
set_header Flash::KEY, flash
|
53
|
+
end
|
54
|
+
|
55
|
+
def flash_hash # :nodoc:
|
56
|
+
get_header Flash::KEY
|
57
|
+
end
|
58
|
+
|
59
|
+
def commit_flash # :nodoc:
|
60
|
+
session = self.session || {}
|
61
|
+
flash_hash = self.flash_hash
|
62
|
+
|
63
|
+
if flash_hash && (flash_hash.present? || session.key?('flash'))
|
64
|
+
session["flash"] = flash_hash.to_session_value
|
65
|
+
self.flash = flash_hash.dup
|
66
|
+
end
|
67
|
+
|
68
|
+
if (!session.respond_to?(:loaded?) || session.loaded?) && # (reset_session uses {}, which doesn't implement #loaded?)
|
69
|
+
session.key?('flash') && session['flash'].nil?
|
70
|
+
session.delete('flash')
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def reset_session # :nodoc
|
75
|
+
super
|
76
|
+
self.flash = nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
50
80
|
class FlashNow #:nodoc:
|
51
81
|
attr_accessor :flash
|
52
82
|
|
@@ -80,24 +110,30 @@ module ActionDispatch
|
|
80
110
|
include Enumerable
|
81
111
|
|
82
112
|
def self.from_session_value(value) #:nodoc:
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
113
|
+
case value
|
114
|
+
when FlashHash # Rails 3.1, 3.2
|
115
|
+
flashes = value.instance_variable_get(:@flashes)
|
116
|
+
if discard = value.instance_variable_get(:@used)
|
117
|
+
flashes.except!(*discard)
|
118
|
+
end
|
119
|
+
new(flashes, flashes.keys)
|
120
|
+
when Hash # Rails 4.0
|
121
|
+
flashes = value['flashes']
|
122
|
+
if discard = value['discard']
|
123
|
+
flashes.except!(*discard)
|
124
|
+
end
|
125
|
+
new(flashes, flashes.keys)
|
126
|
+
else
|
127
|
+
new
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Builds a hash containing the flashes to keep for the next request.
|
132
|
+
# If there are none to keep, returns nil.
|
98
133
|
def to_session_value #:nodoc:
|
99
|
-
|
100
|
-
|
134
|
+
flashes_to_keep = @flashes.except(*@discard)
|
135
|
+
return nil if flashes_to_keep.empty?
|
136
|
+
{ 'discard' => [], 'flashes' => flashes_to_keep }
|
101
137
|
end
|
102
138
|
|
103
139
|
def initialize(flashes = {}, discard = []) #:nodoc:
|
@@ -252,25 +288,10 @@ module ActionDispatch
|
|
252
288
|
end
|
253
289
|
end
|
254
290
|
|
255
|
-
def
|
256
|
-
|
257
|
-
end
|
258
|
-
|
259
|
-
def call(env)
|
260
|
-
@app.call(env)
|
261
|
-
ensure
|
262
|
-
session = Request::Session.find(env) || {}
|
263
|
-
flash_hash = env[KEY]
|
264
|
-
|
265
|
-
if flash_hash && (flash_hash.present? || session.key?('flash'))
|
266
|
-
session["flash"] = flash_hash.to_session_value
|
267
|
-
env[KEY] = flash_hash.dup
|
268
|
-
end
|
291
|
+
def self.new(app) app; end
|
292
|
+
end
|
269
293
|
|
270
|
-
|
271
|
-
|
272
|
-
session.delete('flash')
|
273
|
-
end
|
274
|
-
end
|
294
|
+
class Request
|
295
|
+
prepend Flash::RequestMethods
|
275
296
|
end
|
276
297
|
end
|
@@ -1,60 +1,46 @@
|
|
1
|
-
require 'active_support/core_ext/hash/conversions'
|
2
1
|
require 'action_dispatch/http/request'
|
3
|
-
require 'active_support/core_ext/hash/indifferent_access'
|
4
2
|
|
5
3
|
module ActionDispatch
|
4
|
+
# ActionDispatch::ParamsParser works for all the requests having any Content-Length
|
5
|
+
# (like POST). It takes raw data from the request and puts it through the parser
|
6
|
+
# that is picked based on Content-Type header.
|
7
|
+
#
|
8
|
+
# In case of any error while parsing data ParamsParser::ParseError is raised.
|
6
9
|
class ParamsParser
|
10
|
+
# Raised when raw data from the request cannot be parsed by the parser
|
11
|
+
# defined for request's content mime type.
|
7
12
|
class ParseError < StandardError
|
8
|
-
attr_reader :original_exception
|
9
13
|
|
10
|
-
def initialize(message, original_exception)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
DEFAULT_PARSERS = { Mime::JSON => :json }
|
17
|
-
|
18
|
-
def initialize(app, parsers = {})
|
19
|
-
@app, @parsers = app, DEFAULT_PARSERS.merge(parsers)
|
20
|
-
end
|
21
|
-
|
22
|
-
def call(env)
|
23
|
-
if params = parse_formatted_parameters(env)
|
24
|
-
env["action_dispatch.request.request_parameters"] = params
|
25
|
-
end
|
26
|
-
|
27
|
-
@app.call(env)
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
def parse_formatted_parameters(env)
|
32
|
-
request = Request.new(env)
|
33
|
-
|
34
|
-
return false if request.content_length.zero?
|
35
|
-
|
36
|
-
strategy = @parsers[request.content_mime_type]
|
37
|
-
|
38
|
-
return false unless strategy
|
14
|
+
def initialize(message = nil, original_exception = nil)
|
15
|
+
if message
|
16
|
+
ActiveSupport::Deprecation.warn("Passing #message is deprecated and has no effect. " \
|
17
|
+
"#{self.class} will automatically capture the message " \
|
18
|
+
"of the original exception.", caller)
|
19
|
+
end
|
39
20
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
when :json
|
44
|
-
data = ActiveSupport::JSON.decode(request.raw_post)
|
45
|
-
data = {:_json => data} unless data.is_a?(Hash)
|
46
|
-
Request::Utils.deep_munge(data).with_indifferent_access
|
47
|
-
else
|
48
|
-
false
|
21
|
+
if original_exception
|
22
|
+
ActiveSupport::Deprecation.warn("Passing #original_exception is deprecated and has no effect. " \
|
23
|
+
"Exceptions will automatically capture the original exception.", caller)
|
49
24
|
end
|
50
|
-
rescue => e # JSON or Ruby code block errors
|
51
|
-
logger(env).debug "Error occurred while parsing request parameters.\nContents:\n\n#{request.raw_post}"
|
52
25
|
|
53
|
-
|
26
|
+
super($!.message)
|
54
27
|
end
|
55
28
|
|
56
|
-
def
|
57
|
-
|
29
|
+
def original_exception
|
30
|
+
ActiveSupport::Deprecation.warn("#original_exception is deprecated. Use #cause instead.", caller)
|
31
|
+
cause
|
58
32
|
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Create a new +ParamsParser+ middleware instance.
|
36
|
+
#
|
37
|
+
# The +parsers+ argument can take Hash of parsers where key is identifying
|
38
|
+
# content mime type, and value is a lambda that is going to process data.
|
39
|
+
def self.new(app, parsers = {})
|
40
|
+
ActiveSupport::Deprecation.warn('ActionDispatch::ParamsParser is deprecated and will be removed in Rails 5.1. Configure the parameter parsing in ActionDispatch::Request.parameter_parsers.')
|
41
|
+
parsers = parsers.transform_keys { |key| key.respond_to?(:symbol) ? key.symbol : key }
|
42
|
+
ActionDispatch::Request.parameter_parsers = ActionDispatch::Request::DEFAULT_PARSERS.merge(parsers)
|
43
|
+
app
|
44
|
+
end
|
59
45
|
end
|
60
46
|
end
|
@@ -17,10 +17,10 @@ module ActionDispatch
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def call(env)
|
20
|
-
status = env["PATH_INFO"][1..-1]
|
21
20
|
request = ActionDispatch::Request.new(env)
|
21
|
+
status = request.path_info[1..-1].to_i
|
22
22
|
content_type = request.formats.first
|
23
|
-
body = { :status => status, :error => Rack::Utils::HTTP_STATUS_CODES.fetch(status
|
23
|
+
body = { :status => status, :error => Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500]) }
|
24
24
|
|
25
25
|
render(status, content_type, body)
|
26
26
|
end
|