actionpack 4.2.11.1 → 6.0.3

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 (182) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +212 -526
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +9 -9
  5. data/lib/abstract_controller/asset_paths.rb +2 -0
  6. data/lib/abstract_controller/base.rb +47 -50
  7. data/lib/{action_controller → abstract_controller}/caching/fragments.rb +64 -17
  8. data/lib/abstract_controller/caching.rb +66 -0
  9. data/lib/abstract_controller/callbacks.rb +59 -31
  10. data/lib/abstract_controller/collector.rb +9 -13
  11. data/lib/abstract_controller/error.rb +6 -0
  12. data/lib/abstract_controller/helpers.rb +31 -30
  13. data/lib/abstract_controller/logger.rb +2 -0
  14. data/lib/abstract_controller/railties/routes_helpers.rb +5 -3
  15. data/lib/abstract_controller/rendering.rb +42 -41
  16. data/lib/abstract_controller/translation.rb +12 -9
  17. data/lib/abstract_controller/url_for.rb +2 -0
  18. data/lib/abstract_controller.rb +12 -5
  19. data/lib/action_controller/api/api_rendering.rb +16 -0
  20. data/lib/action_controller/api.rb +150 -0
  21. data/lib/action_controller/base.rb +25 -22
  22. data/lib/action_controller/caching.rb +13 -57
  23. data/lib/action_controller/form_builder.rb +50 -0
  24. data/lib/action_controller/log_subscriber.rb +15 -17
  25. data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
  26. data/lib/action_controller/metal/conditional_get.rb +124 -44
  27. data/lib/action_controller/metal/content_security_policy.rb +51 -0
  28. data/lib/action_controller/metal/cookies.rb +3 -3
  29. data/lib/action_controller/metal/data_streaming.rb +29 -49
  30. data/lib/action_controller/metal/default_headers.rb +17 -0
  31. data/lib/action_controller/metal/etag_with_flash.rb +18 -0
  32. data/lib/action_controller/metal/etag_with_template_digest.rb +20 -13
  33. data/lib/action_controller/metal/exceptions.rb +30 -15
  34. data/lib/action_controller/metal/flash.rb +9 -8
  35. data/lib/action_controller/metal/force_ssl.rb +23 -62
  36. data/lib/action_controller/metal/head.rb +22 -20
  37. data/lib/action_controller/metal/helpers.rb +26 -17
  38. data/lib/action_controller/metal/http_authentication.rb +76 -70
  39. data/lib/action_controller/metal/implicit_render.rb +53 -9
  40. data/lib/action_controller/metal/instrumentation.rb +22 -27
  41. data/lib/action_controller/metal/live.rb +101 -119
  42. data/lib/action_controller/metal/mime_responds.rb +44 -46
  43. data/lib/action_controller/metal/parameter_encoding.rb +51 -0
  44. data/lib/action_controller/metal/params_wrapper.rb +74 -63
  45. data/lib/action_controller/metal/redirecting.rb +53 -32
  46. data/lib/action_controller/metal/renderers.rb +87 -44
  47. data/lib/action_controller/metal/rendering.rb +72 -51
  48. data/lib/action_controller/metal/request_forgery_protection.rb +217 -97
  49. data/lib/action_controller/metal/rescue.rb +9 -16
  50. data/lib/action_controller/metal/streaming.rb +12 -11
  51. data/lib/action_controller/metal/strong_parameters.rb +619 -183
  52. data/lib/action_controller/metal/testing.rb +2 -17
  53. data/lib/action_controller/metal/url_for.rb +19 -10
  54. data/lib/action_controller/metal.rb +104 -87
  55. data/lib/action_controller/railtie.rb +28 -10
  56. data/lib/action_controller/railties/helpers.rb +3 -1
  57. data/lib/action_controller/renderer.rb +130 -0
  58. data/lib/action_controller/template_assertions.rb +11 -0
  59. data/lib/action_controller/test_case.rb +286 -418
  60. data/lib/action_controller.rb +33 -21
  61. data/lib/action_dispatch/http/cache.rb +100 -51
  62. data/lib/action_dispatch/http/content_disposition.rb +45 -0
  63. data/lib/action_dispatch/http/content_security_policy.rb +282 -0
  64. data/lib/action_dispatch/http/filter_parameters.rb +31 -24
  65. data/lib/action_dispatch/http/filter_redirect.rb +10 -12
  66. data/lib/action_dispatch/http/headers.rb +54 -22
  67. data/lib/action_dispatch/http/mime_negotiation.rb +61 -45
  68. data/lib/action_dispatch/http/mime_type.rb +141 -122
  69. data/lib/action_dispatch/http/mime_types.rb +20 -6
  70. data/lib/action_dispatch/http/parameter_filter.rb +8 -68
  71. data/lib/action_dispatch/http/parameters.rb +107 -39
  72. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  73. data/lib/action_dispatch/http/request.rb +204 -117
  74. data/lib/action_dispatch/http/response.rb +248 -114
  75. data/lib/action_dispatch/http/upload.rb +21 -7
  76. data/lib/action_dispatch/http/url.rb +181 -100
  77. data/lib/action_dispatch/journey/formatter.rb +56 -34
  78. data/lib/action_dispatch/journey/gtg/builder.rb +7 -6
  79. data/lib/action_dispatch/journey/gtg/simulator.rb +3 -9
  80. data/lib/action_dispatch/journey/gtg/transition_table.rb +17 -17
  81. data/lib/action_dispatch/journey/nfa/builder.rb +5 -3
  82. data/lib/action_dispatch/journey/nfa/dot.rb +13 -13
  83. data/lib/action_dispatch/journey/nfa/simulator.rb +3 -3
  84. data/lib/action_dispatch/journey/nfa/transition_table.rb +5 -49
  85. data/lib/action_dispatch/journey/nodes/node.rb +25 -12
  86. data/lib/action_dispatch/journey/parser.rb +23 -22
  87. data/lib/action_dispatch/journey/parser.y +3 -2
  88. data/lib/action_dispatch/journey/parser_extras.rb +12 -4
  89. data/lib/action_dispatch/journey/path/pattern.rb +55 -46
  90. data/lib/action_dispatch/journey/route.rb +107 -28
  91. data/lib/action_dispatch/journey/router/utils.rb +25 -16
  92. data/lib/action_dispatch/journey/router.rb +35 -27
  93. data/lib/action_dispatch/journey/routes.rb +17 -17
  94. data/lib/action_dispatch/journey/scanner.rb +26 -17
  95. data/lib/action_dispatch/journey/visitors.rb +98 -54
  96. data/lib/action_dispatch/journey.rb +7 -5
  97. data/lib/action_dispatch/middleware/actionable_exceptions.rb +39 -0
  98. data/lib/action_dispatch/middleware/callbacks.rb +3 -6
  99. data/lib/action_dispatch/middleware/cookies.rb +292 -203
  100. data/lib/action_dispatch/middleware/debug_exceptions.rb +142 -63
  101. data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
  102. data/lib/action_dispatch/middleware/debug_view.rb +66 -0
  103. data/lib/action_dispatch/middleware/exception_wrapper.rb +102 -70
  104. data/lib/action_dispatch/middleware/executor.rb +21 -0
  105. data/lib/action_dispatch/middleware/flash.rb +78 -54
  106. data/lib/action_dispatch/middleware/host_authorization.rb +101 -0
  107. data/lib/action_dispatch/middleware/public_exceptions.rb +32 -27
  108. data/lib/action_dispatch/middleware/reloader.rb +5 -91
  109. data/lib/action_dispatch/middleware/remote_ip.rb +48 -41
  110. data/lib/action_dispatch/middleware/request_id.rb +17 -9
  111. data/lib/action_dispatch/middleware/session/abstract_store.rb +41 -26
  112. data/lib/action_dispatch/middleware/session/cache_store.rb +24 -14
  113. data/lib/action_dispatch/middleware/session/cookie_store.rb +72 -73
  114. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -2
  115. data/lib/action_dispatch/middleware/show_exceptions.rb +26 -23
  116. data/lib/action_dispatch/middleware/ssl.rb +113 -35
  117. data/lib/action_dispatch/middleware/stack.rb +64 -41
  118. data/lib/action_dispatch/middleware/static.rb +57 -51
  119. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  120. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  121. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +4 -14
  122. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  123. data/lib/action_dispatch/middleware/templates/rescues/{_source.erb → _source.html.erb} +4 -2
  124. data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
  125. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
  126. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
  127. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
  128. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -4
  129. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
  130. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
  131. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +15 -0
  132. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +5 -0
  133. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
  134. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  135. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +2 -2
  136. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
  137. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +3 -3
  138. data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
  139. data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +4 -4
  140. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +67 -64
  141. data/lib/action_dispatch/railtie.rb +26 -13
  142. data/lib/action_dispatch/request/session.rb +114 -60
  143. data/lib/action_dispatch/request/utils.rb +67 -24
  144. data/lib/action_dispatch/routing/endpoint.rb +9 -2
  145. data/lib/action_dispatch/routing/inspector.rb +140 -102
  146. data/lib/action_dispatch/routing/mapper.rb +762 -455
  147. data/lib/action_dispatch/routing/polymorphic_routes.rb +161 -142
  148. data/lib/action_dispatch/routing/redirection.rb +36 -26
  149. data/lib/action_dispatch/routing/route_set.rb +322 -298
  150. data/lib/action_dispatch/routing/routes_proxy.rb +32 -5
  151. data/lib/action_dispatch/routing/url_for.rb +65 -26
  152. data/lib/action_dispatch/routing.rb +36 -36
  153. data/lib/action_dispatch/system_test_case.rb +185 -0
  154. data/lib/action_dispatch/system_testing/browser.rb +80 -0
  155. data/lib/action_dispatch/system_testing/driver.rb +68 -0
  156. data/lib/action_dispatch/system_testing/server.rb +31 -0
  157. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +97 -0
  158. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +32 -0
  159. data/lib/action_dispatch/testing/assertion_response.rb +46 -0
  160. data/lib/action_dispatch/testing/assertions/response.rb +44 -20
  161. data/lib/action_dispatch/testing/assertions/routing.rb +44 -28
  162. data/lib/action_dispatch/testing/assertions.rb +6 -4
  163. data/lib/action_dispatch/testing/integration.rb +375 -215
  164. data/lib/action_dispatch/testing/request_encoder.rb +55 -0
  165. data/lib/action_dispatch/testing/test_process.rb +28 -22
  166. data/lib/action_dispatch/testing/test_request.rb +27 -34
  167. data/lib/action_dispatch/testing/test_response.rb +11 -11
  168. data/lib/action_dispatch.rb +33 -20
  169. data/lib/action_pack/gem_version.rb +6 -4
  170. data/lib/action_pack/version.rb +3 -1
  171. data/lib/action_pack.rb +4 -2
  172. metadata +71 -40
  173. data/lib/action_controller/metal/hide_actions.rb +0 -40
  174. data/lib/action_controller/metal/rack_delegation.rb +0 -32
  175. data/lib/action_controller/middleware.rb +0 -39
  176. data/lib/action_controller/model_naming.rb +0 -12
  177. data/lib/action_dispatch/journey/backwards.rb +0 -5
  178. data/lib/action_dispatch/journey/router/strexp.rb +0 -27
  179. data/lib/action_dispatch/middleware/params_parser.rb +0 -60
  180. data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
  181. data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
  182. data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,27 +1,32 @@
