team city api returns json example - ruby

I'm struggling with getting results from the team city api in JSON
require 'open-uri'
url = ".../app/rest/buildQueue/"
c = Curl::Easy.new(url) do |curl|
curl.headers["Content-type"] = "application/json"
curl.http_auth_types = :basic
curl.username = 'user'
curl.password = 'password'
end
c.perform
puts c.body_str
I get a bunch of xml text

You need to use the Accept header to control the response type:
e.g (command line)
curl --url http://xxx/app/rest/buildQueue/ -H Accept:"application/json"
Documentation Reference

also you can use "net/http"
require 'net/http'
require 'uri'
url = URI('http://localhost:8111/httpAuth/app/rest/agents')
req = Net::HTTP::Get.new(url)
req['Accept'] = 'application/json'
req.basic_auth 'admin', 'admin'
res = Net::HTTP.start(url.hostname, url.port) {|http|
http.request(req)
}
puts res.body

Related

Trouble passing params into GET request - Ruby script

I have a Ruby script that issues a GET request to a restful API, but it ignores the params that I'm trying to pass in. I want to just get the activated users but it returns all of the users.
Am I not passing in my params correctly? This is my script:
require 'net/http'
require 'net/https'
require 'time'
require 'api-auth'
require 'json'
URL = 'https://<instance name>.mingle-api.thoughtworks.com/api/v2/users.xml'
OPTIONS = {:access_key_id => '<sign in name>', :access_secret_key => '<secret key>'}
PARAMS = {:user => { :activated => true } }
def http_get(url, options={}, params)
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
body = params.to_json
request = Net::HTTP::Get.new(uri.request_uri)
request.body = body
request['Content-Type'] = 'application/json'
request['Content-Length'] = body.bytesize
ApiAuth.sign!(request, options[:access_key_id], options[:access_secret_key])
response = http.request(request)
users = response.body
if response.code.to_i > 300
raise StandardError, <<-ERROR
Request URL: #{url}
Response: #{response.code}
Response Message: #{response.message}
Response Headers: #{response.to_hash.inspect}
Response Body: #{response.body}
ERROR
end
puts users
end
http_get(URL, OPTIONS, PARAMS)
The response is XML of users, formatted like this:
<user>
<id type="integer">2228</id>
<name>NAME</name>
<login>example#example.com</login>
<email>example#example.com</email>
<light type="boolean">false</light>
<icon_path nil="true"></icon_path>
<activated type="boolean">true</activated>
<admin type="boolean">false</admin>
</user>
I'm still a beginner when it comes to coding, so any help is greatly appreciated! Thank you!
You are putting the parameters for the get request in the body, when you should be placing them in the URL, so that the end of the URL looks something like this:
?param1=value1&param2=value2
Use a function like this (source):
require 'uri'
def hash_to_query(hash)
return URI.encode(hash.map{|k,v| "#{k}=#{v}"}.join("&"))
end
When you create the URI:
uri = URI.parse("#{url}?#{hash_to_query(params)}")
Passing the params via the URL did not work for me.
I ended up pulling the data from the XML that was returned instead of narrowing the search. This returns the correct data:
require 'net/http'
require 'net/https'
require 'time'
require 'api-auth'
require 'json'
require 'nokogiri'
URL = 'https://<instance name>.mingle-api.thoughtworks.com/api/v2/users.xml'
OPTIONS = {:access_key_id => '<sign in name>', :access_secret_key => '<secret key>'}
def http_get(url, options={})
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri.request_uri)
ApiAuth.sign!(request, options[:access_key_id], options[:access_secret_key])
response = http.request(request)
users = response.body
if response.code.to_i > 300
raise StandardError, <<-ERROR
Request URL: #{url}
Response: #{response.code}
Response Message: #{response.message}
Response Headers: #{response.to_hash.inspect}
Response Body: #{response.body}
ERROR
end
return users
end
def extract_active_users
all_users = Nokogiri::XML(http_get(URL, OPTIONS))
all_users.search('//user').each do |user|
active_user = user.xpath('activated')
if active_user.text == 'true'
puts user
end
end
end
extract_active_users

how to set header['content-type']='application/json' in ruby

