Add parameters to post request with Rest-client rails - ruby-on-rails

I need to make a Post request using Rest-Client in my rails backend. I can successfully do it by the following: rv = RestClient.post URL, id.to_json, :content_type => 'application/json'
I need to add a tag parameter but can't make it work. I've tried different combinations of the following: rv = RestClient.post URL, {:params => {:tag => 'TAG'}}, id.to_json, :content_type => 'application/json' and receive errors about syntax (wrong number of arguments). The params would go on the url, the id.to_json would be part of the body. I can't find documentation that talks about this specific use case.

You can use to_query to convert a hash into a HTTP query string like so:
url_params = {:tag => "TAG"}.to_query
=> "tag=TAG"
Then just use that to construct your entire URL:
rv = RestClient.post "#{URL}?#{url_params}", id.to_json, :content_type => 'application/json'

there is another way to add url parameters to the request, it is notable that you have not sent the post parameters to RestClient in the correct order, which is url , payload, headers. and the headers can include any other tag, like :params.
rv = RestClient.post(URL, id.to_json, {:params => {:tag => 'TAG'},
:content_type => 'application/json' })

Related

Use Hash value on url with Nokogiri or RestClient

I have a url like :
http://172.0.0.1:22230/test.action?data={"foo":"bar","joe":"doe"}&sign=x6das
In my browser I can get data from that url, but if I'm use nokogiri
Nokogiri::HTML(open('http://172.0.0.1:22230/test.action?data={"foo":"bar","joe":"doe"}&sign=x6das'))
I get
URI::InvalidURIError: bad URI(is not URI?): http://172.0.0.1:22230/test.action?data={"foo":"bar","joe":"doe"}&sign=x6das
from /home/worka/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/uri/common.rb:176:in `split'
Also with RestClient
RestClient.get 'http://172.0.0.1:22230/test.action?data={"foo":"bar","joe":"doe"}&sign=x6das'
I got same an error.
Encode your url first then use it.
url = 'http://172.0.0:22230/test.action?data={"foo":"bar","joe":"doe"}&sign=x6das'
encoded_url = CGI::escape(url)
Nokogiri::HTML(open(encoded_url))
When dealing with URIs, it's a good idea to use the tools designed for them such as URI, which comes with Ruby.
The URI can't be
http://172.0.0.1:22230/test.action?data={"foo":"bar","joe":"doe"}&sign=x6das
because the data component is invalid. If you are adding data then I'd start with:
require 'uri'
uri = URI.parse('http://172.0.0.1:22230/test.action?sign=x6das')
query = URI.decode_www_form(uri.query).to_h # => {"sign"=>"x6das"}
data = {"foo" => "bar","joe" => "doe"}
uri.query = URI.encode_www_form(query.merge(data)) # => "sign=x6das&foo=bar&joe=doe"
uri.to_s # => "http://172.0.0.1:22230/test.action?sign=x6das&foo=bar&joe=doe"
Your initial example using {"foo":"bar","joe":"doe"} is JSON serialized data, which usually isn't passed in a URL like that. If you need to create JSON, start with the initial hash:
require 'json'
data = {"foo" => "bar","joe" => "doe"}
data.to_json # => "{\"foo\":\"bar\",\"joe\":\"doe\"}"
to_json serializes the hash into a string, which could then be encoded into the URI:
data = {"foo" => "bar","joe" => "doe"}
uri = URI.parse('http://172.0.0.1:22230/test.action?sign=x6das')
query = URI.decode_www_form(uri.query).to_h # => {"sign"=>"x6das"}
uri.query = URI.encode_www_form(query.merge('data' => data.to_json)) # => "sign=x6das&data=%7B%22foo%22%3A%22bar%22%2C%22joe%22%3A%22doe%22%7D"
But again, sending encoded JSON as a query parameter in the URI is not very common or standard since data payload is smaller without the JSON encoding.
Ok I got solved my problem
url = http://172.0.0.1:22230/test.action?data={"foo":"bar","joe":"doe"}&sign=x6das
RestClient.get(URI.encode(url.strip))

The content type 'application/x-www-form-urlencoded' is not supported in Ruby on Rails

So I'm just trying to make a simple post request using httpclient in RoR.
I'm going through a proxy, doing ntlm authentication with the server ( I can make GET requests without a problem).
Now when I try and do a post request, I get the error mentioned in the title...
proxy = ENV['HTTP_PROXY']
client=HTTPClient.new(proxy)
client.set_auth(nil,user,pass)
body= [{'Content-Type' => 'application/atom+xml, :content => ...}]
res = client.post('url',body)
puts res.body
How am i getting this error when I clearly specify the header as atom+xml..?
You should use
res = client.post('url',
:body => "...body content...",
:header => {'Content-Type' => 'application/atom+xml'})

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

Ruby: HTTParty: can't format XML POST data correctly?

NOTE: "object" is a placeholder work, as I don't think I should be saying what the controller does specifically.
so, I have multiple ways of calling my apps API, the following works in the command line:
curl -H 'Content-Type: application/xml' -d '<object><name>Test API object</name><password>password</password><description>This is a test object</description></object>' "http://acme.example.dev/objects.xml?api_key=1234"
the above command generates the following request in the devlog:
Processing ObjectsController#create to xml (for 127.0.0.1 at 2011-07-07 09:17:51) [POST]
Parameters: {"format"=>"xml", "action"=>"create", "api_key"=>"1234", "controller"=>"objects",
"object"=>{"name"=>"Test API object", "description"=>"This is a test object", "password"=>"[FILTERED]"}}
Now, I'm trying to write tests for the actions using the API, to make sure the API works, as well as the controllers.
Here is my current (broken) httparty command:
response = post("create", :api_key => SharedTest.user_api_key, :xml => data, :format => "xml")
this command generates the following request in the testlog:
Processing ObjectsController#create to xml (for 0.0.0.0 at 2011-07-07 09:37:35) [POST]
Parameters: {
"xml"=>"<object><name><![CDATA[first post]]></name>
<description><![CDATA[Things are not as they used to be]]></description>
<password><![CDATA[WHEE]]></password>
</object>",
"format"=>"xml",
"api_key"=>"the_hatter_wants_to_have_tea1",
"action"=>"create",
"controller"=>"objects
So, as you can see, the command line command actually generates the object hash from the xml, whereas the httparty command ends up staying in xml, which causes problems for the create method, as it needs a hash.
Any ideas / proper documentation?
Current documentation says that post takes an url, and "options" and then never says what options are available
**EDIT:
as per #Casper's suggestion, my method now looks like this:
def post_through_api_to_url(url, data, api_key = SharedTest.user_api_key)
response = post("create", {
:query => {
:api_key => api_key
},
:headers => {
"Content-Type" => "application/xml"
},
:body => data
})
ap #request.env["REQUEST_URI"]
assert_response :success
return response
end
unfortunately, the assert_response fails, because the authentication via the api key fails.
looking at the very of of the request_uri, the api_key isn't being set properly... it shows:
api_key%5D=the_hatter_wants_to_have_tea1"
but it should just be equals, without the %5D (right square bracket)
I think this is how you're supposed to use it:
options = {
:query => {
:api_key => 1234
},
:headers => {
"Content-Type" => "application/xml"
},
:body => "<xmlcode>goes here</xmlcode>"
}
post("/create", options)
Forgive me for being basic about it but if you only want to send one variable as a parameter, why don't you do as Casper suggests, but just do:
post("/create?api_key=1234", options)
Or rather than testing HTTParty's peculiarities in accessing your API, perhaps write your tests using Rack::Test? Very rough example...
require "rack/test"
require "nokogiri"
class ObjectsTest < Test::Unit::TestCase
include Rack::Test::Methods
def app
MyApp.new
end
def create_an_object(o)
authorize "x", "1234" # or however you want to authenticate using query params
header 'Accept', 'text/xml'
header 'Content-Type', 'text/xml'
body o.to_xml
post "/create"
xml = Nokogiri::XML(last_response.body)
assert something_logic_about(xml)
end
end

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