1
- require 'stringio'
2
-
3
- require 'active_support/inflector'
4
- require 'action_dispatch/http/headers'
5
- require 'action_controller/metal/exceptions'
6
- require 'rack/request'
7
- require 'action_dispatch/http/cache'
8
- require 'action_dispatch/http/mime_negotiation'
9
- require 'action_dispatch/http/parameters'
10
- require 'action_dispatch/http/filter_parameters'
11
- require 'action_dispatch/http/upload'
12
- require 'action_dispatch/http/url'
13
- require 'active_support/core_ext/array/conversions'
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+
5
+ require "active_support/inflector"
6
+ require "action_dispatch/http/headers"
7
+ require "action_controller/metal/exceptions"
8
+ require "rack/request"
9
+ require "action_dispatch/http/cache"
10
+ require "action_dispatch/http/mime_negotiation"
11
+ require "action_dispatch/http/parameters"
12
+ require "action_dispatch/http/filter_parameters"
13
+ require "action_dispatch/http/upload"
14
+ require "action_dispatch/http/url"
15
+ require "active_support/core_ext/array/conversions"
14
16
 
15
17
  module ActionDispatch
16
- class Request < Rack::Request
18
+ class Request
19
+ include Rack::Request::Helpers
17
20
  include ActionDispatch::Http::Cache::Request
18
21
  include ActionDispatch::Http::MimeNegotiation
19
22
  include ActionDispatch::Http::Parameters
20
23
  include ActionDispatch::Http::FilterParameters
21
24
  include ActionDispatch::Http::URL
25
+ include ActionDispatch::ContentSecurityPolicy::Request
26
+ include Rack::Request::Env
22
27
 
23
- autoload :Session, 'action_dispatch/request/session'
24
- autoload :Utils, 'action_dispatch/request/utils'
28
+ autoload :Session, "action_dispatch/request/session"
29
+ autoload :Utils, "action_dispatch/request/utils"
25
30
 
26
31
  LOCALHOST = Regexp.union [/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/, /^::1$/, /^0:0:0:0:0:0:0:1(%.*)?$/]
27
32
 
@@ -29,19 +34,28 @@ module ActionDispatch
29
34
  PATH_TRANSLATED REMOTE_HOST
30
35
  REMOTE_IDENT REMOTE_USER REMOTE_ADDR
31
36
  SERVER_NAME SERVER_PROTOCOL
37
+ ORIGINAL_SCRIPT_NAME
32
38
 
33
39
  HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
34
40
  HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM
35
- HTTP_NEGOTIATE HTTP_PRAGMA ].freeze
41
+ HTTP_NEGOTIATE HTTP_PRAGMA HTTP_CLIENT_IP
42
+ HTTP_X_FORWARDED_FOR HTTP_ORIGIN HTTP_VERSION
43
+ HTTP_X_CSRF_TOKEN HTTP_X_REQUEST_ID HTTP_X_FORWARDED_HOST
44
+ SERVER_ADDR
45
+ ].freeze
36
46
 
