Monday, January 7, 2013

Suppress RestClient gem Exceptions

This is a little rant on how the RestClient gem handles 400 'bad request' responses. I often use RestClient to handle calls to third-party APIs. I recently hit a use case that had me a little stumped.

I was working on a task that required me to hit a few endpoints on the plivo.com API. No biggie. I set up a RestClient post like normal and expected to get a response back.

ruby-1.9.3-p194 :023 > cp = {"to"=>"121212121212", "from"=>"12121212121212", "answer_url"=>"http://example.com/AnswerUrl", "answer_method"=>"GET", "hangup_url"=>"http://example.com/HanguUrl", "time_limit"=>10}
 => {"to"=>"121212121212", "from"=>"12121212121212", "answer_url"=>"http://example.com/AnswerUrl", "answer_method"=>"GET", "hangup_url"=>"http://example.com/HanguUrl", "time_limit"=>10} 
ruby-1.9.3-p194 :024 > call = RestClient::Resource.new("https://api.plivo.com/v1/Account/XXXXXXXXXX", "XXXXXXXXX", "XXXXXXXXXXXX")
 => https://api.plivo.com/v1/Account/XXXXXXXXXXX
ruby-1.9.3-p194 :025 > r = call["/Call/"].post cp.to_json, :content_type => 'application/json'

RestClient::BadRequest: 400 Bad Request
        from /Users/user/.rvm/gems/ruby-1.9.3-p194/gems/rest-client-1.6.7/lib/restclient/abstract_response.rb:48:in `return!'
        from /Users/user/.rvm/gems/ruby-1.9.3-p194/gems/rest-client-1.6.7/lib/restclient/request.rb:231:in `process_result'
        from /Users/user/.rvm/gems/ruby-1.9.3-p194/gems/rest-client-1.6.7/lib/restclient/request.rb:178:in `block in transmit'
        from /Users/user/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/net/http.rb:745:in `start'
        from /Users/user/.rvm/gems/ruby-1.9.3-p194/gems/rest-client-1.6.7/lib/restclient/request.rb:172:in `transmit'
        from /Users/user/.rvm/gems/ruby-1.9.3-p194/gems/rest-client-1.6.7/lib/restclient/request.rb:64:in `execute'
        from /Users/user/.rvm/gems/ruby-1.9.3-p194/gems/rest-client-1.6.7/lib/restclient/request.rb:33:in `execute'
        from /Users/user/.rvm/gems/ruby-1.9.3-p194/gems/rest-client-1.6.7/lib/restclient/resource.rb:67:in `post'
        from (irb):25
        from /Users/user/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.9/lib/rails/commands/console.rb:47:in `start'
        from /Users/user/.rvm/gems/ruby-1.9.3-p194/gems/railties-3.2.9/lib/rails/commands/console.rb:8:in `start' 

The problem was that instead of giving me a readable response, it gave me a RestClient exception. Shouldn't a REST-Client return a verbose response regardless of that the http status sent? It should be noted that in the case I was working with, the 400 bad request response also returned a message that would help users get a grasp of the problem, but in this case, RestClient just chokes and never passes the returned response message on. I added a 'puts' on the response instance in the request.rb to check out the body of the response and sure enough I saw the message that I was looking for.

{ 
  "api_id": "0f00e214-62d1-11e2-a3f8-22000abc1360",
  "error": "insufficient balance"
}

From the RestClient request.rb source:

# Return the default behavior corresponding to the response code: 
# the response itself for code in 200..206, redirection for 301, 302 and 307 in get and head cases, redirection for 303 and an exception in other cases

Don't get too hung up on not seeing your 400 responses with RestClient. I did a little digging around and it turns out that you actually can disable the exceptions by passing a block with the request.

call["/Call/"].post(cp.to_json, :content_type => 'application/json'){|response| response }
 => "{\n  \"api_id\": \"7def1e60-62d7-11e2-a3f8-22000abc1360\",\n  \"error\": \"insufficient balance\"\n}" 

This is why we read the code :)

No comments:

Post a Comment