omg-actionpack 8.0.0.alpha1

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