37
47
  ENV_METHODS.each do |env|
38
48
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
39
49
  def #{env.sub(/^HTTP_/n, '').downcase} # def accept_charset
40
- @env["#{env}"] # @env["HTTP_ACCEPT_CHARSET"]
50
+ get_header "#{env}".freeze # get_header "HTTP_ACCEPT_CHARSET".freeze
41
51
  end # end
42
52
  METHOD
43
53
  end
44
54
 
55
+ def self.empty
56
+ new({})
57
+ end
58
+
45
59
  def initialize(env)
46
60
  super
47
61
  @method = nil
@@ -50,33 +64,57 @@ module ActionDispatch
50
64
  @original_fullpath = nil
51
65
  @fullpath = nil
52
66
  @ip = nil
53
- @uuid = nil
54
67
  end
55
68
 
56
- def check_path_parameters!
57
- # If any of the path parameters has an invalid encoding then
58
- # raise since it's likely to trigger errors further on.
59
- path_parameters.each do |key, value|
60
- next unless value.respond_to?(:valid_encoding?)
61
- unless value.valid_encoding?
62
- raise ActionController::BadRequest, "Invalid parameter: #{key} => #{value}"
69
+ def commit_cookie_jar! # :nodoc:
70
+ end
71
+
72
+ PASS_NOT_FOUND = Class.new { # :nodoc:
73
+ def self.action(_); self; end
74
+ def self.call(_); [404, { "X-Cascade" => "pass" }, []]; end
75
+ def self.binary_params_for?(action); false; end
76
+ }
77
+
78
+ def controller_class
79
+ params = path_parameters
80
+ params[:action] ||= "index"
81
+ controller_class_for(params[:controller])
82
+ end
83
+
84
+ def controller_class_for(name)
85
+ if name
86
+ controller_param = name.underscore
87
+ const_name = "#{controller_param.camelize}Controller"
88
+ begin
89
+ ActiveSupport::Dependencies.constantize(const_name)
90
+ rescue NameError => error
91
+ if error.missing_name == const_name || const_name.start_with?("#{error.missing_name}::")
92
+ raise MissingController.new(error.message, error.name)
93
+ else
94
+ raise
95
+ end
63
96
  end
97
+ else
98
+ PASS_NOT_FOUND
64
99
  end
65
100
  end
66
101
 
102
+ # Returns true if the request has a header matching the given key parameter.
103
+ #
104
+ # request.key? :ip_spoofing_check # => true
67
105
  def key?(key)
68
- @env.key?(key)
106
+ has_header? key
69
107
  end
70
108
 
71
109
  # List of HTTP request methods from the following RFCs:
