Translating a curl command to httparty - ruby-on-rails

I want to consume some API data from a Rails app. A curl example is curl --data 'api_key=your_api_key&api_secret=your_api_secret&host_id=your_user_host_id' https://api.zoom.us/v1/webinar/list I have experimented with this at the terminal and I am seeing expected responses. I’m now experimenting in a ruby script using httparty. My question is how should I handle the ‘stuff’ before the endpoint (api_key…secret…ect)? Are these headers?
In regard to curl --data only tells me that it is a post request, but I'm not sure how that translates to httparty.
Here is a first attempt:
require 'httparty'
api_key = 'myKey'
api_secret = 'secret'
host_id = 'host'
data_type = 'JSON'
response = HTTParty.post("api_key&api_secret&host_id&data_type https://api.zoom.us/v1/webinar/list/registration")
puts response.parsed_response
But this gives me a bad URI response. If I run this same script with the endpoint only I do get a response code back from zoom saying that API key and secret are required.

Looking at this example I think this should work:
require 'httparty'
api_key = 'myKey'
api_secret = 'secret'
host_id = 'host'
data_type = 'JSON'
options = {
body: {
api_key: api_key,
api_secret: api_secret,
host_id: host_id,
data_type: data_type
}
}
response = HTTParty.post("https://api.zoom.us/v1/webinar/list/registration", options)
puts response.parsed_response
I get the response:
{"error"=>{"code"=>200, "message"=>"Invalid api key or secret."}}
which I think is a step in the right direction.

No those are not headers those are parameters. Header are usually denoated by the -H flag.
Try this:
require 'httparty'
query_params = {api_key: 'myKey',
api_secret: 'secret',
host_id: 'host',
data_type: 'JSON'}
response = HTTParty.post("api_key&api_secret&host_id&data_type https://api.zoom.us/v1/webinar/list/registration", :query => query_params)
puts response.parsed_response

Related

Get HTTPS GET request with headers in Ruby

