March 13, 2013
I recently had the opportunity to make a simple JSON web service using Sinatra, and while testing it
I came across something that wasn’t apparent from the documentation. I needed to test the web service’s response when
JSON was POST’ed to an endpoint. The obvious way to do this, or so I thought, would be to use the post()
method like so:
post('/endpoint', { 'j': 's', 'o': 'n' })
Turns out that doesn’t actually work the way one would expect. Looking at the source code on GitHub,
it looks to me that the above code results in the Content Type of application/x-www-form-urlencoded
and the Hash
being URL encoded. It seems that if you pass a Hash
at all Rack::Test
will try to URL encoded the values. And as
long as you set a specific Content Type Rack::Test
won’t mess with it. Something like the following will successfully
result in a request with application/json
for the Content Type and have the JSON as the request body.
post('/endpoint', "{ 'j': 's', 'o': 'n' }", { "CONTENT_TYPE" => "application/json" })
This is a bit more to type but it gets the job done, you can write a helper to wrap this into something shorter like:
def post_json(uri, json)
post(uri, json, { "CONTENT_TYPE" => "application/json" })
end
I have yet to find another way to achieve this so I am open to any suggestions.
Written by Jason Worley who lives and works in Indianapolis building useful things.