actionpack 4.2.10 → 7.2.0.rc1

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