Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I implement this POST request using HTTParty?

I am having difficulty making a POST request to an API endpoint using Ruby's HTTParty library. The API I'm interacting with is the Gittip API and their endpoint requires authentication. I have been able to successfully make an authenticated GET request using HTTParty.

You can see in the example code:

user = "gratitude_test"
api_key = "5962b93a-5bf7-4cb6-ae6f-aa4114c5e4f2"
# I have included real credentials since the above is merely a test account.

HTTParty.get("https://www.gittip.com/#{user}/tips.json", 
             { :basic_auth => { :username => api_key } })

That request works and returns the following as expected:

[
  {
    "amount" => "1.00",
    "platform" => "gittip",
    "username" => "whit537"
  },
  {
    "amount" => "0.25",
    "platform" => "gittip",
    "username" => "JohnKellyFerguson"
  }
]

However, I have been unable to make a successful POST request using HTTParty. The Gittip API describes making a POST request using curl as follows:

curl https://www.gittip.com/foobar/tips.json \
  -u API_KEY: \
  -X POST \
  -d'[{"username":"bazbuz", "platform":"gittip", "amount": "1.00"}]' \
  -H"Content-Type: application/json"

I have tried (unsuccessfully) structuring my code using HTTParty as follows:

user = "gratitude_test"
api_key = "5962b93a-5bf7-4cb6-ae6f-aa4114c5e4f2"

HTTParty.post("https://www.gittip.com/#{user}/tips.json",
              { 
                :body => [ { "amount" => "0.25", "platform" => "gittip", "username" => "whit537" } ],
                :basic_auth => { :username => api_key },
                :headers => { 'Content-Type' => 'application/json' }
               })

The first argument is the url and the second argument is an options hash. When I run the code above, I get the following error:

NoMethodError: undefined method `bytesize' for [{"amount"=>"0.25", "platform"=>"gittip", "username"=>"whit537"}]:Array
  from /Users/John/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http/generic_request.rb:179:in `send_request_with_body'

I have tried various other combinations of structuring the API call, but can't figure out how to get it to work. Here's another such example, where I do not user an array as part of the body and convert the contents to_json.

user = "gratitude_test"
api_key = "5962b93a-5bf7-4cb6-ae6f-aa4114c5e4f2"

HTTParty.post("https://www.gittip.com/#{user}/tips.json",
          {
            :body => { "amount" => "0.25", "platform" => "gittip", "username" => "whit537" }.to_json,
            :basic_auth => { :username => api_key },
            :headers => { 'Content-Type' => 'application/json' }
           })

Which returns the following (a 500 error):

<html>
  <head>
    <title>500 Internal Server Error</title>
  </head>
  <body>\n        Internal server error, program!\n        <pre></pre>  
  </body>
</html>

I'm not really familiar with curl, so I'm not sure if I am incorrectly translating things to HTTParty.

Any help would be appreciated. Thanks.

like image 293
John K. Ferguson Avatar asked Oct 19 '13 01:10

John K. Ferguson


Video Answer


1 Answers

Just a guess, but it looks like you're passing a hash in the body when JSON is expected.

Try replacing the :body declaration with:

:body => [{ "amount" => "0.25", 
             "platform" => "gittip", 
             "username" => "whit537" }].to_json

Edit: I suggested the to_json serializer, but misplaced it by putting it after the hash instead of the array and removing the array altogether. The example uses multiple records, so the array is necessary.

After looking at this thread, it looks like Gittip is picky about the accept header.

:headers => { 'Content-Type' => 'application/json', 'Accept' => 'application/json'}

So, the full suggestion is:

HTTParty.post("https://www.gittip.com/#{user}/tips.json",
  { 
    :body => [ { "amount" => "0.25", "platform" => "gittip", "username" => "whit537" } ].to_json,
    :basic_auth => { :username => api_key },
    :headers => { 'Content-Type' => 'application/json', 'Accept' => 'application/json'}
  })
like image 101
d_ethier Avatar answered Sep 22 '22 07:09

d_ethier