I have the following curl command that works fine:
curl "https://api.multisafepay.com/v1/json/gateways" -X GET -H "api_key: e983177756a109e87aa5edbe05e0xxxxxxxxxxxx"
When I try to do the same from within Rails (I tried with HTTP and with Faraday I always get back a response that contains:
"error_info\": \"Invalid API key\"
This is the command I do for Faraday:
conn = Faraday.new 'https://api.multisafepay.com/v1/json/'
conn.headers = {'api_key' => 'e983177756a109e87aa5edbe05e0xxxxxxxxxxxx'}
conn.get 'gateways'
What is the difference with the Curl command that is giving a correct result set?
Edit: debugging into Faraday shows me that in this method:
def run_request(method, url, body, headers)
headers are nil? I'm continuing my search why this is.
I don't think you're giving Faraday the right URL. Try something like this
conn = Faraday.new do |f|
f.headers['api_token'] = <yourkey>
f.request :url_encoded
end
resp = conn.get('https://api.multisafepay.com/v1/json/gateways')
require 'rest-client'
require 'json'
response = RestClient.get("https://api.multisafepay.com/v1/json/gateways",
{'api_key' => 'e983177756a109e87aa5edbe05e0xxxxxxxxxxxx'}
)
puts JSON.parse(response, { symbolize_names: true })
#just in case try this one for header
#{:content_type => :json, :accept => :json, :api_key => 'e983177756a109e87aa5edbe05e0xxxxxxxxxxxx'}

How do I access an API service that doesn't have a Ruby gem?

So I want to access Glot.io that has just a barebones RESTful API from my Rails App.
Glot.io requires me to create an account and generates an API key for me -- pretty standard.
At a high-level, what is the best way for me to approach this?
Create an initializer file called glot.rb and what should I include there? Just my ENV_VARS to access the API service? Or do I not need that?
Then using the docs available to CREATE a snippet, what's the best approach to actually doing that? Should I use a CURL gem like curb to re-create this POST request?
curl --request POST \
--header 'Authorization: Token 99090-7abba-12389abcde' \
--header 'Content-type: application/json' \
--data '{"language": "python", "title": "test", "public": false, "files": [{"name": "main.py", "content": "print(42)"}]}' \
--url 'https://snippets.glot.io/snippets'
If so, what might the above look like?
Ideally I would love to get a high-level overview of the approach and then some code snippets of how I might proceed.
I would create a library (either create my own gem, or if just using it here, then in /lib) using net/http.
http://ruby-doc.org/stdlib-2.3.1/libdoc/net/http/rdoc/Net/HTTP.html
This is a very basic example, and could be done a number of ways. This example will allow you to to instantiate SnippetApi and set the URL. You can then call new_snippet, which will take the URL that you supplied, and make the API call.
To continue extending, you can change def new_snippet to def new_snippet(data), and then supply the data with your call.
Note: the filename should be snippet_api.rb to ensure that the "rails magic" works for autoloading.
lib/snippet_api.rb
require 'uri'
require 'net/http'
require 'net/https'
class SnippetApi
def initialize(url, api_token = ENV['API_TOKEN'])
#url = url
#api_token = api_token
end
def url
#url
end
def api_token
#api_token
end
def new_snippet
# https://snippets.glot.io/snippets
uri = URI.parse(self.url)
post_object = {'language': 'python', 'title': 'test', 'public': false, 'files': [{'name': 'main.py', 'content': 'print(42)'}]}
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
req = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' => 'application/json', 'Authorization': "Token #{self.api_token}"})
req.body = "[ #{post_object} ]"
res = https.request(req)
puts "Response #{res.code} #{res.message}: #{res.body}"
end
end
Usage
2.3.0 :001 > snippet_api = SnippetApi.new('https://snippets.glot.io/snippets')
=> #<SnippetApi:0x00000003b6bc20 #url="https://snippets.glot.io/snippets">
2.3.0 :002 > snippet_api.new_snippet
Response 404 Not Found: {"message":"Wrong auth token"}
To ensure that files in /lib are loaded, be sure to add this to application.rb:
config.autoload_paths += Dir["#{config.root}/lib/**/"]
Usage with API Token
[brian#...]$ export API_TOKEN='token from env'
2.3.0 :001 > snippet_api = SnippetApi.new('https://snippets.glot.io/snippets')
=> #<SnippetApi:0x0000000342e8e0 #url="https://snippets.glot.io/snippets", #api_token="token from env">
2.3.0 :002 > snippet_api.api_token
=> "token from env"
2.3.0 :003 > snippet_api = SnippetApi.new('https://snippets.glot.io/snippets','from init')
=> #<SnippetApi:0x000000033a60d0 #url="https://snippets.glot.io/snippets", #api_token="from init">
2.3.0 :004 > snippet_api.api_token
=> "from init"
Edit 1: Added information about loading lib files.

Quickblox Rails Signature

I am having a very hard time getting access to the quickblox API. Based on their documentation this code should work:
require 'base64'
require 'cgi'
require 'openssl'
require 'hmac-sha1'
# Application credentials
aPPLICATION_ID = 12345
aUTH_KEY = 'hidden'
aUTH_SECRET = 'hidden'
# Generate signature
timestamp = Time.now.in_time_zone('UTC').to_i
nonce = timestamp-425346
signature_string = "application_id=#{aPPLICATION_ID}&auth_key=#{aUTH_KEY}&nonce=#{nonce}&timestamp=#{timestamp}"
signature =Base64.encode64("#{ OpenSSL::HMAC.digest('sha1', signature_string, aUTH_SECRET) }")
# Post
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
request = Net::HTTP::Post.new("/session.json")
request.add_field('QuickBlox-REST-API-Version', '0.1.1')
request.add_field('Content-Type', 'application/json')
request.add_field('Accept', '*/*')
request.body = {"application_id" => aPPLICATION_ID, "auth_key" => aUTH_KEY, "nonce" => nonce, "timestamp" => timestamp, "signature" => signature }.to_json
response = http.request(request)
However I keep getting an error: {"errors":{"base":["Unexpected signature"]}}
Even when using their hurl: http://hurl.quickblox.com/ i get the exact same error. Very frustrating. What exactly am I doing wrong?
As it turns out, it looks like QuickBlox does not accept the signature has produced by ruby for some reason. QuickBlox even removed their own ruby gem (in which also generates this same error).
Right now the solution is to grab the token via a php script first then do your calls in ruby.
Check my stackoverflow answer on this issue here.
This mostly boils down to these two lines:
signature_string = "application_id=#{aPPLICATION_ID}&auth_key=#{aUTH_KEY}&nonce=#{nonce}&timestamp=#{timestamp}"
signature =Base64.encode64("#{ OpenSSL::HMAC.digest('sha1', signature_string, aUTH_SECRET) }")
You can check this quickblox_api gem too. It worked greatly for me.

http Post request And declaration of authorization header in rails

I am trying to perform an HTTP authorization using Ruby on Rails. Here is what I'm trying:
res = http.post(uri.request_uri,
:Authorization => cobSessionToken,
"coBrandSessionCredential=loginToken=#{cobSessionToken}&userLogin=#{login}&userPassword=#{password}")
render :json => {"isValid" => true, "Body" => JSON.parse(res.body)}
This doesn't seem to work. How can I perform an authorization?
how about something like this?
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
I would recommend using something like postman (its a free google program you can get at the google store) to make sure the error is not on the server side. Use Net:http it comes with ruby so you do not need to install it but you have to require it.
Require it by:
require "net/http"
require "uri"
Use this cheatsheet I think you need basic_auth.rb You will see how to form the request.

HTTParty and authorization via token

Somehow HTTParty returns 401 where CURL works fine. Not sure how to pass token in headers.
Working (200):
curl http://localhost:3020/api/products -H 'Authorization: Token token="111"'
Not working (401):
HTTParty.get('http://localhost:3020/api/products', headers: {"Authorization: Token token" => '111'})
I have tried with just "Authorization" => '111'and "token" => '111' but same result.
Managed to get it working as follows.
HTTParty.get("http://localhost:3020/api/products", headers: {"Authorization" => "Token token=\"111\""})
This also works if you want to set headers of the class dynamically, this example is for obtaining the Authorization token for Dun and Bradstreet
require 'httparty'
require 'certified'
class DnbAuth
include HTTParty
debug_output $stdout
base_uri "https://maxcvservices.dnb.com/rest/Authentication"
def initialize(ct,u,p)
self.class.headers 'Content-type' => "#{ct}"
self.class.headers 'x-dnb-user' => "#{u}"
self.class.headers 'x-dnb-pwd'=> "#{p}"
end
def token()
response = self.class.post("/")
end
end
ct = 'text/xml'
u = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
p = 'xxxxxx'
xx = DnbAuth.new(ct,u,p)
puts xx.token.message

Resources