72
- # Hypertext Transfer Protocol -- HTTP/1.1 (http://www.ietf.org/rfc/rfc2616.txt)
73
- # HTTP Extensions for Distributed Authoring -- WEBDAV (http://www.ietf.org/rfc/rfc2518.txt)
74
- # Versioning Extensions to WebDAV (http://www.ietf.org/rfc/rfc3253.txt)
75
- # Ordered Collections Protocol (WebDAV) (http://www.ietf.org/rfc/rfc3648.txt)
76
- # Web Distributed Authoring and Versioning (WebDAV) Access Control Protocol (http://www.ietf.org/rfc/rfc3744.txt)
77
- # Web Distributed Authoring and Versioning (WebDAV) SEARCH (http://www.ietf.org/rfc/rfc5323.txt)
78
- # Calendar Extensions to WebDAV (http://www.ietf.org/rfc/rfc4791.txt)
79
- # PATCH Method for HTTP (http://www.ietf.org/rfc/rfc5789.txt)
110
+ # Hypertext Transfer Protocol -- HTTP/1.1 (https://www.ietf.org/rfc/rfc2616.txt)
111
+ # HTTP Extensions for Distributed Authoring -- WEBDAV (https://www.ietf.org/rfc/rfc2518.txt)
112
+ # Versioning Extensions to WebDAV (https://www.ietf.org/rfc/rfc3253.txt)
113
+ # Ordered Collections Protocol (WebDAV) (https://www.ietf.org/rfc/rfc3648.txt)
114
+ # Web Distributed Authoring and Versioning (WebDAV) Access Control Protocol (https://www.ietf.org/rfc/rfc3744.txt)
115
+ # Web Distributed Authoring and Versioning (WebDAV) SEARCH (https://www.ietf.org/rfc/rfc5323.txt)
116
+ # Calendar Extensions to WebDAV (https://www.ietf.org/rfc/rfc4791.txt)
117
+ # PATCH Method for HTTP (https://www.ietf.org/rfc/rfc5789.txt)
80
118
  RFC2616 = %w(OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT)
81
119
  RFC2518 = %w(PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK)
82
120
  RFC3253 = %w(VERSION-CONTROL REPORT CHECKOUT CHECKIN UNCHECKOUT MKWORKSPACE UPDATE LABEL MERGE BASELINE-CONTROL MKACTIVITY)
@@ -90,7 +128,7 @@ module ActionDispatch
90
128
 
91
129
  HTTP_METHOD_LOOKUP = {}
92
130
 
93
- # Populate the HTTP method lookup cache
131
+ # Populate the HTTP method lookup cache.
94
132
  HTTP_METHODS.each { |method|
95
133
  HTTP_METHOD_LOOKUP[method] = method.underscore.to_sym
96
134
  }
@@ -102,73 +140,89 @@ module ActionDispatch
102
140
  # the application should use), this \method returns the overridden
103
141
  # value, not the original.
104
142
  def request_method
105
- @request_method ||= check_method(env["REQUEST_METHOD"])
143
+ @request_method ||= check_method(super)
106
144
  end
107
145
 
108
- def request_method=(request_method) #:nodoc:
109
- if check_method(request_method)
110
- @request_method = env["REQUEST_METHOD"] = request_method
111
- end
146
+ def routes # :nodoc:
147
+ get_header("action_dispatch.routes")
112
148
  end
113
149
 
114
- # Returns a symbol form of the #request_method
115
- def request_method_symbol
116
- HTTP_METHOD_LOOKUP[request_method]
150
+ def routes=(routes) # :nodoc:
151
+ set_header("action_dispatch.routes", routes)
117
152
  end
118
153
 
119
- # Returns the original value of the environment's REQUEST_METHOD,
120
- # even if it was overridden by middleware. See #request_method for
121
- # more information.
122
- def method
123
- @method ||= check_method(env["rack.methodoverride.original_method"] || env['REQUEST_METHOD'])
154
+ def engine_script_name(_routes) # :nodoc:
155
+ get_header(_routes.env_key)
124
156
  end
125
157
 
126
- # Returns a symbol form of the #method
127
- def method_symbol
128
- HTTP_METHOD_LOOKUP[method]
158
+ def engine_script_name=(name) # :nodoc:
159
+ set_header(routes.env_key, name.dup)
160
+ end
161
+
162
+ def request_method=(request_method) #:nodoc:
163
+ if check_method(request_method)
164
+ @request_method = set_header("REQUEST_METHOD", request_method)
165
+ end
129
166
  end
130
167
 
