Faraday: NoMethodError: undefined method 'bytesize' for Hash

Created on 1 Sep 2017  路  2Comments  路  Source: lostisland/faraday

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?

Most helpful comment

Hi @djberg96 and sorry for the delayed response.

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

All 2 comments

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.

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

subvertallchris picture subvertallchris  路  5Comments

JasonBarnabe picture JasonBarnabe  路  4Comments

jordansissel picture jordansissel  路  5Comments

ioquatix picture ioquatix  路  4Comments

amrrbakry picture amrrbakry  路  4Comments