如何使用 Ruby 从 GitHub API 获得经过身份验证的 API 请求限制

How to get authenticated API request limits from the GitHub API using Ruby

我正在尝试更新使用 recently (2021-08-08) Deprecated 的旧 Ruby 应用GitHub API 使用的身份验证方法能够发出较少限制的请求。在 URL 中提供 OATH2 身份验证令牌之前,但现在必须在 header.

请求中提供它们

我尝试了几种方法,但由于我不是Ruby程序员,所以无法解决问题。

使用 curl 执行此操作很简单并且有效,并且在 GitHub 文档页面中有示例。

# 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

使用 Ruby 是另一回事,因为看起来很多 Ruby 事情也发生了变化。


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>')


那些都给出了无用的错误... 然后有人发帖说你可能需要用到:

Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https')

我尝试开始工作的代码是:


#-----------------------------------------------------
# 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

因此从未应用令牌。

整个程序也在使用 oktokit,因此使用它的解决方案也可能有用。

如何使用新的 GitHubAPI 更改使其在 Ruby 中工作?

这个问题似乎更多地与 Ruby 文档维护不善有关,它似乎主要被过时的解决方案所掩盖。另一个最常见的问题是,在我给出(发现)的示例中,它们从未正确处理 SSL (HTTPS)。没有 SSL 就没有成功的 GitHub 交互。此外,据称他们也不接受请求 header.

中的空 User-Agent

正确(高度简化)的解决方案如下:

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

替换 OP 中适当位置的代码可以解决此问题。


为了将来参考,如果您需要将 curl 转换为 Ruby 的 net/http 格式,请使用此站点: