I'm hitting an issue with the Azure REST API where I am unable to specify Content-Type or Accept headers without hitting a NoMethodError.
/Users/djberge/.rbenv/versions/2.4.1/lib/ruby/2.4.0/net/http/generic_request.rb:183:in 'send_request_with_body': undefined method 'bytesize' for #<Hash:0x007fb9c202b2b8> (NoMethodError)
I know this has come up before but I'm having trouble working around it.
Below is the setup:
# azure_test.rb
# Obviously I use the real credentials here
client_id = 'xxx'
tenant_id = 'yyy'
client_key = 'zzz'
# Set the endpoints
site_url = 'https://login.microsoftonline.com'
auth_url = File.join(site_url, tenant_id, "oauth2/token")
connection = Faraday.new(auth_url)
body = {
:grant_type => 'client_credentials',
:client_id => client_id,
:client_secret => client_key
}
# Case 1: This works
response = connection.post do |req|
req.body = body
end
# Case 2: This causes the Ruby error mentioned above
response = connection.post do |req|
req.headers['Content-Type'] = 'application/json'
req.body = body
end
# Case 3: This doesn't blow up, but the request fails
response = connection.post do |req|
req.headers['Content-Type'] = 'application/json'
req.body = body.to_json
end
p response.body
In Case 3 where I explicitly call to_json on the hash, the request fails with the following error message:
The request body must contain the following parameter: 'grant_type'
Which is odd, since it obviously does have that parameter. I've also tried using the faraday_json middleware, and get the same result.
Ultimately, this came up as a result of oauth2, which uses Faraday on the backend, and I'm hitting the NoMethodError when I try to use a custom error handler:
https://github.com/intridea/oauth2/issues/316
So, first question is why does it think I'm not passing the proper parameter? Second question is there a way to get around this when using oauth2 plus custom middleware?
Note that even Case 2 will fail if I try to pass a block to the connection constructor earlier:
connection = Faraday.new(auth_url) do |f|
f.response(:detailed_logger, log)
f.adapter Faraday.default_adapter
end
Hi @djberg96 and sorry for the delayed response.
.to_json on a Hash you get back a String that's why Case 3 works.It appears that Azure is expecting the parameters in www-form-url-encoded format (Faraday's default btw) and since it's not Rails, if you pass them in JSON it won't recognise them. Welcome on Microsoft world....
I'm closing this issue as everything looks fine to me on Faraday's side, but feel free to ask again if you need any further explanation
Most helpful comment
Hi @djberg96 and sorry for the delayed response.
.to_jsonon a Hash you get back a String that's why Case 3 works.It appears that Azure is expecting the parameters in www-form-url-encoded format (Faraday's default btw) and since it's not Rails, if you pass them in JSON it won't recognise them. Welcome on Microsoft world....
I'm closing this issue as everything looks fine to me on Faraday's side, but feel free to ask again if you need any further explanation