131
- # Is this a GET (or HEAD) request?
132
- # Equivalent to <tt>request.request_method_symbol == :get</tt>.
133
- def get?
134
- HTTP_METHOD_LOOKUP[request_method] == :get
168
+ def controller_instance # :nodoc:
169
+ get_header("action_controller.instance")
135
170
  end
136
171
 
137
- # Is this a POST request?
138
- # Equivalent to <tt>request.request_method_symbol == :post</tt>.
139
- def post?
140
- HTTP_METHOD_LOOKUP[request_method] == :post
172
+ def controller_instance=(controller) # :nodoc:
173
+ set_header("action_controller.instance", controller)
141
174
  end
142
175
 
143
- # Is this a PATCH request?
144
- # Equivalent to <tt>request.request_method == :patch</tt>.
145
- def patch?
146
- HTTP_METHOD_LOOKUP[request_method] == :patch
176
+ def http_auth_salt
177
+ get_header "action_dispatch.http_auth_salt"
147
178
  end
148
179
 
149
- # Is this a PUT request?
150
- # Equivalent to <tt>request.request_method_symbol == :put</tt>.
151
- def put?
152
- HTTP_METHOD_LOOKUP[request_method] == :put
180
+ def show_exceptions? # :nodoc:
181
+ # We're treating `nil` as "unset", and we want the default setting to be
182
+ # `true`. This logic should be extracted to `env_config` and calculated
183
+ # once.
184
+ !(get_header("action_dispatch.show_exceptions") == false)
185
+ end
186
+
187
+ # Returns a symbol form of the #request_method.
188
+ def request_method_symbol
189
+ HTTP_METHOD_LOOKUP[request_method]
153
190
  end
154
191
 
155
- # Is this a DELETE request?
156
- # Equivalent to <tt>request.request_method_symbol == :delete</tt>.
157
- def delete?
158
- HTTP_METHOD_LOOKUP[request_method] == :delete
192
+ # Returns the original value of the environment's REQUEST_METHOD,
193
+ # even if it was overridden by middleware. See #request_method for
194
+ # more information.
195
+ def method
196
+ @method ||= check_method(get_header("rack.methodoverride.original_method") || get_header("REQUEST_METHOD"))
159
197
  end
160
198
 
161
- # Is this a HEAD request?
162
- # Equivalent to <tt>request.request_method_symbol == :head</tt>.
163
- def head?
164
- HTTP_METHOD_LOOKUP[request_method] == :head
199
+ # Returns a symbol form of the #method.
200
+ def method_symbol
201
+ HTTP_METHOD_LOOKUP[method]
165
202
  end
166
203
 
167
204
  # Provides access to the request's HTTP headers, for example:
168
205
  #
169
206
  # request.headers["Content-Type"] # => "text/plain"
170
207
  def headers
171
- Http::Headers.new(@env)
208
+ @headers ||= Http::Headers.new(self)
209
+ end
210
+
211
+ # Early Hints is an HTTP/2 status code that indicates hints to help a client start
212
+ # making preparations for processing the final response.
213
+ #
214
+ # If the env contains +rack.early_hints+ then the server accepts HTTP2 push for Link headers.
215
+ #
216
+ # The +send_early_hints+ method accepts a hash of links as follows:
217
+ #
218
+ # send_early_hints("Link" => "</style.css>; rel=preload; as=style\n</script.js>; rel=preload")
219
+ #
220
+ # If you are using +javascript_include_tag+ or +stylesheet_link_tag+ the
221
+ # Early Hints headers are included by default if supported.
222
+ def send_early_hints(links)
223
+ return unless env["rack.early_hints"]
224
+
225
+ env["rack.early_hints"].call(links)
172
226
  end
173
227
 
174
228
  # Returns a +String+ with the last requested path including their params.
@@ -179,7 +233,7 @@ module ActionDispatch
179
233
  # # get '/foo?bar'
180
234
  # request.original_fullpath # => '/foo?bar'
181
235
  def original_fullpath
182
- @original_fullpath ||= (env["ORIGINAL_FULLPATH"] || fullpath)
236
+ @original_fullpath ||= (get_header("ORIGINAL_FULLPATH") || fullpath)
183
237
  end
184
238
 
185
239
  # Returns the +String+ full path including params of the last URL requested.
@@ -218,62 +272,84 @@ module ActionDispatch
218
272
  # (case-insensitive), which may need to be manually added depending on the
219
273
  # choice of JavaScript libraries and frameworks.
