I can never get a JSON response from Faraday, within Ruby 3.1.3 and Faraday 2.7.5:
def connection
@connection ||= Faraday.new(
url: url,
headers: headers
) do |faraday|
faraday.response :json
faraday.request :json
end
end
def headers
{ content_type: 'application/json',
accept: 'application/json' }
end
def send_request
connection.send(method) do |req|
req.body = body
end
end
When running though, I check response.body
, and it is never JSON (even though I have faraday.response :json
:
[1] pry(#<App>)> response.body
=> "{\"data\":{\"date\":\"some_data\"}}"
I have to:
[2] pry(#<>)> JSON.parse response.body
=> {"data"=>{"date"=>"some_data"}}
The test I am checking this with is:
let(:response_body) { { data: { date: 'some_data' } }.to_json }
...
stub_request(:post, url)
.with(
body: body.to_json,
headers: custom_headers
).to_return(status: status, body: response_body, headers: {})
end
it 'POSTS to a url' do
subject
expect(a_request(:post, url)).to have_been_made
end
end
Is my test wrong, or is the client code wrong to have json
always returned?
My guess is that the API you are requesting is not setting the right content-type
response header.
I haven't dug very deep in the Faraday code, but it seems that if the response is not in format 'application/json' the response.body is delivered as plain string.
conn = Faraday.new do |f|
f.request :json
f.response :json
end
res = conn.get("https://dummyjson.com/products/1")
res.body["id"]
# => 1
res.body.class
# => Hash
res.headers["content-type"]
# => "application/json; charset=utf-8"
res = conn.get("https://example.com")
res.headers["content-type"]
# => "text/html; charset=UTF-8"
res.body[0, 80]
# => "<!doctype html>\n<html>\n<head>\n <title>Example Domain</title>\n\n <meta chars"
res.body.class
# => String