404 when using query string
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?
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