220
274
  def xml_http_request?
221
- @env['HTTP_X_REQUESTED_WITH'] =~ /XMLHttpRequest/i
275
+ get_header("HTTP_X_REQUESTED_WITH") =~ /XMLHttpRequest/i
222
276
  end
223
277
  alias :xhr? :xml_http_request?
224
278
 
279
+ # Returns the IP address of client as a +String+.
225
280
  def ip
226
281
  @ip ||= super
227
282
  end
228
283
 
229
- # Originating IP address, usually set by the RemoteIp middleware.
284
+ # Returns the IP address of client as a +String+,
285
+ # usually set by the RemoteIp middleware.
230
286
  def remote_ip
231
- @remote_ip ||= (@env["action_dispatch.remote_ip"] || ip).to_s
287
+ @remote_ip ||= (get_header("action_dispatch.remote_ip") || ip).to_s
288
+ end
289
+
290
+ def remote_ip=(remote_ip)
291
+ set_header "action_dispatch.remote_ip", remote_ip
232
292
  end
233
293
 
294
+ ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id" # :nodoc:
295
+
234
296
  # Returns the unique request id, which is based on either the X-Request-Id header that can
235
297
  # be generated by a firewall, load balancer, or web server or by the RequestId middleware
236
298
  # (which sets the action_dispatch.request_id environment variable).
237
299
  #
238
300
  # This unique ID is useful for tracing a request from end-to-end as part of logging or debugging.
239
- # This relies on the rack variable set by the ActionDispatch::RequestId middleware.
240
- def uuid
241
- @uuid ||= env["action_dispatch.request_id"]
301
+ # This relies on the Rack variable set by the ActionDispatch::RequestId middleware.
302
+ def request_id
303
+ get_header ACTION_DISPATCH_REQUEST_ID
304
+ end
305
+
306
+ def request_id=(id) # :nodoc:
307
+ set_header ACTION_DISPATCH_REQUEST_ID, id
242
308
  end
243
309
 
310
+ alias_method :uuid, :request_id
311
+
244
312
  # Returns the lowercase name of the HTTP server software.
245
313
  def server_software
246
- (@env['SERVER_SOFTWARE'] && /^([a-zA-Z]+)/ =~ @env['SERVER_SOFTWARE']) ? $1.downcase : nil
314
+ (get_header("SERVER_SOFTWARE") && /^([a-zA-Z]+)/ =~ get_header("SERVER_SOFTWARE")) ? $1.downcase : nil
247
315
  end
248
316
 
249
317
  # Read the request \body. This is useful for web services that need to
250
318
  # work with raw requests directly.
251
319
  def raw_post
252
- unless @env.include? 'RAW_POST_DATA'
320
+ unless has_header? "RAW_POST_DATA"
253
321
  raw_post_body = body
254
- @env['RAW_POST_DATA'] = raw_post_body.read(content_length)
322
+ set_header("RAW_POST_DATA", raw_post_body.read(content_length))
255
323
  raw_post_body.rewind if raw_post_body.respond_to?(:rewind)
256
324
  end
257
- @env['RAW_POST_DATA']
325
+ get_header "RAW_POST_DATA"
258
326
  end
259
327
 
260
328
  # The request body is an IO input stream. If the RAW_POST_DATA environment
261
329
  # variable is already set, wrap it in a StringIO.
262
330
  def body
263
- if raw_post = @env['RAW_POST_DATA']
264
- raw_post.force_encoding(Encoding::BINARY)
331
+ if raw_post = get_header("RAW_POST_DATA")
332
+ raw_post = raw_post.dup.force_encoding(Encoding::BINARY)
265
333
  StringIO.new(raw_post)
266
334
  else
267
- @env['rack.input']
335
+ body_stream
268
336
  end
269
337
  end
270
338
 
339
+ # Determine whether the request body contains form-data by checking
340
+ # the request Content-Type for one of the media-types:
341
+ # "application/x-www-form-urlencoded" or "multipart/form-data". The
342
+ # list of form-data media types can be modified through the
343
+ # +FORM_DATA_MEDIA_TYPES+ array.
344
+ #
345
+ # A request body is not assumed to contain form-data when no
346
+ # Content-Type header is provided and the request_method is POST.
271
347
  def form_data?
272
- FORM_DATA_MEDIA_TYPES.include?(content_mime_type.to_s)
348
+ FORM_DATA_MEDIA_TYPES.include?(media_type)
273
349
  end
