actionpack 7.2.1.1 → 8.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +108 -100
 - data/lib/abstract_controller/helpers.rb +2 -0
 - data/lib/abstract_controller/rendering.rb +0 -1
 - data/lib/action_controller/api.rb +1 -0
 - data/lib/action_controller/form_builder.rb +3 -3
 - data/lib/action_controller/metal/allow_browser.rb +12 -2
 - data/lib/action_controller/metal/conditional_get.rb +6 -3
 - data/lib/action_controller/metal/http_authentication.rb +6 -3
 - data/lib/action_controller/metal/instrumentation.rb +1 -2
 - data/lib/action_controller/metal/live.rb +19 -8
 - data/lib/action_controller/metal/rate_limiting.rb +13 -4
 - data/lib/action_controller/metal/renderers.rb +2 -3
 - data/lib/action_controller/metal/streaming.rb +5 -84
 - data/lib/action_controller/metal/strong_parameters.rb +274 -88
 - data/lib/action_controller/railtie.rb +1 -7
 - data/lib/action_controller/test_case.rb +6 -5
 - data/lib/action_dispatch/http/cache.rb +27 -10
 - data/lib/action_dispatch/http/content_security_policy.rb +5 -8
 - data/lib/action_dispatch/http/filter_parameters.rb +4 -9
 - data/lib/action_dispatch/http/filter_redirect.rb +2 -9
 - data/lib/action_dispatch/http/param_builder.rb +163 -0
 - data/lib/action_dispatch/http/param_error.rb +26 -0
 - data/lib/action_dispatch/http/permissions_policy.rb +2 -0
 - data/lib/action_dispatch/http/query_parser.rb +31 -0
 - data/lib/action_dispatch/http/request.rb +60 -16
 - data/lib/action_dispatch/journey/parser.rb +99 -196
 - data/lib/action_dispatch/journey/scanner.rb +40 -42
 - data/lib/action_dispatch/middleware/cookies.rb +4 -2
 - data/lib/action_dispatch/middleware/debug_exceptions.rb +16 -3
 - data/lib/action_dispatch/middleware/debug_view.rb +0 -5
 - data/lib/action_dispatch/middleware/exception_wrapper.rb +0 -6
 - data/lib/action_dispatch/middleware/remote_ip.rb +5 -6
 - data/lib/action_dispatch/middleware/request_id.rb +2 -1
 - data/lib/action_dispatch/middleware/ssl.rb +14 -4
 - data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +0 -3
 - data/lib/action_dispatch/railtie.rb +2 -0
 - data/lib/action_dispatch/request/utils.rb +9 -3
 - data/lib/action_dispatch/routing/inspector.rb +1 -1
 - data/lib/action_dispatch/routing/mapper.rb +91 -62
 - data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -2
 - data/lib/action_dispatch/routing/route_set.rb +20 -8
 - data/lib/action_dispatch/system_testing/browser.rb +12 -21
 - data/lib/action_dispatch/testing/assertions/response.rb +12 -2
 - data/lib/action_dispatch/testing/assertions/routing.rb +4 -4
 - data/lib/action_dispatch/testing/integration.rb +11 -1
 - data/lib/action_dispatch.rb +6 -0
 - data/lib/action_pack/gem_version.rb +4 -4
 - metadata +15 -34
 - data/lib/action_dispatch/journey/parser.y +0 -50
 - data/lib/action_dispatch/journey/parser_extras.rb +0 -33
 
| 
         @@ -48,11 +48,6 @@ module ActionController 
     | 
|
| 
       48 
48 
     | 
    
         
             
                    end
         
     | 
| 
       49 
49 
     | 
    
         | 
| 
       50 
50 
     | 
    
         
             
                    ActionController::Parameters.action_on_unpermitted_parameters = action_on_unpermitted_parameters
         
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
                    unless options.allow_deprecated_parameters_hash_equality.nil?
         
     | 
| 
       53 
     | 
    
         
            -
                      ActionController::Parameters.allow_deprecated_parameters_hash_equality =
         
     | 
| 
       54 
     | 
    
         
            -
                        options.allow_deprecated_parameters_hash_equality
         
     | 
| 
       55 
     | 
    
         
            -
                    end
         
     | 
| 
       56 
51 
     | 
    
         
             
                  end
         
     | 
| 
       57 
52 
     | 
    
         
             
                end
         
     | 
| 
       58 
53 
     | 
    
         | 
| 
         @@ -85,7 +80,6 @@ module ActionController 
     | 
|
| 
       85 
80 
     | 
    
         
             
                      :action_on_unpermitted_parameters,
         
     | 
| 
       86 
81 
     | 
    
         
             
                      :always_permitted_parameters,
         
     | 
| 
       87 
82 
     | 
    
         
             
                      :wrap_parameters_by_default,
         
     | 
| 
       88 
     | 
    
         
            -
                      :allow_deprecated_parameters_hash_equality
         
     | 
| 
       89 
83 
     | 
    
         
             
                    )
         
     | 
| 
       90 
84 
     | 
    
         | 
| 
       91 
85 
     | 
    
         
             
                    filtered_options.each do |k, v|
         
     | 
| 
         @@ -123,7 +117,7 @@ module ActionController 
     | 
|
| 
       123 
117 
     | 
    
         
             
                    app.config.active_record.query_log_tags |= [:action]
         
     | 
| 
       124 
118 
     | 
    
         | 
| 
       125 
119 
     | 
    
         
             
                    ActiveSupport.on_load(:active_record) do
         
     | 
| 
       126 
     | 
    
         
            -
                      ActiveRecord::QueryLogs.taggings.merge 
     | 
