I have an endpoint in my Sinatra application that will be receiving binary data as part of the body. The other application sending it data will have a Faraday request that looks like this:
connection = Faraday.new(url: "https://example.com/post_data") do |conn|
conn.request :multipart
conn.adapter :net_http
conn.headers['Content-Type'] = 'octet/stream'
end
@response ||= connection.post do |req|
req.params = { :host => host,
:verification => "false"}
req.body = my_base64_encoded_binary
end
Then, in Sinatra, I will have an endpoint that receives those request parameters and binary data and passes it along to a model, like so:
post '/post_data' do
request.body.rewind
payload = request.body.read
raise Sinatra::NotFound unless payload and params[:host]
output = MyOutput.new(params, payload)
content_type 'application/json'
body output.data
end
When I try to test this endpoint using Rack::Test
helpers, I end up in a weird situation. I can't seem to create the proper mock in order to test this endpoint properly. Based on some manual testing with PostMan, I'm pretty certain my endpoint works properly. It's just the test that's holding me up. Here is the spec:
it "should return a json response" do
post(url, :host => host, :verification => "false") do |req|
req.body = [my_binary]
req.content_type = "application/octet-stream"
end
expect(last_response.status).to eq(200)
expect(last_response.content_type).to eq("application/json")
end
And when I inspect what the incoming request looks like in the test, it does not contain a proper body. params
is properly set to the host
and verification
settings I set, but the body is also being set to the params (inspected through payload = request.body.read
) instead of the binary.
Is there a different way to set up the mock so that the binary properly is set to the body of the request, and the parameters are still set to the request parameters properly?
The answer is that the only way to post the body is where I was adding the params in the rack test helper. I needed to take the params
and move them into the query string of the URL in the request, and then only add the binary as the body
of the post
request in the test helper.
let(:url) { "http://example.com/post_data?host=>#{host}&verification=#{verification}" }
it "should return a json response" do
post(url, my_binary)
expect(last_response.status).to eq(200)
expect(last_response.content_type).to eq("application/json")
end