Search code examples
rubyresthttprest-clientsinch

Ruby's rest-client isn't replicating my CURL request, and I don't know what I'm doing any differently


Here's my CURL request:

curl  -X POST -u apikey:secret 'https://numbers.api.sinch.com/v1/projects/{project ID}/availableNumbers:rentAny' \
  -d '{
    "regionCode": "US",
    "type": "LOCAL",
    "numberPattern": {
      "pattern": "206",
      "searchPattern": "START"
    },
    "smsConfiguration": {
      "servicePlanId": "{service plan ID}"
    }
  }'

I receive a 200 response, and everything works as expected.

Here's what I'm doing with Ruby's rest-client:

opts = {
  :method=>:post,
  :payload=>{"smsConfiguration"=>{"servicePlanId"=>"service plan ID"}, "numberPattern"=>{"pattern"=>"206", "searchPattern"=>"START"}, "regionCode"=>"US", "type"=>"LOCAL"},
  :url=>"https://numbers.api.sinch.com/v1/projects/{project ID}/availableNumbers:rentAny",
  :headers=>{},
  :user=>"API key",
  :password=>"secret"
}

begin
  RestClient::Request.execute(opts)
rescue RestClient::BadRequest => e
  puts e.response.body
end

This returns a 400 response. The statement printed:

"{\"error\":{\"code\":400,\"message\":\"invalid character 's' looking for beginning of value\",\"status\":\"INVALID_ARGUMENT\",\"details\":[]}}\n"

I expected a 200 response from my rest-client, using the same data from my CURL request.


Solution

  • If the API is expecting a JSON document in the request body, you need to tell RestClient this, otherwise, it will produce a POST request with a content-type of application/x-www-form-urlencoded and form-encoded body.

    Use to_json on your body to encode it, and add headers: { content_type: :json } to tell RestClient to make a JSON request.

    RestClient::Request.execute(
      method: :post,
      payload: { "smsConfiguration" => { ... } }.to_json,
      headers: { 
        content_type: :json,
      },
      # ...
    )
    

    Note that, in your first example, it would be more correct to also include the Content-Type and Accept headers in your CURL request, but it seems likely that the API assumes JSON in the case that those headers aren't set.

    However, RestClient cannot make this assumption, you need to specifically tell it you are intending to send JSON.