Convert Hash to specific string format in ruby - ruby

I would like to convert a hash: {"key1"=>"value1", "key2"=>"value2"} into a string which looks like this: '[{"key1" : "value1","key2" : "value2"}]'
Background: I'm making an API call from my rails Controller.
The curl equivalent of this request is curl -X POST -H 'Content-Type: application/json' -i 'valid_uri' --data '[{"key1" : "value1","key2" : "value2"}]'
So, to convert this in ruby, I tried the following:
require 'net/http'
require 'uri'
require 'json'
uri = URI.parse(VALID_URI)
header = {'Content-Type' => 'application/json'}
data = {"key1"=>"value1", "key2"=>"value2"}
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri, header)
request.body = Array.wrap(data1.to_s.gsub('=>',':')).to_s
response = http.request(request)
However, the format of request.body doesn't match the format of data in curl request which results in Net::HTTPBadRequest 400 Bad Request
Can someone please explain how can I achieve this? TIA

just use the json module:
require "json"
h=[{"key1"=>"value1", "key2"=>"value2"}]
string=h.to_json # => [{"key1":"value1","key2":"value2"}]

Related

How to use httparty instead of net/http or curl

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.

Add `Authorization Bearer` hash to Net::HTTP post request (Ruby)

How can I add Authorization Bearer to a POST request with Net::HTTP?
I can only find help for "basic authentication" in the documentation.
req.basic_auth 'user', 'pass'
Source: https://docs.ruby-lang.org/en/2.0.0/Net/HTTP.html#class-Net::HTTP-label-Basic+Authentication
I'm trying to replicate a curl that would look like:
> curl 'http://localhost:8080/places' -d '{"_json":[{"uuid":"0514b...",
> "name":"Athens"}]}' -X POST -H 'Content-Type: application/json' -H
> 'Authorization: Bearer eyJ0eXAiO...'
Currently I've gotten to:
require 'net/http'
require 'net/https'
require 'uri'
uri = URI('http://localhost:8080/places')
res = Net::HTTP.post_form(uri, '_json' => [{'uuid': '0514b...', 'name':'Athens'}])
But I'm having trouble figuring out how to add the Authentication: Bearer... part.
Does anyone have experience with this?
I dont think you can add custom headers with the post_form method. You can add it with post method. Try the code below:
uri = URI("http://localhost:8080/places")
params = [{'uuid': '0514b...', 'name':'Athens'}]
headers = {
'Authorization'=>'Bearer foobar',
'Content-Type' =>'application/json',
'Accept'=>'application/json'
}
http = Net::HTTP.new(uri.host, uri.port)
response = http.post(uri.path, params.to_json, headers)

Artifactory AQL post over ruby

I'm trying to query the Artifactory's AQL API using ruby code, I already checked that this code works on bash using curl:
curl -u admin:password -i -H "Accept: application/json" -X POST http://server.example.com:8081/artifactory/api/search/aql -T aql.aql
Where aql.aql contents are as follows:
items.find
(
{
"repo":{"$eq":"test-ASO"}
}
)
.include("name","property.*")
Now I'm trying to do the same using Ruby with this code:
#!/usr/bin/ruby
require 'rubygems'
require 'json'
require 'open-uri'
require 'uri'
require 'net/http'
payload ='items.find
(
{
"repo":{"$eq":"test-ASO"}
}
).include("name","property.*")'
uri = URI.parse("http://server.example.com:8081/artifactory/api/search/aql")
http = Net::HTTP.new(uri.host,uri.port)
req = Net::HTTP::Post.new(uri.path)
req.basic_auth 'user', 'password'
req.set_form_data(payload)
res = http.request(req)
puts res.body
But all that I get is:
{
"errors" : [ {
"status" : 400,
"message" : "Bad Request"
} ]
}
My guess is that the payload of the query has to be a file, as I did before with curl (-T parameter) but I don't think that using files for queries is a very elegant way to achieve this.
EDIT
Finally I achieved this by declaring the req.body variable with the proper content:
#!/usr/bin/ruby
require 'rubygems'
require 'json'
require 'open-uri'
require 'uri'
require 'net/http'
payload = 'items.find().include("name","property.*")'
uri = URI.parse("http://server.example.com:8081/artifactory/api/search/aql")
http = Net::HTTP.new(uri.host,uri.port)
req = Net::HTTP::Post.new(uri.path)
req["Content-Type"] = "text/plain"
req.basic_auth 'admin', 'password'
req.body = payload
res = http.request(req)
puts res.body

curl request in ruby

How would I make the following curl request in ruby?
curl -k -X GET -H "Content-Type: application/xml" -H "Accept: application/xml" -H "X-OFFERSDB-API-KEY: demo" 'http://testapi.offersdb.com/distribution/beta/offers?radius=10&postal_code=30305'
I'm having difficulty with some of the headers.
require 'net/http'
url = 'http://testapi.offersdb.com/distribution/beta/offers?radius=10&postal_code=30305'
mykey = 'demo'
request = Net::HTTP.new(url)
request.request_head('/', 'X-OFFERSDB-API-KEY' => mykey)
puts request
I think you need to create a request object, instead of an HTTP object. Then set headers on it.
require 'net/http'
url = 'http://testapi.offersdb.com/distribution/beta/offers?radius=10&postal_code=30305'
mykey = 'demo'
uri = URI(url)
request = Net::HTTP::Get.new(uri.path)
request['Content-Type'] = 'application/xml'
request['Accept'] = 'application/xml'
request['X-OFFERSDB-API-KEY'] = mykey
response = Net::HTTP.new(uri.host,uri.port) do |http|
http.request(request)
end
puts response
Source: http://ruby-doc.org/stdlib-1.9.3/libdoc/net/http/rdoc/Net/HTTPHeader.html

How to write this HTTPS POST request in ruby?

I'm pretty new in Ruby and Rails.
I want to send a HTTP POST request in my rails application, the request can be invoked by command line like:
curl -X POST -u "username:password" \
-H "Content-Type: application/json" \
--data '{"device_tokens": ["0C676037F5FE3194F11709B"], "aps": {"alert": "Hello!"}}' \
https://go.urbanairship.com/api/push/
The ruby code I wrote (actually it's glue code) is:
uri = URI('https://go.urbanairship.com/api/push')
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
request = Net::HTTP::Post.new(uri.request_uri, initheader = {'Content-Type' =>'application/json'})
request.basic_auth 'username', 'password'
request.body = ActiveSupport::JSON.encode({'device_tokens' => ["4872AAB82341AEE600C6E219AA93BB38B5144176037F2056D65FE3194F11709B"], "aps" => {"alert" => "Hello!"}})
response = http.request request # Net::HTTPResponse object
puts response.body
end
However, running the ruby code in Rails Console didn't give me expected result (the command line does). Can someone give me a hand? I've tried searching relevant posts and Ruby docs, however my knowledge in Ruby is not good enough to solve it.
require 'net/http'
require 'net/https'
https = Net::HTTP.new('go.urbanairship.com', 443)
https.use_ssl = true
path = '/api/push'
It's often tidier to create a little client class. I like HTTParty for that:
require 'httparty'
class UAS
include HTTParty
base_uri "https://go.urbanairship.com"
basic_auth 'username', 'password'
default_params :output => 'json'
#token = "4872AAB82341AEE600C6E219AA93BB38B5144176037F2056D65FE3194F11709B"
def self.alert(message)
post('/api/push/', {'device_tokens' => #token, 'aps' => {"alert" => message}})
end
end
Then you use it like so:
UAS.alert('Hello!')

Resources