actionpack 4.2.11.1 → 6.1.3.2

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