Rails + HTTParty : Expecting JSON data in the body - ruby-on-rails

I want to integrate the Routific API into a Rails application. I made my request with HTTParty but I get the following message {"error"=>"Expecting JSON data in the body"}
I don't understand... I am sending the json in the body. Please check my code below.
Thanks for your help
Julien
file = File.read("#{Rails.root}/app/controllers/demo.json")
api_key = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1ODE3M2ZiNTk1NzRjZTFiMmZhNWEwNTAiLCJpYXQiOjE0Nzc5MTg2NDZ9.extq0nKtPGwj6VXxMpj9u8uapasKVSorWeTBFW7HgOE"
headers = {
"Content-Type:" => "application/json",
'authorization'=> 'bearer ' + api_key
}
#results = HTTParty.post("https://api.routific.com/v1/vrp",
:headers => headers,
:body => file.to_json)

you added invalid headers
it should be "Content-Type" instead of "Content-Type:" (without colon)

Related

Net/HTTP in rails with request header and body

I am trying to call external API for my project and I have some troubles while using Net::HTTP in my rails lib . Here is my code
class ApiCall
def self.do_api_request(api_token, body)
require 'net/http'
require 'uri'
uri = URI.parse('https://sample.com')
header = {'Token' => api_token, 'Content-Type' => 'application/json', 'Accept' => 'application/json'}
request = Net::HTTP::Post.new(uri.request_uri, header)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = (uri.scheme == "https")
request.body = body
http.request(request)
end
end
This is how I use it (assume I knew the api_token and body):
body = {'id' => 2, 'age'=> 23};
ApiCall.do_api_request(api_token, body)
This way, it throws an error back:
NoMethodError: undefined method `bytesize' for Hash
Then after check online, seems like the body is hash instead of string, so I did this
body = URI.encode_www_form(body) and after rerun, it gives me :
400 bad request
I have no ideas how to put both header and body into a rails Net::HTTP method
Solution:
I know where the problem is. request body supposed to be string
so body = "{'id' : 2, 'age' : 23}" , I used body.to_json
I will suggest you to use HTTParty for calling an api. This is real simple to use. Following are the examples-
HTTParty.get("https://api.bigcommerce.com/stores/"+#store.store_hash+"/v3/catalog/categories", :headers => #your_header_data)
This will return the response. Also for post request,
HTTParty.post("https://api.bigcommerce.com/stores/"+#store.store_hash+"/v3/catalog/products", :headers => #auth, :body => product_json)
So you can pass body to in body param here.

Rails - How to add contacts to SendGrid marketing campaigns via API

I need to make HTTP get and post requests with SendGrid to add contacts to our account, however there doesn't seem to be a gem for their email marketing functionality.
It boils down to making a few requests however I can't get past their authentication step.
They say to do this
curl -X "GET" "https://api.sendgrid.com/v3/templates" -H "Authorization: Bearer Your.API.Key-HERE" -H "Content-Type: application/json"
And using the Rest-Client gem I'm trying to make the authentication request like so...
username = 'username'
api_key = 'SG.MY_API_KEY'
key = Base64.encode64(username + ":" + api_key)
headers = {"Authorization" => "Bearer #{key}", "Content-Type" => "application/json"}
response = RestClient.get 'https://api.sendgrid.com/v3/templates', headers
which returns...
RestClient::Unauthorized: 401 Unauthorized: {"errors":[{"field":null,"message":"authorization required"}]}
The ultimate objective of using their API is to add contacts.
How am I incorrectly making this get request?
I ended up figuring it out. For future reference, here's the code that worked...
require 'rest_client'
api_key = 'YOUR_API_KEY'
headers = {'Authorization' => "Bearer #{api_key}"}
data = {:email => 'email#website.com'}
response = RestClient.post 'https://api.sendgrid.com/v3/contactdb/recipients', [data].to_json, headers
To add marketing contacts to your SendGrid account via the API,
see the documentation at https://sendgrid.api-docs.io/v3.0/contacts-api-recipients/add-recipients
You can see sample code in the "code generation" section of the page.
require 'uri'
require 'net/http'
url = URI("https://api.sendgrid.com/v3/contactdb/recipients")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
request["authorization"] = 'Bearer <<YOUR_API_KEY>>'
request["content-type"] = 'application/json'
request.body = "[{\"email\":\"example#example.com\",\"first_name\":\"\",\"last_name\":\"User\",\"age\":25},{\"email\":\"example2#example.com\",\"first_name\":\"Example\",\"last_name\":\"User\",\"age\":25}]"
response = http.request(request)
puts response.read_body

Google Drive API watch 400 error Ruby on Rails

I'm implementing the google drive api using the OAuth2 gem (ruby on rails). I'm not using the client library because I'm also integrating other API's, so I'm trying to make all these calls as modular as possible. I'm having trouble with the this request: POST https://www.googleapis.com/drive/v2/changes/watch.
I keep getting this error:
{"errors"=>[{"domain"=>"global", "reason"=>"required", "message"=>"entity.resource"}],
"code"=>400, "message"=>"entity.resource"}: { "error": { "errors": [ { "domain":
"global", "reason": "required", "message": "entity.resource" } ], "code": 400,
"message": "entity.resource" } }
which is not very useful. It may not be Google. It could be OAuth2, but I don't think so, because the debugger gets to the response after making the connection. Well, at this point, I don't know anything, so any help is appreciated. There is THIS GUY who has exactly the same error code as me, as well as the same conclusion.
Anyway, the relevant code parts:
First, the parameters I pass to OAuth2::AccessToken's post method(I need more than 10 rep to post another link, but here is the dochttp://rdoc.info/github/intridea/oauth2/ebe4be038ec14b349682/OAuth2/AccessToken#post-instance_method)(you can click on the request method to see how the params are handled)
base_url = request.protocol + request.host_with_port
channel_id = (0...50).map { ('a'..'z').to_a[rand(26)] }.join
body_post = {:id => channel_id,:type => 'web_hook',:address => base_url + "/googledrive/webhook"}
headers = {'Content-Type' => 'application/json'}
response = makeApiCall(token,"google_drive","/changes/watch","post",{},body_post,headers)
All this does is built my request with my the appropriate request body and headers for the call
Here is the relevant part from makeApiCall (at the line token.post is where the request is made, and where it breaks)
params = {"oauth_consumer_key" => ENV[key], "access_token" => token.token}.merge(params)
#body = Rack::Utils.build_query(body)
opts = {
:params => params,
:body => body,
:headers => headers
}
if(method=="get")
response = token.get(base + path,:opts => opts)
elsif(method=="post")
debugger
response = token.post(base + path,:opts => opts)
end
This is my first or second post, so forgive me if I messed anything up.
Okay, after struggling for so long, I figured out why it wasn't working. I forgot to do this:
JSON.generate(body_post)
So that my body was actually in application/json form.
Also, this line:
response = token.post(base + path,:opts => opts)
should be this:
response = token.post(base + path,opts)
simply because I'm not assigning the opts key, but the variable that I'm passing. Silly me.

Rails - Sending image using Faraday

I'm trying to make a request to an API sending an image and some other data, and getting the response. That's my code:
file = "assets/images/test.jpg"
conn = Faraday.new(:url => "api_url" ) do |faraday|
faraday.request :multipart
end
payload = { :profile_pic => Faraday::UploadIO.new(file, 'image/jpeg') }
conn.post "/test", payload
My first problem is that I'm always getting the following error:
Errno::ENOENT (No such file or directory - assets/images/test.png)
I've tried all the paths I could imagine. Where should be saved the image in directories to be found by Faraday?
The second question is about the response, how can I get the response and handle it?
The third one is that, I haven't understand what's the utility of the first parameter of the last call:
conn.post "/hello", payload
I've written "/hello" but don't have any idea about what's the real usage.
And the last one. Could I send a raw image saved in a variable instead of sending a path to Faraday?
EDIT
Now it's working, this is the solution:
Be aware that url must be only until .com, the rest of the path must go on conn.post like this example /v1/search.
c.adapter :net_http was needed too.
Message response is correctly handled in json variable.
Solution:
url = 'http://url.com'
file = Rails.root.to_s + "/app/assets/images/test.jpg"
conn = Faraday.new(:url => url ) do |c|
c.request :multipart
c.adapter :net_http
end
payload = { :image => Faraday::UploadIO.new(file, 'image/jpeg'), :token => token}
response = conn.post '/v1/search', payload
json = JSON.parse response.body
You should try this for your first question :
file = Rails.root.to_s + "/app/assets/images/test.jpg"
For your third question, the first parameters allows you to construct the right URL from the base "api_url". Please see the example from the Readme.
## POST ##
conn.post '/nigiri', { :name => 'Maguro' } # POST "name=maguro" to http://sushi.com/nigiri

Changing Content-Type to JSON using HTTParty

I am trying to use Ruby on Rails to communicate with the Salesforce API. I can fetch data easily enough but I am having problems posting data to the server. I am using HTTParty as per Quinton Wall's post here:
https://github.com/quintonwall/omniauth-rails3-forcedotcom/wiki/Build-Mobile-Apps-in-the-Cloud-with-Omniauth,-Httparty-and-Force.com
but all I seem to be able to get from the salesforce server is the error that I am submitting the body as html
{"message"=>"MediaType of 'application/x-www-form-urlencoded' is not supported by this resource", "errorCode"=>"UNSUPPORTED_MEDIA_TYPE"}
the responsible code looks like:
require 'rubygems'
require 'httparty'
class Accounts
include HTTParty
format :json
...[set headers and root_url etc]
def self.save
Accounts.set_headers
response = (post(Accounts.root_url+"/sobjects/Account/", :body => {:name => "graham"}.to_json))
end
end
anyone have an idea why the body should be being posted as html and how to change this so that it definitely goes as json so that salesforce doesn't reject it?
Any help would be appreciated. cheers
The Content-Type header needs to be set to "application/json". This can be done by inserting :headers => {'Content-Type' => 'application/json'} as a parameter to post, ie:
response = post(Accounts.root_url+"/sobjects/Account/",
:body => {:name => "graham"}.to_json,
:headers => {'Content-Type' => 'application/json'} )
You have to set the Content-Type header to application/json. I haven't used HTTParty, but it looks like you have to do something like
response = (post(Accounts.root_url+"/sobjects/Account/", :body => {:name => "graham"}.to_json) , :options => { :headers => { 'Content-Type' => 'application/json' } } )
I'm somewhat surpised that the format option doesn't do this automatically.

Resources