batch_api icon indicating copy to clipboard operation
batch_api copied to clipboard

404 when using query string

Open anothermh opened this issue 10 years ago • 1 comments

I am using batch_api with a Grape API in a Rails app. I found that all batch requests processed normally except for those using query string parameters. For example, this request would work:

{
  "ops": [
    {"method": "get", "url": "/api/v1/model"}
  ],
  "sequential": true
}

The response:

{
  "results": [
    {
      "body": "[{:one=>1}]",
      "headers": {
        "Content-Type": "application/json"
      },
      "status": 200
    }
  ]
}

The same request with a query string fails:

{
  "ops": [
    {"method": "get", "url": "/api/v1/model?per_page=5"}
  ],
  "sequential": true
}

Returns:

{
  "results": [
    {
      "body": "Not Found",
      "headers": {
        "X-Cascade": "pass"
      },
      "status": 404
    }
  ]
}

This was true whether the query string had values or not, i.e., /api/v1/model? also failed without any parameters.

I inspected the Rack env variable in a batch request with a query string. env['PATH_INFO'] = '/api/v1/model?per_page=5' is the value, and this value does not work. If there is a query string appended to PATH_INFO then the call will fail. When I reset PATH_INFO to remove the query string the batch call completed successfully.

The other difference I saw was that rack.request.query_hash was empty, but this didn't appear to impact the request.

This looks like it can be fixed by setting ORIGINAL_FULLPATH and PATH_INFO separately in https://github.com/arsduo/batch_api/blob/master/lib/batch_api/operation/rack.rb#L65.

@env["ORIGINAL_FULLPATH"] = @url
@env["PATH_INFO"] = @url.split('?').first

@arsduo Do you know if there are any unforeseen consequences from this change? Would you accept a PR for this issue?

anothermh avatar Jan 22 '16 01:01 anothermh

I was wrong, I had to get rack.request.query_hash set as well. I have patched in config/initializers/api_batch.rb for now to override the method:

require 'batch_api/response'

module BatchApi
  module Operation
    class Rack
      def process_env
        path, qs = @url.split("?")

        # Headers
        headrs = (@headers || {}).inject({}) do |heads, (k, v)|
          heads.tap {|h| h["HTTP_" + k.gsub(/\-/, "_").upcase] = v}
        end
        # preserve original headers unless explicitly overridden
        @env.merge!(headrs)

        # method
        @env["REQUEST_METHOD"] = @method.upcase

        # path and query string
        if @env["REQUEST_URI"]
          # not all servers provide REQUEST_URI -- Pow, for instance, doesn't
          @env["REQUEST_URI"] = @env["REQUEST_URI"].gsub(/#{BatchApi.config.endpoint}.*/, @url)
        end
        @env["REQUEST_PATH"] = @env["PATH_INFO"] = path
        @env["ORIGINAL_FULLPATH"] = @url

        @env["rack.request.query_string"] = qs
        @env["QUERY_STRING"] = qs

        # parameters
        @env["rack.request.form_hash"] = @params
        @env["rack.request.query_hash"] = ::Rack::Utils.parse_nested_query(qs)
        binding.pry
      end
    end
  end
end

anothermh avatar Jan 22 '16 02:01 anothermh