require 'net/http'
require 'rubygems'
require 'json'
url = URI.parse('http://www.xyxx/abc/pqr')
resp = Net::HTTP.get_response(url) # get_response takes an URI object
data = resp.body
puts data
this is my code in ruby, resp.data is giving me data in xml form.
rest api return xml data by default , and json if header content-type is application/json.
but i want data in json form.for this i have to set header['content-type']='application/json'.
but i do not know , how to set header with get_response method.to get json data.
def post_test
require 'net/http'
require 'json'
#host = '23.23.xxx.xx'
#port = '8080'
#path = "/restxxx/abc/xyz"
request = Net::HTTP::Get.new(#path, initheader = {'Content-Type' =>'application/json'})
response = Net::HTTP.new(#host, #port).start {|http| http.request(request) }
puts "Response #{response.code} #{response.message}: #{response.body}"
end
Use instance method Net::HTTP#get to modify the header of a GET request.
require 'net/http'
url = URI.parse('http://www.xyxx/abc/pqr')
http = Net::HTTP.new url.host
resp = http.get("#{url.path}?#{url.query.to_s}", {'Content-Type' => 'application/json'})
data = resp.body
puts data
You can simply do this:
uri = URI.parse('http://www.xyxx/abc/pqr')
req = Net::HTTP::Get.new(uri.path, 'Content-Type' => 'application/json')
res = Net::HTTP.new(uri.host, uri.port).request(req)

How to post json data with Rest API

require 'net/http'
require 'uri'
postData = Net::HTTP.post_form(URI.parse('http://localhost/restapi/index.php/api/posts'),
{'id'=>9,'firstname'=>"test","lastname"=>"test"})
puts postData.body
How can I send data in JSON form?
#toSend = {"id" =>5,"firstname" => "anurag","lastname" => "arya"}
I also tried this but it did not work:
#toSend.to_json
Example:
require 'rubygems'
require 'net/http'
require 'uri'
require 'json'
url = "http://localhost/restapi/index.php/api/posts"
uri = URI.parse(url)
data = {"id"=>11,
"firstname"=>"PWD","lastname"=>"last"}
headers = {'Content-Type' =>'application/json',
'Accept-Encoding'=> "gzip,deflate",
'Accept' => "application/json"}
http = Net::HTTP.new(uri.host,uri.port) # Creates a http object
#http.use_ssl = true # When using https
#http.verify_mode = OpenSSL::SSL::VERIFY_NONE
response = http.post(uri.path,data.to_json,headers)
puts response.code
puts response.body
postData=Net::HTTP.post_form(URI.parse('http://localhost/oecprashant/yiiIndex.php/api/rubyREST'),
{'data'=>jsonData})

RUBY - SSL, Basic Auth, and POST

I'm having quite a hard time with this -- seems like there are a few snippets of code lying around that I can't seem to piece together. I'm simply trying to POST key/value pairs, but getting Connection refused - connect(2) (Errno::ECONNREFUSED). Help!
require 'net/http'
require 'net/https'
require 'uri'
#http = Net::HTTP.new('https://my.url.com/path', 443)
#http.use_ssl = true
#http.start() { |http|
req = Net::HTTP.post_form(
URI.parse('https:///my.url.com/path'),
{'key1' => 'value1', 'key2' => 'value2'}
)
req.basic_auth 'username', 'password'
response = http.request(req)
puts response.body
}
HTTP#post_form will execute directly, ignoring your other settings. Try this instead:
require 'net/http'
require 'uri'
url = URI.parse('https://my.url.com/path')
req = Net::HTTP::Post.new(url.path)
req.basic_auth 'user', 'pass'
req.use_ssl = true
req.form_data({'key1' => 'val1', 'key2' => 'val2'})
resp = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }
puts resp
You are likely to run into trouble with the server's certificates. See my other post for instructions on how to get/configure them.
Found this question during my search for a solultion, and just to be clear emboss' code as is is non functional. What I got working is this (inside of a larger Sinatra application):
require 'net/http'
require 'net/https'
require 'uri'
set :api_username, 'usr'
set :api_passwor, 'pswd'
def do_auth_check params
puts params.inspect
url = URI.parse("https://my_auth_site.com:443/authenticate")
req = Net::HTTP::Post.new(url.path)
req.basic_auth options.api_username, options.api_password
req.set_form_data({'username' => params[:name], 'password' => params[:pass]})
sock = Net::HTTP.new(url.host, url.port)
sock.use_ssl = true
res = sock.start {|http| http.request(req) }
# you're on your own down here to identify success/failure, but for me 2xx/3xx was ok and 401/404/500/etc would be failure
return true if res.code.to_i < 400
return "Error logging in"
end

Ruby send JSON request