274
350
 
275
351
  def body_stream #:nodoc:
276
- @env['rack.input']
352
+ get_header("rack.input")
277
353
  end
278
354
 
279
355
  # TODO This should be broken apart into AD::Request::Session and probably
@@ -284,60 +360,71 @@ module ActionDispatch
284
360
  else
285
361
  self.session = {}
286
362
  end
287
- @env['action_dispatch.request.flash_hash'] = nil
288
363
  end
289
364
 
290
365
  def session=(session) #:nodoc:
291
- Session.set @env, session
366
+ Session.set self, session
292
367
  end
293
368
 
294
369
  def session_options=(options)
295
- Session::Options.set @env, options
370
+ Session::Options.set self, options
296
371
  end
297
372
 
298
- # Override Rack's GET method to support indifferent access
373
+ # Override Rack's GET method to support indifferent access.
299
374
  def GET
300
- @env["action_dispatch.request.query_parameters"] ||= Utils.deep_munge(normalize_encode_params(super || {}))
375
+ fetch_header("action_dispatch.request.query_parameters") do |k|
376
+ rack_query_params = super || {}
377
+ # Check for non UTF-8 parameter values, which would cause errors later
378
+ Request::Utils.check_param_encoding(rack_query_params)
379
+ set_header k, Request::Utils.normalize_encode_params(rack_query_params)
380
+ end
301
381
  rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
302
- raise ActionController::BadRequest.new(:query, e)
382
+ raise ActionController::BadRequest.new("Invalid query parameters: #{e.message}")
303
383
  end
304
384
  alias :query_parameters :GET
305
385
 
306
- # Override Rack's POST method to support indifferent access
386
+ # Override Rack's POST method to support indifferent access.
307
387
  def POST
308
- @env["action_dispatch.request.request_parameters"] ||= Utils.deep_munge(normalize_encode_params(super || {}))
388
+ fetch_header("action_dispatch.request.request_parameters") do
389
+ pr = parse_formatted_parameters(params_parsers) do |params|
390
+ super || {}
391
+ end
392
+ self.request_parameters = Request::Utils.normalize_encode_params(pr)
393
+ end
309
394
  rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
310
- raise ActionController::BadRequest.new(:request, e)
395
+ raise ActionController::BadRequest.new("Invalid request parameters: #{e.message}")
311
396
  end
312
397
  alias :request_parameters :POST
313
398
 
314
399
  # Returns the authorization header regardless of whether it was specified directly or through one of the
315
400
  # proxy alternatives.
316
401
  def authorization
317
- @env['HTTP_AUTHORIZATION'] ||
318
- @env['X-HTTP_AUTHORIZATION'] ||
319
- @env['X_HTTP_AUTHORIZATION'] ||
320
- @env['REDIRECT_X_HTTP_AUTHORIZATION']
402
+ get_header("HTTP_AUTHORIZATION") ||
403
+ get_header("X-HTTP_AUTHORIZATION") ||
404
+ get_header("X_HTTP_AUTHORIZATION") ||
405
+ get_header("REDIRECT_X_HTTP_AUTHORIZATION")
321
406
  end
322
407
 
323
- # True if the request came from localhost, 127.0.0.1.
408
+ # True if the request came from localhost, 127.0.0.1, or ::1.
324
409
  def local?
325
410
  LOCALHOST =~ remote_addr && LOCALHOST =~ remote_ip
326
411
  end
327
412
 
328
- # Extracted into ActionDispatch::Request::Utils.deep_munge, but kept here for backwards compatibility.
329
- def deep_munge(hash)
330
- ActiveSupport::Deprecation.warn(
331
- 'This method has been extracted into `ActionDispatch::Request::Utils.deep_munge`. Please start using that instead.'
332
- )
413
+ def request_parameters=(params)
414
+ raise if params.nil?
415
+ set_header("action_dispatch.request.request_parameters", params)
416
+ end
333
417
 
334
- Utils.deep_munge(hash)
418
+ def logger
419
+ get_header("action_dispatch.logger")
335
420
  end
336
421
 
337
- protected
338
- def parse_query(qs)
339
- Utils.deep_munge(super)
340
- end
422
+ def commit_flash
423
+ end
424
+
425
+ def ssl?
426
+ super || scheme == "wss"
427
+ end
341
428
 
342
429
  private
343
430
  def check_method(name)