Rails: query parameter vs post parameter

前端 未结 4 655
闹比i
闹比i 2020-12-14 11:49

Suppose you have a url

localhost:3000?a=1

and in the request, you also have a post parameter

a=2

What wou

相关标签:
4条回答
  • 2020-12-14 12:35

    Rails uses Rack::Request for HTTP requests. However, it redefines the Rack params method in ActionDispatch::Http::Parameters (via an alias).

    This params method, which returns request parameters, is implemented as:

      # Returns both GET and POST \parameters in a single hash.
      def parameters
        @env["action_dispatch.request.parameters"] ||= begin
          params = request_parameters.merge(query_parameters)
          params.merge!(path_parameters)
          encode_params(params).with_indifferent_access
        end
      end
      alias :params :parameters
    

    Note the aliased parameters method.

    Unless redefined, parameters from the query string will overwrite parameters from the POST body.

    0 讨论(0)
  • 2020-12-14 12:45

    No it doesn't depend on de HTTP verb but you sure can have different actions to handle GET and POST or it can be the same and you'll get `params[:a] in both cases.

    0 讨论(0)
  • 2020-12-14 12:48

    When I tried this in a sample code, what I was able to see was that query parameters(GET) are given precedence than the POST body. So, I went digging into the code of Rack which handles the HTTP requests in Rails. Here is the code from request.rb

    # Returns the data recieved in the query string.
    def GET
      ....
    end
    
    # Returns the data recieved in the request body.
    #
    # This method support both application/x-www-form-urlencoded and
    # multipart/form-data.
    def POST
      ....
    end
    
    # The union of GET and POST data.
    def params
      @params ||= self.GET.merge(self.POST)
    rescue EOFError
      self.GET
    end
    

    Here, the method

    • GET - returns the query parameters in a hash format
    • POST - returns the post body in a hash format

    So, according to the code for params, the GET parameters should get overridden by POST parameters in case of identical keys. (self.GET.merge(self.POST)). But, this is contrary to what I got when I tried it practically.

    So, the only chance is that this code is being overridden by Rails. When I thought about it, it made perfect sense as the params hash from the Rails will always contain "controller" and "action" keys, which will be absent in case of Rack. So, I looked at the code of Rails also, and found that params method was indeed being overridden. Take a look at request.rb and parameters.rb in Rails source code. In parameters.rb, we have:

      # Returns both GET and POST \parameters in a single hash.
      def parameters
        @env["action_dispatch.request.parameters"] ||= begin
          params = request_parameters.merge(query_parameters)
          params.merge!(path_parameters)
          encode_params(params).with_indifferent_access
        end
      end
      alias :params :parameters
    

    and in request.rb:

    # Override Rack's GET method to support indifferent access
    def GET
      @env["action_dispatch.request.query_parameters"] ||= (normalize_parameters(super) || {})
    end
    alias :query_parameters :GET
    
    # Override Rack's POST method to support indifferent access
    def POST
      @env["action_dispatch.request.request_parameters"] ||= (normalize_parameters(super) || {})
    end
    alias :request_parameters :POST
    

    So, here

    • query_parameters - Alias for the GET method
    • request_parameters - Alias for the POST method
    • path_parameters - Method which returns the controller and action for the request as a hash
    • parameters - Alias for params (It was overridden here)

    Note that GET method and POST method were also overridden, mainly to convert the hash returned to an object of HashWithIndifferentAccess.

    So, looking at the code here (params = request_parameters.merge(query_parameters)), it becomes evident that POST parameters are overridden by GET parameters in case of identical keys, in Rails. Or in other words, GET parameters are given precedence over POST parameters.

    0 讨论(0)
  • 2020-12-14 12:49

    It would be 2. But for routing, it would match against the '1'.

    If you want, you can use request.GET and request.POST to access the get and post vars.

    0 讨论(0)
提交回复
热议问题