How do I send a JSON request in ruby? I have a JSON object but I dont think I can just do .send. Do I have to have javascript send the form?
Or can I use the net/http class in ruby?
With header - content type = json and body the json object?
uri = URI('https://myapp.com/api/v1/resource')
body = { param1: 'some value', param2: 'some other value' }
headers = { 'Content-Type': 'application/json' }
response = Net::HTTP.post(uri, body.to_json, headers)
require 'net/http'
require 'json'
def create_agent
uri = URI('http://api.nsa.gov:1337/agent')
http = Net::HTTP.new(uri.host, uri.port)
req = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json')
req.body = {name: 'John Doe', role: 'agent'}.to_json
res = http.request(req)
puts "response #{res.body}"
rescue => e
puts "failed #{e}"
end
HTTParty makes this a bit easier I think (and works with nested json etc, which didn't seem to work in other examples I've seen.
require 'httparty'
HTTParty.post("http://localhost:3000/api/v1/users", body: {user: {email: 'user1#example.com', password: 'secret'}}).body
This works on ruby 2.4 HTTPS Post with JSON object and the response body written out.
require 'net/http' #net/https does not have to be required anymore
require 'json'
require 'uri'
uri = URI('https://your.secure-url.com')
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
request = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
request.body = {parameter: 'value'}.to_json
response = http.request request # Net::HTTPResponse object
puts "response #{response.body}"
end
real life example, notify Airbrake API about new deployment via NetHttps
require 'uri'
require 'net/https'
require 'json'
class MakeHttpsRequest
def call(url, hash_json)
uri = URI.parse(url)
req = Net::HTTP::Post.new(uri.to_s)
req.body = hash_json.to_json
req['Content-Type'] = 'application/json'
# ... set more request headers
response = https(uri).request(req)
response.body
end
private
def https(uri)
Net::HTTP.new(uri.host, uri.port).tap do |http|
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
end
end
project_id = 'yyyyyy'
project_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
url = "https://airbrake.io/api/v4/projects/#{project_id}/deploys?key=#{project_key}"
body_hash = {
"environment":"production",
"username":"tomas",
"repository":"https://github.com/equivalent/scrapbook2",
"revision":"live-20160905_0001",
"version":"v2.0"
}
puts MakeHttpsRequest.new.call(url, body_hash)
Notes:
in case you doing authentication via Authorisation header set header req['Authorization'] = "Token xxxxxxxxxxxx" or http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html
A simple json POST request example for those that need it even simpler than what Tom is linking to:
require 'net/http'
uri = URI.parse("http://www.example.com/search.json")
response = Net::HTTP.post_form(uri, {"search" => "Berlin"})
I like this light weight http request client called `unirest'
gem install unirest
usage:
response = Unirest.post "http://httpbin.org/post",
headers:{ "Accept" => "application/json" },
parameters:{ :age => 23, :foo => "bar" }
response.code # Status code
response.headers # Response headers
response.body # Parsed body
response.raw_body # Unparsed body
It's 2020 - nobody should be using Net::HTTP any more and all answers seem to be saying so, use a more high level gem such as Faraday - Github
That said, what I like to do is a wrapper around the HTTP api call,something that's called like
rv = Transporter::FaradayHttp[url, options]
because this allows me to fake HTTP calls without additional dependencies, ie:
if InfoSig.env?(:test) && !(url.to_s =~ /localhost/)
response_body = FakerForTests[url: url, options: options]
else
conn = Faraday::Connection.new url, connection_options
Where the faker looks something like this
I know there are HTTP mocking/stubbing frameworks, but at least when I researched last time they didn't allow me to validate requests efficiently and they were just for HTTP, not for example for raw TCP exchanges, this system allows me to have a unified framework for all API communication.
Assuming you just want to quick&dirty convert a hash to json, send the json to a remote host to test an API and parse response to ruby this is probably fastest way without involving additional gems:
JSON.load `curl -H 'Content-Type:application/json' -H 'Accept:application/json' -X POST localhost:3000/simple_api -d '#{message.to_json}'`
Hopefully this goes without saying, but don't use this in production.
The net/http api can be tough to use.
require "net/http"
uri = URI.parse(uri)
Net::HTTP.new(uri.host, uri.port).start do |client|
request = Net::HTTP::Post.new(uri.path)
request.body = "{}"
request["Content-Type"] = "application/json"
client.request(request)
end
data = {a: {b: [1, 2]}}.to_json
uri = URI 'https://myapp.com/api/v1/resource'
https = Net::HTTP.new uri.host, uri.port
https.use_ssl = true
https.post2 uri.path, data, 'Content-Type' => 'application/json'
Using my favourite http request library in ruby:
resp = HTTP.timeout(connect: 15, read: 30).accept(:json).get('https://units.d8u.us/money/1/USD/GBP/', json: {iAmOne: 'Hash'}).parse
resp.class
=> Hash

Resources