Ruby RestClient post request with cookies - ruby

I've been trying for over a week now with no joy to post an api request setting the cookies with values from a previous request. First request is fine:
response = RestClient.post ('http://api-qa1:8180/api/rest/GB/session'),'{"email":""}',:content_type => 'application/json'
obj = JSON.parse(response)
id = obj['id']
profileId = obj['profile_id']
#cookies = response.cookies
dyn = obj['verification_id']
jsessionid = #cookies['JSESSIONID']
puts jsessionid,dyn,profileID
I get a response and the values i need, I now want to use the values returned 'profile_id'(URi), jsessionid(cookie), and dyn(cookie) values to form my second request.
res = RestClient.post ("http://api-qa1:8180/api/rest/GB/profile/#{profileId}/cart/item"),
'{
"sku_id":"1234"
"product_id":"1234"
"quantity":"2"
"recommended":"false"
}',
headers = {
:content_type => 'application/json',
:userPrefLanguage => 'en-GB'
}
cookies = {'JSESSIONID' => jsessionid},{'DYN_USER_CONFIRM' => dyn }
I've tried many combinations all to no avail, this is as far as i've got which gives me a 403, im also aware that post request should have a maximum of 3 arguments I just cant get it to work. The cookies properties i need to set are
DYN_USER_CONFIRM and JSESSION.

Just looking at the documentation for RestClient:
response.cookies
# => {"_applicatioN_session_id" => "1234"}
response2 = RestClient.post(
'http://localhost:3000/',
{:param1 => "foo"},
{:cookies => {:session_id => "1234"}}
)
It looks like you need to set cookies and headers as a hash inside of the request. The code you've posted has cookies = .... and it's not inside of the request. You need to set headers in a hash as well I believe.

Related

HTTParty post method doesn't return status code when adding follow_redirects = false along with other headers and cookies?

The HTTParty methods are like HTTParty.XXX(urlGoesHere, and Args Here)
I'm doing the following:
params = {:UserName => "uname", :Password => "pwd"}
cookie_hash = HTTParty::CookieHash.new
cookie_hash.add_cookies("key1=val1")
cookie_hash.add_cookies("key2=val2")
options = {
:body=>params,
:headers => { 'Cookie' => cookie_hash.to_cookie_string,
'Accept' => something },
:follow_redirects => false
}
URLUserNamePwd = HTTParty.post(myURL, options) # Is this the right way to do?
When I check the http status code, body I get nothing. When I check in the browser development console, I see 302 redirect, and in response headers I see lot of header pairs returned.
What is the URL you're attempting to hit? 302 Found will be paired with a Location header containing the URL where the resource can be found.

In ruby with sinatra, How to get I response with get method on rest client?

I use ruby with sinatra and I used rest-client on import for payment.
I got token that string typed through post method on specific url: '... /users/getToken'.
Using this token, I wanna get payments information with get method on this url:
get_url = 'https://api/iamport.kr/payments/'+imp_uid
the detail codes are below,
def get_paymentsdetails(token, imp_uid)
get_url = 'https://api.iamport.kr/payments/'+imp_uid
response = RestClient.get get_url, :data => {}.to_json, :accept => :json, :headers => {'Authorization' => token}
json = JSON.parse(response, :symbolize_names => true)
# json = JSON.parse(response.to_json, {:symbolize_names => true})
return json
end
However, I got 401 unauthorized error on this part of code.
response = RestClient.get get_url, :data => {}.to_json, :accept => :json, :headers => {'Authorization' => token}
After I access get_url with specific imp_uid, I got this page,{"code":-1,"message":"Unauthorized","response":null}
I checked parameter token and imp_uid of get_paymentsdetails function have valid string values,, so How can I access response parameter??
I think that there are some problems on response = RestClient.get get_url.... code.
Thanks.
Method 'get' from the 'RestClient' class return some object with attributes. So response have few values. Which of them do you need? Access to them you can get by their names, its described here.
In your case, after response = RestClient.get get_url... you should have variable response and ability to call response.headers, response.code or response.body.
But im afraid that you have some problems with autorization, which means that imp_uid or token is not correct. Thats why remote server sended to you responce with http-code 401 (Unauthorized). If it is so you should try to check your imp_uid and token. If everything is correct try to reach support of iamport.kr .

Sending a http post request in ruby [duplicate]

So here's the request using curl:
curl -XPOST -H content-type:application/json -d "{\"credentials\":{\"username\":\"username\",\"key\":\"key\"}}" https://auth.api.rackspacecloud.com/v1.1/auth
I've been trying to make this same request using ruby, but I can't seem to get it to work.
I tried a couple of libraries also, but I can't get it to work.
Here's what I have so far:
uri = URI.parse("https://auth.api.rackspacecloud.com")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new("/v1.1/auth")
request.set_form_data({'credentials' => {'username' => 'username', 'key' => 'key'}})
response = http.request(request)
I get a 415 unsupported media type error.
You are close, but not quite there. Try something like this instead:
uri = URI.parse("https://auth.api.rackspacecloud.com")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new("/v1.1/auth")
request.add_field('Content-Type', 'application/json')
request.body = {'credentials' => {'username' => 'username', 'key' => 'key'}}.to_json
response = http.request(request)
This will set the Content-Type header as well as post the JSON in the body, rather than in the form data as your code had it. With the sample credentials, it still fails, but I suspect it should work with real data in there.
There's a very good explanation of how to make a JSON POST request with Net::HTTP at this link.
I would recommend using a library like HTTParty. It's well-documented, you can just set up your class like so:
class RackSpaceClient
include HTTParty
base_uri "https://auth.api.rackspacecloud.com/"
format :json
headers 'Accept' => 'application/json'
#methods to do whatever
end
It looks like the main difference between the Ruby code you placed there, and the curl request, is that the curl request is POSTing JSON (content-type application/json) to the endpoint, whereas request.set_form_data is going to send a form in the body of the POST request (content-type application/x-www-form-urlencoded). You have to make sure the content going both ways is of type application/json.
All others are too long here is a ONE LINER:
Net::HTTP.start('auth.api.rackspacecloud.com', :use_ssl => true).post(
'/v1.1/auth', {:credentials => {:username => "username",:key => "key"}}.to_json,
initheader={'Content-Type' => 'application/json'}
)
* to_json needs require 'json'
OR if you want to
NOT verify the hosts
be more readable
ensure the connection is closed once you're done
then:
ssl_opts={:use_ssl => true, :verify_mode => OpenSSL::SSL::VERIFY_NONE}
Net::HTTP.start('auth.api.rackspacecloud.com', ssl_opts) { |secure_connection|
secure_connection.post(
'/v1.1/auth', {:credentials => {:username => "username",:key => "key"}}.to_json,
initheader={'Content-Type' => 'application/json'}
)
}
In case it's tough to remember what params go where:
SSL options are per connection so you specify them while opening the connection.
You can reuse the connection for multiple REST calls to same base url. Think of thread safety of course.
Header is a "request header" and hence specified per request. I.e. in calls to get/post/patch/....
HTTP.start(): Creates a new Net::HTTP object, then additionally opens the TCP connection and HTTP session.
HTTP.new(): Creates a new Net::HTTP object without opening a TCP connection or HTTP session.
Another example:
#!/usr/bin/ruby
require 'net/http'
require 'json'
require 'uri'
full_url = "http://" + options[:artifactory_url] + "/" + "api/build/promote/" + options[:build]
puts "Artifactory url: #{full_url}"
data = {
status: "staged",
comment: "Tested on all target platforms.",
ciUser: "builder",
#timestamp: "ISO8601",
dryRun: false,
targetRepo: "#{options[:target]}",
copy: true,
artifacts: true,
dependencies: false,
failFast: true,
}
uri = URI.parse(full_url)
headers = {'Content-Type' => "application/json", 'Accept-Encoding'=> "gzip,deflate",'Accept' => "application/json" }
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri, headers)
request.basic_auth(options[:user], options[:password])
request.body = data.to_json
response = http.request(request)
puts response.code
puts response.body

Ruby Http Post Parameters

