I have a curl request which works
curl -X GET -k 'https://APIADDRESSHERE' -u 'USERNAME:PASSWORD' -H 'Content-Type: application/json'
I can also get this working in ruby:
require 'net/http'
require 'uri'
require 'openssl'
uri = URI.parse("https://APIADDRESSHERE")
request = Net::HTTP::Get.new(uri)
request.basic_auth("USERNAME", "PASSWORD")
request.content_type = "application/json"
req_options = {
use_ssl: uri.scheme == "https",
verify_mode: OpenSSL::SSL::VERIFY_NONE,
}
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
However when I try this with httparty I keep getting a 401 error saying:
An Authentication object was not found in the SecurityContext This request requires HTTP authentication.
I have tried a lot of variations of the following but I'm stuck.
response = HTTParty.get('https://APIURLHERE', {"headers": { "Authorization:" => "BASE64ENCODEDUSERNAMEANDPASSWORD", "Content-Type" => "application/json" }})
Have you tried the following?
response = HTTParty.get('https://APIURLHERE', headers: { "Authorization:" => "BASE64ENCODEDUSERNAMEANDPASSWORD", "Content-Type" => "application/json" })
Ok I made a simple mistake somewhere along the way because the original solution from the similar post worked... Dont know how it didnt work 50 times last time I was working on this but it was clearly an error on my part somewhere.
Related
I'm using the following request in Curl
curl -X GET -k -H 'Content-Type: application/json' -H 'Authorization: Bearer XXXXXXX' -H 'RowId: 100' -i 'https://url.xxx/row'
and the request using REST_CLIENT (2.1.0):
RestClient::Request.execute(:url => "https://url.xxx/row", :method => :get, :verify_ssl => false, :headers => {:content_type => "application/json", :Authorization => "Bearer XXXXXXX", :RowId => 100})
RestClient::NotFound: 404 Not Found
The first one (Curl) is working, but the equivalent request in RestClient does not.
The problem is that rest-client is not passing all headers:
{:content_type => "application/json", :Authorization => "Bearer XXXXXXX", :RowId => 100}
only content_type and Authorization are used, the others are not taken when request is sending
There is a similar issue with net/http:
require 'net/http'
uri = URI('https://url.xxx/row')
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
https.ssl_version = :TLSv1
req = Net::HTTP::Get.new uri
req['content_type'] = 'application/json'
req['Authorization'] = "Bearer #{token}"
req['RowId'] = 100
res = https.request req
puts res.body
Any suggestions ?
Thx
rest-client will return 404 error in multiple cases not only for not found errors
the best way here is to return and check the server's response
as per their documentation: https://github.com/rest-client/rest-client#exceptions-see-httpwwww3orgprotocolsrfc2616rfc2616-sec10html
>> RestClient.get 'http://example.com/nonexistent'
Exception: RestClient::NotFound: 404 Not Found
>> begin
RestClient.get 'http://example.com/nonexistent'
rescue RestClient::ExceptionWithResponse => e
e.response
end
=> <RestClient::Response 404 "<!doctype h...">
probably also try to call e.response.body to check the error
I have a ruby script that I'm using to get info from a web page and update the page. I am getting some json info from the web page with:
`curl -s -u #{username}:#{password} #{HTTPS_PAGE_URL}`
And then I am updating the page with:
`curl -s -u #{username}:#{password} -X PUT -H 'Content-Type: application/json' -d'#{new_page_json_info}' #{HTTPS_PAGE_URL}`
I want to use Net::HTTP to do this instead. How can I do this?
For reference here is the confluence doc that I used to create the curl command in the first place: https://developer.atlassian.com/confdev/confluence-server-rest-api/confluence-rest-api-examples
can try doing something like:
uri = URI.parse("http://google.com/")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
request.basic_auth("username", "password")
Thank you http://jhawthorn.github.io/curl-to-ruby
That solved it. All you have to do is give that website your curl command and it will convert it into a ruby script.
For the first curl (this gets the json info from a page and sends it to stdout):
#!/usr/bin/env ruby
require 'net/http'
require 'uri'
uri = URI.parse("https://my.page.io/rest/api/content/")
request = Net::HTTP::Get.new(uri)
request.basic_auth("username", "password")
req_options = {
use_ssl: uri.scheme == "https",
}
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
# response.code
puts JSON.parse(response.body).to_hash
For the second (this updates the json info on a page):
#!/usr/bin/env ruby
require 'net/http'
require 'uri'
require 'json'
uri = URI.parse("https://my.page.io/rest/api/content/")
request = Net::HTTP::Put.new(uri)
request.basic_auth("username", "password")
request.content_type = "application/json"
request.body = "{Test:blah}"
req_options = {
use_ssl: uri.scheme == "https",
}
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
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
Would be very grateful if someone could help me convert this curl request into ruby?I have Been trying for a while and can't get the syntax correct.
curl -v -H "Content-Type: application/json" -H "X-Knack-Application-Id:000000" -H "X-Knack-REST-API-Key:000000" https://api.knackhq.com/v1/objects/object_6/records
tried:
uri = URI('https://api.knackhq.com/v1/objects/object_1/records')
Net::HTTP.start(uri.host, uri.port,
:use_ssl => uri.scheme == 'https') do |http|
request = Net::HTTP::Post.new uri
# API details of Knack
request["X-Knack-Application-Id"] = '56e72cd003219158'
request["X-Knack-REST-API-Key"] = 'd9c343d2-2a4b-291e0712a63a'
end
There are at least two issues.
First, in the cURL command you don't specify a method, hence by default it is a GET, but you use POST in Ruby.
Secondly, you are missing the part where you execute the HTTP request
http.request(request)
Here's the code:
uri = URI('https://api.knackhq.com/v1/objects/object_1/records')
req = Net::HTTP::Get.new(uri)
req["X-Knack-Application-Id"] = '56e72cd003219158'
req["X-Knack-REST-API-Key"] = 'd9c343d2-2a4b-291e0712a63a'
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(req)
end
More examples are available in the Net::HTTP documentation.
Did you try some gems? I often use RestClient for api reqests, here is my example:
RestClient.post("https://api.knackhq.com/v1/objects/object_6/records", {}, {"X-Knack-REST-API-Key" => "000000", "X-Knack-Application-Id"=>"000000"})
More information about: https://github.com/rest-client/rest-client
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