I'm trying to update an old Ruby app that was using the recently (2021-08-08) Deprecated
Authentication method used by GitHub API to be able to make less limited requests. Before the OATH2 authentication token(s) was supplied in the URL, but now they have to be supplied in the request header.
I have tried several methods, but as I am not a Ruby programmer, I am not able to solve the problem.
Using curl
for doing this is trivial and works and have example in the GitHub documentation pages.
# Simple, should give a rate limit of: 60
curl -H "Accept: application/vnd.github.v3 json" https://api.github.com/rate_limit
# Authenticated, should give a rate limit of: 5000
curl -H "Accept: application/vnd.github.v3 json" -H "Authorization: token <MY-40-CHAR-TOKEN>" https://api.github.com/rate_limit
Using Ruby is another story as it seem a lot of Ruby things also have changed since.
require 'net/http'
#-----------------------------------------------------
# Test-1
#-----------------------------------------------------
uri = URI("https://api.github.com/rate_limit")
params = { :Authorization => "token <MY-40-CHAR-TOKEN>", :Accept => "application/vnd.github.v3 json" }
uri.query = URI.encode_www_form(params)
res = Net::HTTP.get_response(uri)
puts res.body if res.is_a?(Net::HTTPSuccess)
#-----------------------------------------------------
# Test-2
#-----------------------------------------------------
uri = URI.parse("https://api.github.com/rate_limit")
http = Net::HTTP.new(uri.host, uri.port)
req = Net::HTTP::Get.new(uri.request_uri)
req["User-Agent"] = "my-ruby-script"
req["Accept"] = "application/vnd.github.v3 json"
req["Authorization"] = "token <MY-40-CHAR-TOKEN>"
res = http.request(req)
res["content-type"]
response.each_header do |key, value|
p "#{key} => #{value}"
end
puts res.body
#-----------------------------------------------------
# Test-3
#-----------------------------------------------------
uri = URI.parse('https://api.github.com/rate_limit')
http = Net::HTTP.new(uri.host, uri.port)
res = http.request_get(uri, 'User-Agent': 'myscript' , 'Accept': 'application/vnd.github.v3 json', 'Authorization': 'token <MY-40-CHAR-TOKEN>')
Those all gave useless errors... Then someone posted that you may need to use:
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https')
The code I'm trying to get to work is:
#-----------------------------------------------------
# Test-4
#-----------------------------------------------------
require 'net/http'
require 'json'
hLine = "-"*60
if (1)
access_token = "<MY-40-CHAR-TOKEN>"
if (access_token)
puts "Using access_token: #{access_token}"
# :headers => { "Authorization" => "token " access_token },
uri = URI.parse("https://api.github.com/rate_limit")
req = Net::HTTP::Get.new(uri)
req["User-Agent"] = "myscript"
req["Accept"] = "application/vnd.github.v3 json"
req["Authorization"] = "token #{access_token}"
res = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https')
else
uri = URI.parse("https://api.github.com/rate_limit")
end
res = Net::HTTP.get_response(uri)
if (res.message != "OK") # 200
puts "ERROR: Bad response code: #{res.code}\n"
puts res.body
else
debug = 1
if (debug)
puts hLine "\nResponse Headers:\n" hLine
puts "#{res.to_hash.inspect}\n"
puts hLine "\nBody:\n" hLine
puts "#{res.body}\n" hLine
end
rbr = JSON.parse(res.body)['resources']['core']
RTc = Time.at(rbr['reset'])
puts "\nCore"
puts " Rate limit : #{rbr['limit']}"
puts " Remaining : #{rbr['remaining']}"
puts " Refresh at : #{RTc}"
end
end
# OUTPUT:
#----------------------------------------------
# Core
# Rate limit : 60
# Remaining : 59
# Refresh at : 2022-01-25 20:40:52 0200
So the token is never applied.
The entire program is also using oktokit
, so a solution using that may also be useful.
How can I get this to work in Ruby with the new GitHub API changes?
CodePudding user response:
The issue seem to have more to do with poor Ruby documentation maintenance, it seem mostly obscured with outdated solutions. The other most common issue is, that in the examples I gave (found) they never handle SSL
(HTTPS) properly. There is no successful GitHub interaction without SSL. In addition it is stated that they also don't accept an empty User-Agent
in the request header.
The correct (highly simplified) solution is the following:
require 'net/http'
url = URI("https://api.github.com/rate_limit")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
req = Net::HTTP::Get.new(url)
req["Authorization"] = 'token <MY-40-CHAR-TOKEN>'
res = http.request(req)
puts res.read_body
Replacing the code in OP in the appropriate places fixes this.
For future reference, if you need to convert a curl
into Ruby's net/http
format, use this site: