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.

Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +553 -401
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -3
  5. data/lib/abstract_controller/base.rb +28 -38
  6. data/lib/{action_controller → abstract_controller}/caching/fragments.rb +51 -11
  7. data/lib/abstract_controller/caching.rb +62 -0
  8. data/lib/abstract_controller/callbacks.rb +52 -19
  9. data/lib/abstract_controller/collector.rb +4 -9
  10. data/lib/abstract_controller/error.rb +4 -0
  11. data/lib/abstract_controller/helpers.rb +4 -3
  12. data/lib/abstract_controller/railties/routes_helpers.rb +2 -2
  13. data/lib/abstract_controller/rendering.rb +28 -18
  14. data/lib/abstract_controller/translation.rb +8 -7
  15. data/lib/abstract_controller.rb +6 -2
  16. data/lib/action_controller/api/api_rendering.rb +14 -0
  17. data/lib/action_controller/api.rb +147 -0
  18. data/lib/action_controller/base.rb +10 -13
  19. data/lib/action_controller/caching.rb +13 -58
  20. data/lib/action_controller/form_builder.rb +48 -0
  21. data/lib/action_controller/log_subscriber.rb +3 -10
  22. data/lib/action_controller/metal/basic_implicit_render.rb +11 -0
  23. data/lib/action_controller/metal/conditional_get.rb +106 -34
  24. data/lib/action_controller/metal/cookies.rb +1 -3
  25. data/lib/action_controller/metal/data_streaming.rb +11 -32
  26. data/lib/action_controller/metal/etag_with_template_digest.rb +1 -1
  27. data/lib/action_controller/metal/exceptions.rb +11 -6
  28. data/lib/action_controller/metal/force_ssl.rb +10 -10
  29. data/lib/action_controller/metal/head.rb +14 -8
  30. data/lib/action_controller/metal/helpers.rb +15 -6
  31. data/lib/action_controller/metal/http_authentication.rb +44 -35
  32. data/lib/action_controller/metal/implicit_render.rb +61 -6
  33. data/lib/action_controller/metal/instrumentation.rb +5 -5
  34. data/lib/action_controller/metal/live.rb +66 -88
  35. data/lib/action_controller/metal/mime_responds.rb +27 -42
  36. data/lib/action_controller/metal/params_wrapper.rb +8 -8
  37. data/lib/action_controller/metal/redirecting.rb +32 -9
  38. data/lib/action_controller/metal/renderers.rb +85 -40
  39. data/lib/action_controller/metal/rendering.rb +38 -6
  40. data/lib/action_controller/metal/request_forgery_protection.rb +126 -48
  41. data/lib/action_controller/metal/rescue.rb +3 -12
  42. data/lib/action_controller/metal/streaming.rb +4 -4
  43. data/lib/action_controller/metal/strong_parameters.rb +293 -90
  44. data/lib/action_controller/metal/testing.rb +1 -12
  45. data/lib/action_controller/metal/url_for.rb +12 -5
  46. data/lib/action_controller/metal.rb +88 -63
  47. data/lib/action_controller/renderer.rb +111 -0
  48. data/lib/action_controller/template_assertions.rb +9 -0
  49. data/lib/action_controller/test_case.rb +288 -368
  50. data/lib/action_controller.rb +12 -9
  51. data/lib/action_dispatch/http/cache.rb +73 -34
  52. data/lib/action_dispatch/http/filter_parameters.rb +15 -11
  53. data/lib/action_dispatch/http/filter_redirect.rb +7 -8
  54. data/lib/action_dispatch/http/headers.rb +44 -13
  55. data/lib/action_dispatch/http/mime_negotiation.rb +41 -23
  56. data/lib/action_dispatch/http/mime_type.rb +126 -90
  57. data/lib/action_dispatch/http/mime_types.rb +3 -4
  58. data/lib/action_dispatch/http/parameter_filter.rb +18 -8
  59. data/lib/action_dispatch/http/parameters.rb +54 -41
  60. data/lib/action_dispatch/http/request.rb +149 -82
  61. data/lib/action_dispatch/http/response.rb +206 -102
  62. data/lib/action_dispatch/http/url.rb +117 -8
  63. data/lib/action_dispatch/journey/formatter.rb +39 -28
  64. data/lib/action_dispatch/journey/gtg/transition_table.rb +1 -1
  65. data/lib/action_dispatch/journey/nfa/dot.rb +0 -2
  66. data/lib/action_dispatch/journey/nfa/transition_table.rb +1 -46
  67. data/lib/action_dispatch/journey/nodes/node.rb +14 -4
  68. data/lib/action_dispatch/journey/parser_extras.rb +4 -0
  69. data/lib/action_dispatch/journey/path/pattern.rb +38 -42
  70. data/lib/action_dispatch/journey/route.rb +74 -19
  71. data/lib/action_dispatch/journey/router/utils.rb +5 -5
  72. data/lib/action_dispatch/journey/router.rb +5 -9
  73. data/lib/action_dispatch/journey/routes.rb +14 -15
  74. data/lib/action_dispatch/journey/visitors.rb +86 -43
  75. data/lib/action_dispatch/middleware/callbacks.rb +10 -1
  76. data/lib/action_dispatch/middleware/cookies.rb +189 -135
  77. data/lib/action_dispatch/middleware/debug_exceptions.rb +124 -49
  78. data/lib/action_dispatch/middleware/exception_wrapper.rb +21 -21
  79. data/lib/action_dispatch/middleware/executor.rb +19 -0
  80. data/lib/action_dispatch/middleware/flash.rb +66 -45
  81. data/lib/action_dispatch/middleware/params_parser.rb +32 -46
  82. data/lib/action_dispatch/middleware/public_exceptions.rb +2 -2
  83. data/lib/action_dispatch/middleware/reloader.rb +14 -58
  84. data/lib/action_dispatch/middleware/remote_ip.rb +29 -19
  85. data/lib/action_dispatch/middleware/request_id.rb +11 -6
  86. data/lib/action_dispatch/middleware/session/abstract_store.rb +23 -11
  87. data/lib/action_dispatch/middleware/session/cache_store.rb +9 -6
  88. data/lib/action_dispatch/middleware/session/cookie_store.rb +30 -24
  89. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +4 -0
  90. data/lib/action_dispatch/middleware/show_exceptions.rb +11 -9
  91. data/lib/action_dispatch/middleware/ssl.rb +115 -36
  92. data/lib/action_dispatch/middleware/stack.rb +44 -40
  93. data/lib/action_dispatch/middleware/static.rb +51 -35
  94. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +2 -14
  95. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  96. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +1 -1
  97. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
  98. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
  99. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +59 -63
  100. data/lib/action_dispatch/railtie.rb +2 -2
  101. data/lib/action_dispatch/request/session.rb +69 -33
  102. data/lib/action_dispatch/request/utils.rb +51 -19
  103. data/lib/action_dispatch/routing/inspector.rb +32 -43
  104. data/lib/action_dispatch/routing/mapper.rb +491 -338
  105. data/lib/action_dispatch/routing/polymorphic_routes.rb +8 -14
  106. data/lib/action_dispatch/routing/redirection.rb +3 -3
  107. data/lib/action_dispatch/routing/route_set.rb +145 -238
  108. data/lib/action_dispatch/routing/url_for.rb +27 -10
  109. data/lib/action_dispatch/routing.rb +17 -13
  110. data/lib/action_dispatch/testing/assertion_response.rb +45 -0
  111. data/lib/action_dispatch/testing/assertions/response.rb +38 -20
  112. data/lib/action_dispatch/testing/assertions/routing.rb +11 -10
  113. data/lib/action_dispatch/testing/assertions.rb +1 -1
  114. data/lib/action_dispatch/testing/integration.rb +368 -97
  115. data/lib/action_dispatch/testing/test_process.rb +5 -6
  116. data/lib/action_dispatch/testing/test_request.rb +22 -31
  117. data/lib/action_dispatch/testing/test_response.rb +7 -4
  118. data/lib/action_dispatch.rb +3 -1
  119. data/lib/action_pack/gem_version.rb +3 -3
  120. data/lib/action_pack.rb +1 -1
  121. metadata +30 -34
  122. data/lib/action_controller/metal/hide_actions.rb +0 -40
  123. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  124. data/lib/action_controller/middleware.rb +0 -39
  125. data/lib/action_controller/model_naming.rb +0 -12
  126. data/lib/action_dispatch/journey/backwards.rb +0 -5
  127. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  128. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  129. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  130. data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
  131. /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
- def initialize(app, routes_app = nil)
12
- @app = app
13
- @routes_app = routes_app
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 if env['action_dispatch.show_exceptions'] == false
27
- render_exception(env, 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(env, exception)
33
- wrapper = ExceptionWrapper.new(env, exception)
34
- log_error(env, wrapper)
35
-
36
- if env['action_dispatch.show_detailed_exceptions']
37
- request = Request.new(env)
38
- traces = wrapper.traces
39
-
40
- trace_to_show = 'Application Trace'
41
- if traces[trace_to_show].empty? && wrapper.rescue_template != 'routing_error'
42
- trace_to_show = 'Full Trace'
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
- if source_to_show = traces[trace_to_show].first
46
- source_to_show_id = source_to_show[:id]
47
- end
81
+ def render_for_default_application(request, wrapper)
82
+ template = create_template(request, wrapper)
83
+ file = "rescues/#{wrapper.rescue_template}"
48
84
 
49
- template = ActionView::Base.new([RESCUES_TEMPLATE_PATH],
50
- request: request,
51
- exception: wrapper.exception,
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
- raise exception
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(env, wrapper)
80
- logger = logger(env)
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
- message = "\n#{exception.class} (#{exception.message}):\n"
90
- message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code)
91
- message << " " << trace.join("\n ")
92
- logger.fatal("#{message}\n\n")
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(env)
97
- env['action_dispatch.logger'] || stderr_logger
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 :env, :exception, :line_number, :file
33
+ attr_reader :backtrace_cleaner, :exception, :line_number, :file
32
34
 
33
- def initialize(env, exception)
34
- @env = env
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.try(:original_exception).try(:is_a?, SyntaxError)
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
- appplication_trace_with_ids = []
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
- appplication_trace_with_ids << trace_with_id
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" => appplication_trace_with_ids,
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, line = trace.split(":")
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 registered_original_exception?(exception)
108
- exception.original_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
- flash = case value
84
- when FlashHash # Rails 3.1, 3.2
85
- new(value.instance_variable_get(:@flashes), value.instance_variable_get(:@used))
86
- when Hash # Rails 4.0
87
- new(value['flashes'], value['discard'])
88
- else
89
- new
90
- end
91
-
92
- flash.tap(&:sweep)
93
- end
94
-
95
- # Builds a hash containing the discarded values and the hashes
96
- # representing the flashes.
97
- # If there are no values in @flashes, returns nil.
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
- return nil if empty?
100
- {'discard' => @discard.to_a, 'flashes' => @flashes}
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 initialize(app)
256
- @app = app
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
- if (!session.respond_to?(:loaded?) || session.loaded?) && # (reset_session uses {}, which doesn't implement #loaded?)
271
- session.key?('flash') && session['flash'].nil?
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
- super(message)
12
- @original_exception = original_exception
13
- end
14
- end
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
- case strategy
41
- when Proc
42
- strategy.call(request.raw_post)
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
- raise ParseError.new(e.message, e)
26
+ super($!.message)
54
27
  end
55
28
 
56
- def logger(env)
57
- env['action_dispatch.logger'] || ActiveSupport::Logger.new($stderr)
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.to_i, Rack::Utils::HTTP_STATUS_CODES[500]) }
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