| 
      
 120 
     | 
    
         
            +
                      ActiveRecord::QueryLogs.taggings = ActiveRecord::QueryLogs.taggings.merge(
         
     | 
| 
       127 
121 
     | 
    
         
             
                        controller:            ->(context) { context[:controller]&.controller_name },
         
     | 
| 
       128 
122 
     | 
    
         
             
                        action:                ->(context) { context[:controller]&.action_name },
         
     | 
| 
       129 
123 
     | 
    
         
             
                        namespaced_controller: ->(context) {
         
     | 
| 
         @@ -22,6 +22,8 @@ module ActionController 
     | 
|
| 
       22 
22 
     | 
    
         
             
                # database on the main thread, so they could open a txn, then the controller
         
     | 
| 
       23 
23 
     | 
    
         
             
                # thread will open a new connection and try to access data that's only visible
         
     | 
| 
       24 
24 
     | 
    
         
             
                # to the main thread's txn. This is the problem in #23483.
         
     | 
| 
      
 25 
     | 
    
         
            +
                alias_method :original_new_controller_thread, :new_controller_thread
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
       25 
27 
     | 
    
         
             
                silence_redefinition_of_method :new_controller_thread
         
     | 
| 
       26 
28 
     | 
    
         
             
                def new_controller_thread # :nodoc:
         
     | 
| 
       27 
29 
     | 
    
         
             
                  yield
         
     | 
| 
         @@ -106,7 +108,7 @@ module ActionController 
     | 
|
| 
       106 
108 
     | 
    
         
             
                        set_header k, "application/x-www-form-urlencoded"
         
     | 
| 
       107 
109 
     | 
    
         
             
                      end
         
     | 
| 
       108 
110 
     | 
    
         | 
| 
       109 
     | 
    
         
            -
                      case content_mime_type 
     | 
| 
      
 111 
     | 
    
         
            +
                      case content_mime_type&.to_sym
         
     | 
| 
       110 
112 
     | 
    
         
             
                      when nil
         
     | 
| 
       111 
113 
     | 
    
         
             
                        raise "Unknown Content-Type: #{content_type}"
         
     | 
| 
       112 
114 
     | 
    
         
             
                      when :json
         
     | 
| 
         @@ -121,7 +123,7 @@ module ActionController 
     | 
|
| 
       121 
123 
     | 
    
         
             
                      end
         
     | 
| 
       122 
124 
     | 
    
         
             
                    end
         
     | 
| 
       123 
125 
     | 
    
         | 
| 
       124 
     | 
    
         
            -
                    data_stream = StringIO.new(data)
         
     | 
| 
      
 126 
     | 
    
         
            +
                    data_stream = StringIO.new(data.b)
         
     | 
| 
       125 
127 
     | 
    
         
             
                    set_header "CONTENT_LENGTH", data_stream.length.to_s
         
     | 
| 
       126 
128 
     | 
    
         
             
                    set_header "rack.input", data_stream
         
     | 
| 
       127 
129 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -427,9 +429,7 @@ module ActionController 
     | 
|
| 
       427 
429 
     | 
    
         
             
                  # Note that the request method is not verified. The different methods are
         
     | 
| 
       428 
430 
     | 
    
         
             
                  # available to make the tests more expressive.
         
     | 
| 
       429 
431 
     | 
    
         
             
                  def get(action, **args)
         
     | 
| 
       430 
     | 
    
         
            -
                     
     | 
| 
       431 
     | 
    
         
            -
                    cookies.update res.cookies
         
     | 
| 
       432 
     | 
    
         
            -
                    res
         
     | 
| 
      
 432 
     | 
    
         
            +
                    process(action, method: "GET", **args)
         
     | 
| 
       433 
433 
     | 
    
         
             
                  end
         
     | 
| 
       434 
434 
     | 
    
         | 
| 
       435 
435 
     | 
    
         
             
                  # Simulate a POST request with the given parameters and set/volley the response.
         
     | 
| 
         @@ -637,6 +637,7 @@ module ActionController 
     | 
|
| 
       637 
637 
     | 
    
         
             
                          unless @request.cookie_jar.committed?
         
     | 
| 
       638 
638 
     | 
    
         
             
                            @request.cookie_jar.write(@response)
         
     | 
| 
       639 
639 
     | 
    
         
             
                            cookies.update(@request.cookie_jar.instance_variable_get(:@cookies))
         
     | 
| 
      
 640 
     | 
    
         
            +
                            cookies.update(@response.cookies)
         
     | 
| 
       640 
641 
     | 
    
         
             
                          end
         
     | 
| 
       641 
642 
     | 
    
         
             
                        end
         
     | 
| 
       642 
643 
     | 
    
         
             
                        @response.prepare!
         
     | 
| 
         @@ -9,6 +9,8 @@ module ActionDispatch 
     | 
|
| 
       9 
9 
     | 
    
         
             
                    HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE"
         
     | 
| 
       10 
10 
     | 
    
         
             
                    HTTP_IF_NONE_MATCH     = "HTTP_IF_NONE_MATCH"
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
      
 12 
     | 
    
         
            +
                    mattr_accessor :strict_freshness, default: false
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
       12 
14 
     | 
    
         
             
                    def if_modified_since
         
     | 
| 
       13 
15 
     | 
    
         
             
                      if since = get_header(HTTP_IF_MODIFIED_SINCE)
         
     | 
| 
       14 
16 
     | 
    
         
             
                        Time.rfc2822(since) rescue nil
         
     | 
| 
         @@ -34,19 +36,32 @@ module ActionDispatch 
     | 
|
| 
       34 
36 
     | 
    
         
             
                      end
         
     | 
| 
       35 
37 
     | 
    
         
             
                    end
         
     | 
| 
       36 
38 
     | 
    
         | 
| 
       37 
     | 
    
         
            -
                    # Check response freshness (`Last-Modified` and ETag) against request
         
     | 
| 
       38 
     | 
    
         
            -
                    # `If-Modified-Since` and `If-None-Match` conditions. 
     | 
| 
       39 
     | 
    
         
            -
                    # supplied,  
     | 
| 
      
 39 
     | 
    
         
            +
                    # Check response freshness (`Last-Modified` and `ETag`) against request
         
     | 
| 
      
 40 
     | 
    
         
            +
                    # `If-Modified-Since` and `If-None-Match` conditions.
         
     | 
| 
      
 41 
     | 
    
         
            +
                    # If both headers are supplied, based on configuration, either `ETag` is preferred over `Last-Modified`
         
     | 
| 
      
 42 
     | 
    
         
            +
                    # or both are considered equally. You can adjust the preference with
         
     | 
| 
      
 43 
     | 
    
         
            +
                    # `config.action_dispatch.strict_freshness`.
         
     | 
| 
      
 44 
     | 
    
         
            +
                    # Reference: http://tools.ietf.org/html/rfc7232#section-6
         
     | 
| 
       40 
45 
     | 
    
         
             
                    def fresh?(response)
         
     | 
| 
       41 
     | 
    
         
            -
                       
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
      
 46 
     | 
    
         
            +
                      if Request.strict_freshness
         
     | 
| 
      
 47 
     | 
    
         
            +
                        if if_none_match
         
     | 
| 
      
 48 
     | 
    
         
            +
                          etag_matches?(response.etag)
         
     | 
| 
      
 49 
     | 
    
         
            +
                        elsif if_modified_since
         
     | 
| 
      
 50 
     | 
    
         
            +
                          not_modified?(response.last_modified)
         
     | 
| 
      
 51 
     | 
    
         
            +
                        else
         
     | 
| 
      
 52 
     | 
    
         
            +
                          false
         
     | 
| 
      
 53 
     | 
    
         
            +
                        end
         
     | 
| 
      
 54 
     | 
    
         
            +
                      else
         
     | 
| 
      
 55 
     | 
    
         
            +
                        last_modified = if_modified_since
         
     | 
| 
      
 56 
     | 
    
         
            +
                        etag          = if_none_match
         
     | 
| 
       43 
57 
     | 
    
         | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
      
 58 
     | 
    
         
            +
                        return false unless last_modified || etag
         
     | 
| 
       45 
59 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
      
 60 
     | 
    
         
            +
                        success = true
         
     | 
| 
      
 61 
     | 
    
         
            +
                        success &&= not_modified?(response.last_modified) if last_modified
         
     | 
| 
      
 62 
     | 
    
         
            +
                        success &&= etag_matches?(response.etag) if etag
         
     | 
| 
      
 63 
     | 
    
         
            +
                        success
         
     | 
| 
      
 64 
     | 
    
         
            +
                      end
         
     | 
| 
       50 
65 
     | 
    
         
             
                    end
         
     | 
| 
       51 
66 
     | 
    
         
             
                  end
         
     | 
| 
       52 
67 
     | 
    
         | 
| 
         @@ -171,6 +186,7 @@ module ActionDispatch 
     | 
|
| 
       171 
186 
     | 
    
         
             
                    PUBLIC                = "public"
         
     | 
| 
       172 
187 
     | 
    
         
             
                    PRIVATE               = "private"
         
     | 
| 
       173 
188 
     | 
    
         
             
                    MUST_REVALIDATE       = "must-revalidate"
         
     | 
| 
      
 189 
     | 
    
         
            +
                    IMMUTABLE             = "immutable"
         
     | 
| 
       174 
190 
     | 
    
         | 
| 
       175 
191 
     | 
    
         
             
                    def handle_conditional_get!
         
     | 
| 
       176 
192 
     | 
    
         
             
                      # Normally default cache control setting is handled by ETag middleware. But, if
         
     | 
| 
         @@ -221,6 +237,7 @@ module ActionDispatch 
     | 
|
| 
       221 
237 
     | 
    
         
             
                        options << MUST_REVALIDATE if control[:must_revalidate]
         
     | 
| 
       222 
238 
     | 
    
         
             
                        options << "stale-while-revalidate=#{stale_while_revalidate.to_i}" if stale_while_revalidate
         
     | 
| 
       223 
239 
     | 
    
         
             
                        options << "stale-if-error=#{stale_if_error.to_i}" if stale_if_error
         
     | 
| 
      
 240 
     | 
    
         
            +
                        options << IMMUTABLE if control[:immutable]
         
     | 
| 
       224 
241 
     | 
    
         
             
                        options.concat(extras) if extras
         
     | 
| 
       225 
242 
     | 
    
         
             
                      end
         
     | 
| 
       226 
243 
     | 
    
         | 
| 
         @@ -8,8 +8,7 @@ require "active_support/core_ext/array/wrap" 
     | 
|
| 
       8 
8 
     | 
    
         
             
            module ActionDispatch # :nodoc:
         
     | 
| 
       9 
9 
     | 
    
         
             
              # # Action Dispatch Content Security Policy
         
     | 
| 
       10 
10 
     | 
    
         
             
              #
         
     | 
| 
       11 
     | 
    
         
            -
              # Configures the HTTP [Content-Security-Policy]
         
     | 
| 
       12 
     | 
    
         
            -
              # (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy)
         
     | 
| 
      
 11 
     | 
    
         
            +
              # Configures the HTTP [Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy)
         
     | 
| 
       13 
12 
     | 
    
         
             
              # response header to help protect against XSS and
         
     | 
| 
       14 
13 
     | 
    
         
             
              # injection attacks.
         
     | 
| 
       15 
14 
     | 
    
         
             
              #
         
     | 
| 
         @@ -126,6 +125,7 @@ module ActionDispatch # :nodoc: 
     | 
|
| 
       126 
125 
     | 
    
         
             
                MAPPINGS = {
         
     | 
| 
       127 
126 
     | 
    
         
             
                  self:             "'self'",
         
     | 
| 
       128 
127 
     | 
    
         
             
                  unsafe_eval:      "'unsafe-eval'",
         
     | 
| 
      
 128 
     | 
    
         
            +
                  wasm_unsafe_eval: "'wasm-unsafe-eval'",
         
     | 
| 
       129 
129 
     | 
    
         
             
                  unsafe_hashes:    "'unsafe-hashes'",
         
     | 
| 
       130 
130 
     | 
    
         
             
                  unsafe_inline:    "'unsafe-inline'",
         
     | 
| 
       131 
131 
     | 
    
         
             
                  none:             "'none'",
         
     | 
| 
         @@ -226,8 +226,7 @@ module ActionDispatch # :nodoc: 
     | 
|
| 
       226 
226 
     | 
    
         
             
                  end
         
     | 
| 
       227 
227 
     | 
    
         
             
                end
         
     | 
| 
       228 
228 
     | 
    
         | 
| 
       229 
     | 
    
         
            -
                # Enable the [report-uri]
         
     | 
| 
       230 
     | 
    
         
            -
                # (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-uri)
         
     | 
| 
      
 229 
     | 
    
         
            +
                # Enable the [report-uri](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-uri)
         
     | 
| 
       231 
230 
     | 
    
         
             
                # directive. Violation reports will be sent to the
         
     | 
| 
       232 
231 
     | 
    
         
             
                # specified URI:
         
     | 
| 
       233 
232 
     | 
    
         
             
                #
         
     | 
| 
         @@ -237,8 +236,7 @@ module ActionDispatch # :nodoc: 
     | 
|
| 
       237 
236 
     | 
    
         
             
                  @directives["report-uri"] = [uri]
         
     | 
| 
       238 
237 
     | 
    
         
             
                end
         
     | 
| 
       239 
238 
     | 
    
         | 
| 
       240 
     | 
    
         
            -
                # Specify asset types for which [Subresource Integrity]
         
     | 
| 
       241 
     | 
    
         
            -
                # (https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) is required:
         
     | 
| 
      
 239 
     | 
    
         
            +
                # Specify asset types for which [Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) is required:
         
     | 
| 
       242 
240 
     | 
    
         
             
                #
         
     | 
| 
       243 
241 
     | 
    
         
             
                #     policy.require_sri_for :script, :style
         
     | 
| 
       244 
242 
     | 
    
         
             
                #
         
     | 
| 
         @@ -254,8 +252,7 @@ module ActionDispatch # :nodoc: 
     | 
|
| 
       254 
252 
     | 
    
         
             
                  end
         
     | 
| 
       255 
253 
     | 
    
         
             
                end
         
     | 
| 
       256 
254 
     | 
    
         | 
| 
       257 
     | 
    
         
            -
                # Specify whether a [sandbox]
         
     | 
| 
       258 
     | 
    
         
            -
                # (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/sandbox)
         
     | 
| 
      
 255 
     | 
    
         
            +
                # Specify whether a [sandbox](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/sandbox)
         
     | 
| 
       259 
256 
     | 
    
         
             
                # should be enabled for the requested resource:
         
     | 
| 
       260 
257 
     | 
    
         
             
                #
         
     | 
| 
       261 
258 
     | 
    
         
             
                #     policy.sandbox
         
     | 
| 
         @@ -68,17 +68,12 @@ module ActionDispatch 
     | 
|
| 
       68 
68 
     | 
    
         
             
                    ActiveSupport::ParameterFilter.new(filters)
         
     | 
| 
       69 
69 
     | 
    
         
             
                  end
         
     | 
| 
       70 
70 
     | 
    
         | 
| 
      
 71 
     | 
    
         
            +
                  KV_RE   = "[^&;=]+"
         
     | 
| 
      
 72 
     | 
    
         
            +
                  PAIR_RE = %r{(#{KV_RE})=(#{KV_RE})}
         
     | 
| 
       71 
73 
     | 
    
         
             
                  def filtered_query_string # :doc:
         
     | 
| 
       72 
     | 
    
         
            -
                     
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
                      if part.include?("=")
         
     | 
| 
       75 
     | 
    
         
            -
                        key, value = part.split("=", 2)
         
     | 
| 
       76 
     | 
    
         
            -
                        parameter_filter.filter(key => value).first.join("=")
         
     | 
| 
       77 
     | 
    
         
            -
                      else
         
     | 
| 
       78 
     | 
    
         
            -
                        part
         
     | 
| 
       79 
     | 
    
         
            -
                      end
         
     | 
| 
      
 74 
     | 
    
         
            +
                    query_string.gsub(PAIR_RE) do |_|
         
     | 
| 
      
 75 
     | 
    
         
            +
                      parameter_filter.filter($1 => $2).first.join("=")
         
     | 
| 
       80 
76 
     | 
    
         
             
                    end
         
     | 
| 
       81 
     | 
    
         
            -
                    filtered_parts.join("")
         
     | 
| 
       82 
77 
     | 
    
         
             
                  end
         
     | 
| 
       83 
78 
     | 
    
         
             
                end
         
     | 
| 
       84 
79 
     | 
    
         
             
              end
         
     | 
| 
         @@ -37,16 +37,9 @@ module ActionDispatch 
     | 
|
| 
       37 
37 
     | 
    
         
             
                  def parameter_filtered_location
         
     | 
| 
       38 
38 
     | 
    
         
             
                    uri = URI.parse(location)
         
     | 
| 
       39 
39 
     | 
    
         
             
                    unless uri.query.nil? || uri.query.empty?
         
     | 
| 
       40 
     | 
    
         
            -
                       
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
                        if part.include?("=")
         
     | 
| 
       43 
     | 
    
         
            -
                          key, value = part.split("=", 2)
         
     | 
| 
       44 
     | 
    
         
            -
                          request.parameter_filter.filter(key => value).first.join("=")
         
     | 
| 
       45 
     | 
    
         
            -
                        else
         
     | 
| 
       46 
     | 
    
         
            -
                          part
         
     | 
| 
       47 
     | 
    
         
            -
                        end
         
     | 
| 
      
 40 
     | 
    
         
            +
                      uri.query.gsub!(FilterParameters::PAIR_RE) do
         
     | 
| 
      
 41 
     | 
    
         
            +
                        request.parameter_filter.filter($1 => $2).first.join("=")
         
     | 
| 
       48 
42 
     | 
    
         
             
                      end
         
     | 
| 
       49 
     | 
    
         
            -
                      uri.query = filtered_parts.join("")
         
     | 
| 
       50 
43 
     | 
    
         
             
                    end
         
     | 
| 
       51 
44 
     | 
    
         
             
                    uri.to_s
         
     | 
| 
       52 
45 
     | 
    
         
             
                  rescue URI::Error
         
     | 
| 
         @@ -0,0 +1,163 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module ActionDispatch
         
     | 
| 
      
 4 
     | 
    
         
            +
              class ParamBuilder
         
     | 
| 
      
 5 
     | 
    
         
            +
                def self.make_default(param_depth_limit)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  new param_depth_limit
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                attr_reader :param_depth_limit
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def initialize(param_depth_limit)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @param_depth_limit = param_depth_limit
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                cattr_accessor :default
         
     | 
| 
      
 16 
     | 
    
         
            +
                self.default = make_default(100)
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 19 
     | 
    
         
            +
                  delegate :from_query_string, :from_pairs, :from_hash, to: :default
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                def from_query_string(qs, separator: nil, encoding_template: nil)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  from_pairs QueryParser.each_pair(qs, separator), encoding_template: encoding_template
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def from_pairs(pairs, encoding_template: nil)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  params = make_params
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  pairs.each do |k, v|
         
     | 
| 
      
 30 
     | 
    
         
            +
                    if Hash === v
         
     | 
| 
      
 31 
     | 
    
         
            +
                      v = ActionDispatch::Http::UploadedFile.new(v)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    store_nested_param(params, k, v, 0, encoding_template)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  params
         
     | 
| 
      
 38 
     | 
    
         
            +
                rescue ArgumentError => e
         
     | 
| 
      
 39 
     | 
    
         
            +
                  raise InvalidParameterError, e.message, e.backtrace
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def from_hash(hash, encoding_template: nil)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  # Force encodings from encoding template
         
     | 
| 
      
 44 
     | 
    
         
            +
                  hash = Request::Utils::CustomParamEncoder.encode_for_template(hash, encoding_template)
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                  # Assert valid encoding
         
     | 
| 
      
 47 
     | 
    
         
            +
                  Request::Utils.check_param_encoding(hash)
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  # Convert hashes to HWIA (or UploadedFile), and deep-munge nils
         
     | 
| 
      
 50 
     | 
    
         
            +
                  # out of arrays
         
     | 
| 
      
 51 
     | 
    
         
            +
                  hash = Request::Utils.normalize_encode_params(hash)
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  hash
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                private
         
     | 
| 
      
 57 
     | 
    
         
            +
                  def store_nested_param(params, name, v, depth, encoding_template = nil)
         
     | 
| 
      
 58 
     | 
    
         
            +
                    raise ParamsTooDeepError if depth >= param_depth_limit
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                    if !name
         
     | 
| 
      
 61 
     | 
    
         
            +
                      # nil name, treat same as empty string (required by tests)
         
     | 
| 
      
 62 
     | 
    
         
            +
                      k = after = ""
         
     | 
| 
      
 63 
     | 
    
         
            +
                    elsif depth == 0
         
     | 
| 
      
 64 
     | 
    
         
            +
                      # Start of parsing, don't treat [] or [ at start of string specially
         
     | 
| 
      
 65 
     | 
    
         
            +
                      if start = name.index("[", 1)
         
     | 
| 
      
 66 
     | 
    
         
            +
                        # Start of parameter nesting, use part before brackets as key
         
     | 
| 
      
 67 
     | 
    
         
            +
                        k = name[0, start]
         
     | 
| 
      
 68 
     | 
    
         
            +
                        after = name[start, name.length]
         
     | 
| 
      
 69 
     | 
    
         
            +
                      else
         
     | 
| 
      
 70 
     | 
    
         
            +
                        # Plain parameter with no nesting
         
     | 
| 
      
 71 
     | 
    
         
            +
                        k = name
         
     | 
| 
      
 72 
     | 
    
         
            +
                        after = ""
         
     | 
| 
      
 73 
     | 
    
         
            +
                      end
         
     | 
| 
      
 74 
     | 
    
         
            +
                    elsif name.start_with?("[]")
         
     | 
| 
      
 75 
     | 
    
         
            +
                      # Array nesting
         
     | 
| 
      
 76 
     | 
    
         
            +
                      k = "[]"
         
     | 
| 
      
 77 
     | 
    
         
            +
                      after = name[2, name.length]
         
     | 
| 
      
 78 
     | 
    
         
            +
                    elsif name.start_with?("[") && (start = name.index("]", 1))
         
     | 
| 
      
 79 
     | 
    
         
            +
                      # Hash nesting, use the part inside brackets as the key
         
     | 
| 
      
 80 
     | 
    
         
            +
                      k = name[1, start - 1]
         
     | 
| 
      
 81 
     | 
    
         
            +
                      after = name[start + 1, name.length]
         
     | 
| 
      
 82 
     | 
    
         
            +
                    else
         
     | 
| 
      
 83 
     | 
    
         
            +
                      # Probably malformed input, nested but not starting with [
         
     | 
| 
      
 84 
     | 
    
         
            +
                      # treat full name as key for backwards compatibility.
         
     | 
| 
      
 85 
     | 
    
         
            +
                      k = name
         
     | 
| 
      
 86 
     | 
    
         
            +
                      after = ""
         
     | 
| 
      
 87 
     | 
    
         
            +
                    end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                    return if k.empty?
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                    if depth == 0 && String === v
         
     | 
| 
      
 92 
     | 
    
         
            +
                      # We have to wait until we've found the top part of the name,
         
     | 
| 
      
 93 
     | 
    
         
            +
                      # because that's what the encoding template is configured with
         
     | 
| 
      
 94 
     | 
    
         
            +
                      if encoding_template && (designated_encoding = encoding_template[k]) && !v.frozen?
         
     | 
| 
      
 95 
     | 
    
         
            +
                        v.force_encoding(designated_encoding)
         
     | 
| 
      
 96 
     | 
    
         
            +
                      end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                      # ... and we can't validate the encoding until after we've
         
     | 
| 
      
 99 
     | 
    
         
            +
                      # applied any template override
         
     | 
| 
      
 100 
     | 
    
         
            +
                      unless v.valid_encoding?
         
     | 
| 
      
 101 
     | 
    
         
            +
                        raise InvalidParameterError, "Invalid encoding for parameter: #{v.scrub}"
         
     | 
| 
      
 102 
     | 
    
         
            +
                      end
         
     | 
| 
      
 103 
     | 
    
         
            +
                    end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                    if after == ""
         
     | 
| 
      
 106 
     | 
    
         
            +
                      if k == "[]" && depth != 0
         
     | 
| 
      
 107 
     | 
    
         
            +
                        return (v || !ActionDispatch::Request::Utils.perform_deep_munge) ? [v] : []
         
     | 
| 
      
 108 
     | 
    
         
            +
                      else
         
     | 
| 
      
 109 
     | 
    
         
            +
                        params[k] = v
         
     | 
| 
      
 110 
     | 
    
         
            +
                      end
         
     | 
| 
      
 111 
     | 
    
         
            +
                    elsif after == "["
         
     | 
| 
      
 112 
     | 
    
         
            +
                      params[name] = v
         
     | 
| 
      
 113 
     | 
    
         
            +
                    elsif after == "[]"
         
     | 
| 
      
 114 
     | 
    
         
            +
                      params[k] ||= []
         
     | 
| 
      
 115 
     | 
    
         
            +
                      raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
         
     | 
| 
      
 116 
     | 
    
         
            +
                      params[k] << v if v || !ActionDispatch::Request::Utils.perform_deep_munge
         
     | 
| 
      
 117 
     | 
    
         
            +
                    elsif after.start_with?("[]")
         
     | 
| 
      
 118 
     | 
    
         
            +
                      # Recognize x[][y] (hash inside array) parameters
         
     | 
| 
      
 119 
     | 
    
         
            +
                      unless after[2] == "[" && after.end_with?("]") && (child_key = after[3, after.length - 4]) && !child_key.empty? && !child_key.index("[") && !child_key.index("]")
         
     | 
| 
      
 120 
     | 
    
         
            +
                        # Handle other nested array parameters
         
     | 
| 
      
 121 
     | 
    
         
            +
                        child_key = after[2, after.length]
         
     | 
| 
      
 122 
     | 
    
         
            +
                      end
         
     | 
| 
      
 123 
     | 
    
         
            +
                      params[k] ||= []
         
     | 
| 
      
 124 
     | 
    
         
            +
                      raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
         
     | 
| 
      
 125 
     | 
    
         
            +
                      if params_hash_type?(params[k].last) && !params_hash_has_key?(params[k].last, child_key)
         
     | 
| 
      
 126 
     | 
    
         
            +
                        store_nested_param(params[k].last, child_key, v, depth + 1)
         
     | 
| 
      
 127 
     | 
    
         
            +
                      else
         
     | 
| 
      
 128 
     | 
    
         
            +
                        params[k] << store_nested_param(make_params, child_key, v, depth + 1)
         
     | 
| 
      
 129 
     | 
    
         
            +
                      end
         
     | 
| 
      
 130 
     | 
    
         
            +
                    else
         
     | 
| 
      
 131 
     | 
    
         
            +
                      params[k] ||= make_params
         
     | 
| 
      
 132 
     | 
    
         
            +
                      raise ParameterTypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params_hash_type?(params[k])
         
     | 
| 
      
 133 
     | 
    
         
            +
                      params[k] = store_nested_param(params[k], after, v, depth + 1)
         
     | 
| 
      
 134 
     | 
    
         
            +
                    end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                    params
         
     | 
| 
      
 137 
     | 
    
         
            +
                  end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                  def make_params
         
     | 
| 
      
 140 
     | 
    
         
            +
                    ActiveSupport::HashWithIndifferentAccess.new
         
     | 
| 
      
 141 
     | 
    
         
            +
                  end
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                  def new_depth_limit(param_depth_limit)
         
     | 
| 
      
 144 
     | 
    
         
            +
                    self.class.new @params_class, param_depth_limit
         
     | 
| 
      
 145 
     | 
    
         
            +
                  end
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                  def params_hash_type?(obj)
         
     | 
| 
      
 148 
     | 
    
         
            +
                    Hash === obj
         
     | 
| 
      
 149 
     | 
    
         
            +
                  end
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
                  def params_hash_has_key?(hash, key)
         
     | 
| 
      
 152 
     | 
    
         
            +
                    return false if key.include?("[]")
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
                    key.split(/[\[\]]+/).inject(hash) do |h, part|
         
     | 
| 
      
 155 
     | 
    
         
            +
                      next h if part == ""
         
     | 
| 
      
 156 
     | 
    
         
            +
                      return false unless params_hash_type?(h) && h.key?(part)
         
     | 
| 
      
 157 
     | 
    
         
            +
                      h[part]
         
     | 
| 
      
 158 
     | 
    
         
            +
                    end
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
                    true
         
     | 
| 
      
 161 
     | 
    
         
            +
                  end
         
     | 
| 
      
 162 
     | 
    
         
            +
              end
         
     | 
| 
      
 163 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module ActionDispatch
         
     | 
| 
      
 4 
     | 
    
         
            +
              class ParamError < ActionDispatch::Http::Parameters::ParseError
         
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(message = nil)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  super
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def self.===(other)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  super || (
         
     | 
| 
      
 11 
     | 
    
         
            +
                    defined?(Rack::Utils::ParameterTypeError) && Rack::Utils::ParameterTypeError === other ||
         
     | 
| 
      
 12 
     | 
    
         
            +
                    defined?(Rack::Utils::InvalidParameterError) && Rack::Utils::InvalidParameterError === other ||
         
     | 
| 
      
 13 
     | 
    
         
            +
                    defined?(Rack::QueryParser::ParamsTooDeepError) && Rack::QueryParser::ParamsTooDeepError === other
         
     | 
| 
      
 14 
     | 
    
         
            +
                  )
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              class ParameterTypeError < ParamError
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              class InvalidParameterError < ParamError
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              class ParamsTooDeepError < ParamError
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -86,12 +86,14 @@ module ActionDispatch # :nodoc: 
     | 
|
| 
       86 
86 
     | 
    
         
             
                  ambient_light_sensor: "ambient-light-sensor",
         
     | 
| 
       87 
87 
     | 
    
         
             
                  autoplay:             "autoplay",
         
     | 
| 
       88 
88 
     | 
    
         
             
                  camera:               "camera",
         
     | 
| 
      
 89 
     | 
    
         
            +
                  display_capture:      "display-capture",
         
     | 
| 
       89 
90 
     | 
    
         
             
                  encrypted_media:      "encrypted-media",
         
     | 
| 
       90 
91 
     | 
    
         
             
                  fullscreen:           "fullscreen",
         
     | 
| 
       91 
92 
     | 
    
         
             
                  geolocation:          "geolocation",
         
     | 
| 
       92 
93 
     | 
    
         
             
                  gyroscope:            "gyroscope",
         
     | 
| 
       93 
94 
     | 
    
         
             
                  hid:                  "hid",
         
     | 
| 
       94 
95 
     | 
    
         
             
                  idle_detection:       "idle-detection",
         
     | 
| 
      
 96 
     | 
    
         
            +
                  keyboard_map:         "keyboard-map",
         
     | 
| 
       95 
97 
     | 
    
         
             
                  magnetometer:         "magnetometer",
         
     | 
| 
       96 
98 
     | 
    
         
             
                  microphone:           "microphone",
         
     | 
| 
       97 
99 
     | 
    
         
             
                  midi:                 "midi",
         
     | 
| 
         @@ -0,0 +1,31 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "uri"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module ActionDispatch
         
     | 
| 
      
 6 
     | 
    
         
            +
              class QueryParser
         
     | 
| 
      
 7 
     | 
    
         
            +
                DEFAULT_SEP = /& */n
         
     | 
| 
      
 8 
     | 
    
         
            +
                COMMON_SEP = { ";" => /; */n, ";," => /[;,] */n, "&" => /& */n }
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                #--
         
     | 
| 
      
 11 
     | 
    
         
            +
                # Note this departs from WHATWG's specified parsing algorithm by
         
     | 
| 
      
 12 
     | 
    
         
            +
                # giving a nil value for keys that do not use '='. Callers that need
         
     | 
| 
      
 13 
     | 
    
         
            +
                # the standard's interpretation can use `v.to_s`.
         
     | 
| 
      
 14 
     | 
    
         
            +
                def self.each_pair(s, separator = nil)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  return enum_for(:each_pair, s, separator) unless block_given?
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  (s || "").split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP).each do |part|
         
     | 
| 
      
 18 
     | 
    
         
            +
                    next if part.empty?
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    k, v = part.split("=", 2)
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    k = URI.decode_www_form_component(k)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    v &&= URI.decode_www_form_component(v)
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    yield k, v
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -55,12 +55,17 @@ module ActionDispatch 
     | 
|
| 
       55 
55 
     | 
    
         
             
                  METHOD
         
     | 
| 
       56 
56 
     | 
    
         
             
                end
         
     | 
| 
       57 
57 
     | 
    
         | 
| 
      
 58 
     | 
    
         
            +
                TRANSFER_ENCODING = "HTTP_TRANSFER_ENCODING" # :nodoc:
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
       58 
60 
     | 
    
         
             
                def self.empty
         
     | 
| 
       59 
61 
     | 
    
         
             
                  new({})
         
     | 
| 
       60 
62 
     | 
    
         
             
                end
         
     | 
| 
       61 
63 
     | 
    
         | 
| 
       62 
64 
     | 
    
         
             
                def initialize(env)
         
     | 
| 
       63 
65 
     | 
    
         
             
                  super
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  @rack_request = Rack::Request.new(env)
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
       64 
69 
     | 
    
         
             
                  @method            = nil
         
     | 
| 
       65 
70 
     | 
    
         
             
                  @request_method    = nil
         
     | 
| 
       66 
71 
     | 
    
         
             
                  @remote_ip         = nil
         
     | 
| 
         @@ -69,6 +74,8 @@ module ActionDispatch 
     | 
|
| 
       69 
74 
     | 
    
         
             
                  @ip                = nil
         
     | 
| 
       70 
75 
     | 
    
         
             
                end
         
     | 
| 
       71 
76 
     | 
    
         | 
| 
      
 77 
     | 
    
         
            +
                attr_reader :rack_request
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
       72 
79 
     | 
    
         
             
                def commit_cookie_jar! # :nodoc:
         
     | 
| 
       73 
80 
     | 
    
         
             
                end
         
     | 
| 
       74 
81 
     | 
    
         | 
| 
         @@ -282,7 +289,7 @@ module ActionDispatch 
     | 
|
| 
       282 
289 
     | 
    
         | 
| 
       283 
290 
     | 
    
         
             
                # Returns the content length of the request as an integer.
         
     | 
| 
       284 
291 
     | 
    
         
             
                def content_length
         
     | 
| 
       285 
     | 
    
         
            -
                  return raw_post.bytesize if  
     | 
| 
      
 292 
     | 
    
         
            +
                  return raw_post.bytesize if has_header?(TRANSFER_ENCODING)
         
     | 
| 
       286 
293 
     | 
    
         
             
                  super.to_i
         
     | 
| 
       287 
294 
     | 
    
         
             
                end
         
     | 
| 
       288 
295 
     | 
    
         | 
| 
         @@ -386,15 +393,12 @@ module ActionDispatch 
     | 
|
| 
       386 
393 
     | 
    
         
             
                # Override Rack's GET method to support indifferent access.
         
     | 
| 
       387 
394 
     | 
    
         
             
                def GET
         
     | 
| 
       388 
395 
     | 
    
         
             
                  fetch_header("action_dispatch.request.query_parameters") do |k|
         
     | 
| 
       389 
     | 
    
         
            -
                     
     | 
| 
       390 
     | 
    
         
            -
                     
     | 
| 
       391 
     | 
    
         
            -
             
     | 
| 
       392 
     | 
    
         
            -
                     
     | 
| 
       393 
     | 
    
         
            -
                    # Check for non UTF-8 parameter values, which would cause errors later
         
     | 
| 
       394 
     | 
    
         
            -
                    Request::Utils.check_param_encoding(rack_query_params)
         
     | 
| 
       395 
     | 
    
         
            -
                    set_header k, Request::Utils.normalize_encode_params(rack_query_params)
         
     | 
| 
      
 396 
     | 
    
         
            +
                    encoding_template = Request::Utils::CustomParamEncoder.action_encoding_template(self, path_parameters[:controller], path_parameters[:action])
         
     | 
| 
      
 397 
     | 
    
         
            +
                    rack_query_params = ActionDispatch::ParamBuilder.from_query_string(rack_request.query_string, encoding_template: encoding_template)
         
     | 
| 
      
 398 
     | 
    
         
            +
             
     | 
| 
      
 399 
     | 
    
         
            +
                    set_header k, rack_query_params
         
     | 
| 
       396 
400 
     | 
    
         
             
                  end
         
     | 
| 
       397 
     | 
    
         
            -
                rescue  
     | 
| 
      
 401 
     | 
    
         
            +
                rescue ActionDispatch::ParamError => e
         
     | 
| 
       398 
402 
     | 
    
         
             
                  raise ActionController::BadRequest.new("Invalid query parameters: #{e.message}")
         
     | 
| 
       399 
403 
     | 
    
         
             
                end
         
     | 
| 
       400 
404 
     | 
    
         
             
                alias :query_parameters :GET
         
     | 
| 
         @@ -402,18 +406,54 @@ module ActionDispatch 
     | 
|
| 
       402 
406 
     | 
    
         
             
                # Override Rack's POST method to support indifferent access.
         
     | 
| 
       403 
407 
     | 
    
         
             
                def POST
         
     | 
| 
       404 
408 
     | 
    
         
             
                  fetch_header("action_dispatch.request.request_parameters") do
         
     | 
| 
       405 
     | 
    
         
            -
                     
     | 
| 
       406 
     | 
    
         
            -
             
     | 
| 
      
 409 
     | 
    
         
            +
                    encoding_template = Request::Utils::CustomParamEncoder.action_encoding_template(self, path_parameters[:controller], path_parameters[:action])
         
     | 
| 
      
 410 
     | 
    
         
            +
             
     | 
| 
      
 411 
     | 
    
         
            +
                    param_list = nil
         
     | 
| 
      
 412 
     | 
    
         
            +
                    pr = parse_formatted_parameters(params_parsers) do
         
     | 
| 
      
 413 
     | 
    
         
            +
                      if param_list = request_parameters_list
         
     | 
| 
      
 414 
     | 
    
         
            +
                        ActionDispatch::ParamBuilder.from_pairs(param_list, encoding_template: encoding_template)
         
     | 
| 
      
 415 
     | 
    
         
            +
                      else
         
     | 
| 
      
 416 
     | 
    
         
            +
                        # We're not using a version of Rack that provides raw form
         
     | 
| 
      
 417 
     | 
    
         
            +
                        # pairs; we must use its hash (and thus post-process it below).
         
     | 
| 
      
 418 
     | 
    
         
            +
                        fallback_request_parameters
         
     | 
| 
      
 419 
     | 
    
         
            +
                      end
         
     | 
| 
       407 
420 
     | 
    
         
             
                    end
         
     | 
| 
       408 
     | 
    
         
            -
             
     | 
| 
       409 
     | 
    
         
            -
                     
     | 
| 
       410 
     | 
    
         
            -
                     
     | 
| 
      
 421 
     | 
    
         
            +
             
     | 
| 
      
 422 
     | 
    
         
            +
                    # If the request body was parsed by a custom parser like JSON
         
     | 
| 
      
 423 
     | 
    
         
            +
                    # (and thus the above block was not run), we need to
         
     | 
| 
      
 424 
     | 
    
         
            +
                    # post-process the result hash.
         
     | 
| 
      
 425 
     | 
    
         
            +
                    if param_list.nil?
         
     | 
| 
      
 426 
     | 
    
         
            +
                      pr = ActionDispatch::ParamBuilder.from_hash(pr, encoding_template: encoding_template)
         
     | 
| 
      
 427 
     | 
    
         
            +
                    end
         
     | 
| 
      
 428 
     | 
    
         
            +
             
     | 
| 
      
 429 
     | 
    
         
            +
                    self.request_parameters = pr
         
     | 
| 
       411 
430 
     | 
    
         
             
                  end
         
     | 
| 
       412 
     | 
    
         
            -
                rescue  
     | 
| 
      
 431 
     | 
    
         
            +
                rescue ActionDispatch::ParamError, EOFError => e
         
     | 
| 
       413 
432 
     | 
    
         
             
                  raise ActionController::BadRequest.new("Invalid request parameters: #{e.message}")
         
     | 
| 
       414 
433 
     | 
    
         
             
                end
         
     | 
| 
       415 
434 
     | 
    
         
             
                alias :request_parameters :POST
         
     | 
| 
       416 
435 
     | 
    
         | 
| 
      
 436 
     | 
    
         
            +
                def request_parameters_list
         
     | 
| 
      
 437 
     | 
    
         
            +
                  # We don't use Rack's parse result, but we must call it so Rack
         
     | 
| 
      
 438 
     | 
    
         
            +
                  # can populate the rack.request.* keys we need.
         
     | 
| 
      
 439 
     | 
    
         
            +
                  rack_post = rack_request.POST
         
     | 
| 
      
 440 
     | 
    
         
            +
             
     | 
| 
      
 441 
     | 
    
         
            +
                  if form_pairs = get_header("rack.request.form_pairs")
         
     | 
| 
      
 442 
     | 
    
         
            +
                    # Multipart
         
     | 
| 
      
 443 
     | 
    
         
            +
                    form_pairs
         
     | 
| 
      
 444 
     | 
    
         
            +
                  elsif form_vars = get_header("rack.request.form_vars")
         
     | 
| 
      
 445 
     | 
    
         
            +
                    # URL-encoded
         
     | 
| 
      
 446 
     | 
    
         
            +
                    ActionDispatch::QueryParser.each_pair(form_vars)
         
     | 
| 
      
 447 
     | 
    
         
            +
                  elsif rack_post && !rack_post.empty?
         
     | 
| 
      
 448 
     | 
    
         
            +
                    # It was multipart, but Rack did not preserve a pair list
         
     | 
| 
      
 449 
     | 
    
         
            +
                    # (probably too old). Flat parameter list is not available.
         
     | 
| 
      
 450 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 451 
     | 
    
         
            +
                  else
         
     | 
| 
      
 452 
     | 
    
         
            +
                    # No request body, or not a format Rack knows
         
     | 
| 
      
 453 
     | 
    
         
            +
                    []
         
     | 
| 
      
 454 
     | 
    
         
            +
                  end
         
     | 
| 
      
 455 
     | 
    
         
            +
                end
         
     | 
| 
      
 456 
     | 
    
         
            +
             
     | 
| 
       417 
457 
     | 
    
         
             
                # Returns the authorization header regardless of whether it was specified
         
     | 
| 
       418 
458 
     | 
    
         
             
                # directly or through one of the proxy alternatives.
         
     | 
| 
       419 
459 
     | 
    
         
             
                def authorization
         
     | 
| 
         @@ -468,7 +508,7 @@ module ActionDispatch 
     | 
|
| 
       468 
508 
     | 
    
         
             
                  def read_body_stream
         
     | 
| 
       469 
509 
     | 
    
         
             
                    if body_stream
         
     | 
| 
       470 
510 
     | 
    
         
             
                      reset_stream(body_stream) do
         
     | 
| 
       471 
     | 
    
         
            -
                        if  
     | 
| 
      
 511 
     | 
    
         
            +
                        if has_header?(TRANSFER_ENCODING)
         
     | 
| 
       472 
512 
     | 
    
         
             
                          body_stream.read # Read body stream until EOF if "Transfer-Encoding" is present
         
     | 
| 
       473 
513 
     | 
    
         
             
                        else
         
     | 
| 
       474 
514 
     | 
    
         
             
                          body_stream.read(content_length)
         
     | 
| 
         @@ -490,6 +530,10 @@ module ActionDispatch 
     | 
|
| 
       490 
530 
     | 
    
         
             
                      yield
         
     | 
| 
       491 
531 
     | 
    
         
             
                    end
         
     | 
| 
       492 
532 
     | 
    
         
             
                  end
         
     | 
| 
      
 533 
     | 
    
         
            +
             
     | 
| 
      
 534 
     | 
    
         
            +
                  def fallback_request_parameters
         
     | 
| 
      
 535 
     | 
    
         
            +
                    rack_request.POST
         
     | 
| 
      
 536 
     | 
    
         
            +
                  end
         
     | 
| 
       493 
537 
     | 
    
         
             
              end
         
     | 
| 
       494 
538 
     | 
    
         
             
            end
         
     | 
| 
       495 
539 
     | 
    
         |