Ruby github API - ruby-on-rails

I am new to ruby programming. I was trying to write below ruby code to create a comment in Github gist.
uri = URI.parse("https://api.github.com/gists/xxxxxxxxxxx/comments")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = (uri.scheme == 'https')
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(uri.request_uri)
request.body = {
"body" => "Chef run failed "
}.to_json
response = http.request(request)
response2 = JSON.parse(response.body)
puts response2
But I executed below script then I always get {"message"=>"Not Found", "documentation_url"=>"https://developer.github.com/v3"}
Don't know what I am doing wrong. Appreciate help.

Make sure that you're authenticated first. From the Github API docs on Authentication:
There are three ways to authenticate through GitHub API v3. Requests
that require authentication will return 404 Not Found, instead of 403
Forbidden, in some places. This is to prevent the accidental leakage
of private repositories to unauthorized users.
You can do this by creating an OAuth2 token and setting it as an HTTP header:
request['Authorization'] = 'token YOUR_OAUTH_TOKEN'
You can also pass the OAuth2 token as a POST parameter:
uri.query = URI.encode_www_form(access_token: 'YOUR_OAUTH_TOKEN')
# Encoding really isn't necessary though for this though, so this should suffice
uri.query = 'access_token=YOUR_OAUTH_TOKEN'

Related

Bad Request trying to call service with Digest Auth from ruby

I'm trying to call a service with Digest Auth from a rails application and it always returns a 400 bad request error.
I've used net-http-digest_auth gem to create the headers but I think I've missed something.
def get_digest(url)
uri = URI.parse(url)
http = Net::HTTP.new uri.host, uri.port
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
req = Net::HTTP::Get.new(uri.request_uri)
# Fist call with the 401 and auth headers
digest_response = http.request(req)
digest_auth_request = Net::HTTP::DigestAuth.new
uri.user = digest_auth[:user]
uri.password = digest_auth[:password]
auth = digest_auth_request.auth_header uri, digest_response['www-authenticate'], 'GET', true
req.add_field 'Authorization', auth
response = http.request(req)
# Response is always #<Net::HTTPBadRequest 400 Bad Request readbody=true>
if response.code.to_i == 200
response_body = response.body
else
error
end
response_body
end
The request's headers look like this:
Digest username=\"myuser#mydomain.com\", realm=\"Digest\", algorithm=MD5-sess, qop=\"auth\", uri=\"/path/WS/my%20user/path/path/path/path/service.svc\", nonce=\"+Upgraded+v1e3f88bce1c32bd15avn421e440ca6622ebadd4522f7ed201fab1421c39d8fd15b771b972c9eb59894f8879307b9e6a5544476bc05cc7885a\", nc=00000000, cnonce=\"d42e6ea8a37aadsasdbea1231232456709\", response=\"7fbfc75cc3aasdasd342230ebf57ac37df\""
I can't figure out what's happening, is there any other gem to make this easier?
Finally found the problem by comparing browser header vs ruby header.
I wasn't calculating "nc" (calls counter) correctly. After adding +1 it started to return a 401 error (now I have a different problem ;)).

Rails - How to add contacts to SendGrid marketing campaigns via API

I need to make HTTP get and post requests with SendGrid to add contacts to our account, however there doesn't seem to be a gem for their email marketing functionality.
It boils down to making a few requests however I can't get past their authentication step.
They say to do this
curl -X "GET" "https://api.sendgrid.com/v3/templates" -H "Authorization: Bearer Your.API.Key-HERE" -H "Content-Type: application/json"
And using the Rest-Client gem I'm trying to make the authentication request like so...
username = 'username'
api_key = 'SG.MY_API_KEY'
key = Base64.encode64(username + ":" + api_key)
headers = {"Authorization" => "Bearer #{key}", "Content-Type" => "application/json"}
response = RestClient.get 'https://api.sendgrid.com/v3/templates', headers
which returns...
RestClient::Unauthorized: 401 Unauthorized: {"errors":[{"field":null,"message":"authorization required"}]}
The ultimate objective of using their API is to add contacts.
How am I incorrectly making this get request?
I ended up figuring it out. For future reference, here's the code that worked...
require 'rest_client'
api_key = 'YOUR_API_KEY'
headers = {'Authorization' => "Bearer #{api_key}"}
data = {:email => 'email#website.com'}
response = RestClient.post 'https://api.sendgrid.com/v3/contactdb/recipients', [data].to_json, headers
To add marketing contacts to your SendGrid account via the API,
see the documentation at https://sendgrid.api-docs.io/v3.0/contacts-api-recipients/add-recipients
You can see sample code in the "code generation" section of the page.
require 'uri'
require 'net/http'
url = URI("https://api.sendgrid.com/v3/contactdb/recipients")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
request["authorization"] = 'Bearer <<YOUR_API_KEY>>'
request["content-type"] = 'application/json'
request.body = "[{\"email\":\"example#example.com\",\"first_name\":\"\",\"last_name\":\"User\",\"age\":25},{\"email\":\"example2#example.com\",\"first_name\":\"Example\",\"last_name\":\"User\",\"age\":25}]"
response = http.request(request)
puts response.read_body

Rails http GET request with no ssl verification and basic auth