How can I add post parameters to what I have right now:
#toSend = {
"nonce" => Time.now.to_i,
"command" => "returnCompleteBalances"
}.to_json
uri = URI.parse("https://poloniex.com/tradingApi")
https = Net::HTTP.new(uri.host,uri.port)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
req = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/json'})
req.set_form_data({"nonce" => Time.now.to_i, "command" => "returnCompleteBalances"})
req['Key'] = '******-N4WZI2OG-******-10RX5JYR'
req['Sign'] = 'secret_key'
req.body = "[ #{#toSend} ]"
res = https.request(req)
puts "Response #{res.code} #{res.message}: #{res.body}"
These are the params I want to send:
"nonce" => Time.now.to_i,
"command" => "returnCompleteBalances"
Thank you.
It appears that you're trying to use Poloniex's trading API. If this is your primary goal, you might wish to consider using a library to handle the nitty-gritty details. For example:
https://github.com/Lowest0ne/poloniex
If your primary goal is not simply to use the API, but to use this as a learning experience, here are a few pointers:
The API documentation indicates that the API accepts form-encoded POST data (not JSON) but responds with JSON.
The key parameter ("Key") is like your user id. It allows Poloniex to understand who is attempting to make a request against the API.
The signature parameter ("Sign") is an HMAC generated from the contents of your secret key and the contents of your message (the encoded form data). This produces a sort of fingerprint that only you and Poloniex have the information to reproduce, giving some level of assurance that your request originated from the owner of the secret key. Of course, this assumes that your secret key is indeed only known by you.
I don't use the Poloniex exchange and cannot test this code, but I believe this is close to what you're attempting to accomplish:
require 'net/http'
require 'openssl'
secret = 'your-secret-key'
api_key = 'your-api-key'
uri = URI('https://poloniex.com/tradingApi')
http = Net::HTTP.new(uri.host)
request = Net::HTTP::Post.new(uri.request_uri)
form_data = URI.encode_www_form({:command => 'returnBalances', :nonce => Time.now.to_i * 1000 })
request.body = form_data
request.add_field('Key', api_key)
request.add_field('Sign', OpenSSL::HMAC.hexdigest( 'sha512', secret, form_data))
res = http.request(request)
puts res.body

Specifying Content Type in rspec

I'm trying to build an rspec test that sends JSON (or XML) via POST. However, I can't seem to actually get it working:
json = {.... data ....}.to_json
post '/model1.json',json,{'CONTENT_TYPE'=>'application/json'}
and this
json = {.... data ....}.to_json
post '/model1.json',json,{'Content-Type'=>'application/json'}
any ideas? THANKS!
In Rails 3, you can skip the header and #request.env stuff and just add a format parameter to your post call, e.g.:
post :create, format: :json, param: 'Value of Param'
There's a way to do this described in this thread -- it's a hack, but it seems to work:
#request.env["HTTP_ACCEPT"] = "application/json"
json = { ... data ... }.to_json
post :create, :some_param => json
A lot of frustration and variations and that's what worked for me.
Rails 3.2.12 Rspec 2.10
#request.env["HTTP_ACCEPT"] = "application/json"
#request.env["CONTENT_TYPE"] = "application/json"
put :update, :id => 1, "email" => "bing#test.com"
First of all, you don't want to test the built-in conversion of json to hash. Same applies to xml.
You test controller with data as hashes, not bothering wether it's json, xml or from a html form.
But if you would like to do that as an exercise, this is a standalone ruby script to do play with :)
require 'json'
url = URI.parse('http://localhost:3030/mymodels.json')
request = Net::HTTP::Post.new(url.path)
request.content_type="application/json"
request.basic_auth('username', 'password') #if used, else comment out
hash = {:mymodel => {:name => "Test Name 1", :description => "some data for testing description"}}
request.body = hash.to_json
response = Net::HTTP.start(url.host, url.port) {|http| http.request(request)}
puts response
to switch to xml, use content_type="text/xml" and
request.body = "<?xml version='1.0' encoding='UTF-8'?><somedata><name>Test Name 1</name><description>Some data for testing</description></somedata>"
A slightly more elegant test is to use the header helper:
header "HTTP_ACCEPT", "application/json"
json = {.... data ....}.to_json
post '/model1.json', json
Now this does exactly the same thing as setting #env; it's just a bit prettier.
The best way that I have found to test these things is with request tests. Request tests go through the full param parsing and routing stages of Rails. So I can write a test like this:
request_params = {:id => 1, :some_attribute => "some value"}
headers = {'Accept' => 'application/json', 'Content-Type' => 'application/json'}
put "/url/path", request_params.to_json, headers
expect(response).to be_success
I think that you can specify the headers with headers param:
post '/model1.json', headers: {'Content-type': 'application/json'}
Following the Rspec documentation of how provide JSON data.
#request.env["CONTENT_TYPE"] = "application/json"
OR pass in request
"CONTENT_TYPE" => "application/json"

Resources