I am trying to make a http get request as specified in the title.
What I've written:
uri = URI.parse("https://myaddress.com")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
#data = http.get(uri.request_uri)
The request is sent where I want it to be sent and I receive an Unauthorized response (as expected, because I did not specify the basic auth).
I've tried
http.basic_auth 'user', 'pass'
But there's no such method for the type of my http variable.
How can I add the auth details?
Update: I tried to use something like here RUBY - SSL, Basic Auth, and POST, but after replacing Post with Get, I cannot use the 'use_ssl', nor 'verify_mode' attributes (I get no such attribute error).
Update 2: I figured out that I can set the 'use_ssl' attribute on a Net::HTTP object and the 'basic_auth' on a Net::HTTP::Get object.
Now the question is how can I make them work together?
Well, I ended up finding an answer. Maybe this will help others:
url = URI.parse('https://myaddress.com')
req = Net::HTTP::Get.new(url.path)
req.basic_auth 'user', 'pass'
sock = Net::HTTP.new(url.host, url.port)
sock.use_ssl = true
sock.verify_mode = OpenSSL::SSL::VERIFY_NONE
resp = sock.start {|http| http.request(req) }

curl to Ruby request for connecting to wheniwork

Back story
I've spent a few days on the Ruby gem for wheniwork, and it's been a nightmare. To make a long story short, the gem had a dependency of an older version of activesupport and I basically forked their repo and made a compatible version for my ruby project. I was able to create a new gem and attempted to use it, but I was getting the following json message:
{"error"=>"User login required for this resource.", "code"=>1000}
The username, password, and api key were set. What I basically need to do is access our account on wheniwork, and retrieve data.
This is an example using the curl command
curl https://api.wheniwork.com/2/login \
--data '{"username":"user#example.com","password":"*******"}' \
-H "W-Key: iworksoharditsnotfunny"
Essentially, I would get some kind of return object from wheniwork that would contain the token. I'd use this token for future requests to the wheniwork site.
To (Ruby)
A new attempt to translate this to Ruby
require 'net/http'
data = {'credentials' => {'username' => 'XXXXX#XXXXX.com','password' => 'XXXXX', 'W-Key' => '111111111XXXXX'}}
uri = URI.parse("https://api.wheniwork.com/2/login/")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/json'})
request.add_field('Content-Type', 'application/json')
request.body = data.to_json
response = http.request(request)
Result:
#<Net::HTTPUnauthorized 401 Unauthorized readbody=true>
If you have any idea or clue (or basically anything that would help me here), I would appreciate it beyond words. Thanks!
Got it!! The major issue(s) were that the api key and (username+password) combo are two separate pieces.
I was so close the entire time, but here it is:
data = {'username' => 'XXXX#XXXXXXX.com','password' => 'XXXXX'}
uri = URI.parse("https://api.wheniwork.com/2/login/")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(uri.path)
request.add_field('W-Key', 'XXXXXXXXXXXXX')
request.body = data.to_json
response = http.request(request)
puts JSON.parse(response.body)

Running a HTTP request with rails

It has been a while since I have used Rails. I currently have a curl request as follows
curl -X GET -H 'Authorization: Element TOKEN, User TOKEN' 'https://api.cloud-elements.com/elements/api-v2/hubs/marketing/ping'
All I am looking to do is to be able to run this request from inside of a rails controller, but my lack of understanding when it comes to HTTP requests is preventing me from figuring it out to how best handle this. Thanks in advance.
Use this method for HTTP requests:
def api_request(type , url, body=nil, header =nil )
require "net/http"
uri = URI.parse(url)
case type
when :post
request = Net::HTTP::Post.new(uri)
request.body = body
when :get
request = Net::HTTP::Get.new(uri)
when :put
request = Net::HTTP::Put.new(uri)
request.body = body
when :delete
request = Net::HTTP::Delete.new(uri)
end
request.initialize_http_header(header)
#request.content_type = 'application/json'
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') {|http| http.request request}
end
Your example will be:
api_request(:get, "https://api.cloud-elements.com/elements/api-v2/hubs/marketing/ping",nil, {"Authorization" => "Element TOKEN, User TOKEN" })
It would be something like the following. Note that the connection will be blocking, so it can tie up your server depending on how quickly the remote host returns the HTTP response and how many of these requests you are making.
require 'net/http'
# Let Ruby form a canonical URI from our URL
ping_uri = URI('https://api.cloud-elements.com/elements/api-v2/hubs/marketing/ping')
# Pass the basic configuration to Net::HTTP
# Note, this is not asynchronous. Ruby will wait until the HTTP connection
# has closed before moving forward
Net::HTTP.start(ping_uri.host, ping_uri.port, :use_ssl => true) do |http|
# Build the request using the URI as a Net::HTTP::Get object
request = Net::HTTP::Get.new(ping_uri)
# Add the Authorization header
request['Authorization'] = "Element #{ELEMENT_TOKEN}, User #{user.token}"
# Actually send the request
response = http.request(request)
# Ruby will automatically close the connection once we exit the block
end
Once the block exits, you can use the response object as necessary. The response object is always a subclass (or subclass of a subclass) of Net::HTTPResponse and you can use response.is_a? Net::HTTPSuccess to check for a 2xx response. The actual body of the response will be in response.body as a String.

Resources