Skip to content

Commit

Permalink
Merge pull request #1270 from jatindhankhar/add-context-for-octokit-e…
Browse files Browse the repository at this point in the history
…rrors

Add context with rate limit struct for Octokit::TooManyRequests  and Octokit:: AbuseDetected errors
  • Loading branch information
tarebyte committed Jul 9, 2020
2 parents 4ab6bb3 + 70f6ba6 commit dbea2c6
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 2 deletions.
10 changes: 9 additions & 1 deletion lib/octokit/error.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Octokit
# Custom error class for rescuing from all GitHub errors
class Error < StandardError

attr_reader :context
# Returns the appropriate Octokit::Error subclass based
# on status and response message
#
Expand Down Expand Up @@ -34,9 +34,16 @@ def self.from_response(response)
end
end

def build_error_context
if RATE_LIMITED_ERRORS.include?(self.class)
@context = Octokit::RateLimit.from_response(@response)
end
end

def initialize(response=nil)
@response = response
super(build_error_message)
build_error_context
end

# Documentation URL returned by the API for some errors
Expand Down Expand Up @@ -315,4 +322,5 @@ class ApplicationCredentialsRequired < StandardError; end
# Raised when a repository is created with an invalid format
class InvalidRepository < ArgumentError; end

RATE_LIMITED_ERRORS = [Octokit::TooManyRequests, Octokit::AbuseDetected]
end
2 changes: 1 addition & 1 deletion lib/octokit/rate_limit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class RateLimit < Struct.new(:limit, :remaining, :resets_at, :resets_in)
# @return [RateLimit]
def self.from_response(response)
info = new
if response && !response.headers.nil?
if response && response.respond_to?(:headers) && !response.headers.nil?
info.limit = (response.headers['X-RateLimit-Limit'] || 1).to_i
info.remaining = (response.headers['X-RateLimit-Remaining'] || 1).to_i
info.resets_at = Time.at((response.headers['X-RateLimit-Reset'] || Time.now).to_i)
Expand Down
47 changes: 47 additions & 0 deletions spec/octokit/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,53 @@
end
end

it "returns empty context when non rate limit error occurs" do
stub_get('/user').to_return \
:status => 509,
:headers => {
:content_type => "application/json",
},
:body => {:message => "Bandwidth exceeded"}.to_json
begin
Octokit.get('/user')
rescue Octokit::ServerError => server_error
expect(server_error.context).to be_nil
end
end

it "returns context with default data when rate limit error occurs but headers are missing" do
stub_get('/user').to_return \
:status => 403,
:headers => {
:content_type => "application/json",
},
:body => {:message => "rate limit exceeded"}.to_json
begin
expect_any_instance_of(Faraday::Env).to receive(:headers).at_least(:once).and_return({})
Octokit.get('/user')
rescue Octokit::TooManyRequests => rate_limit_error
expect(rate_limit_error.context).to be_an_instance_of(Octokit::RateLimit)
end
end

it "returns context when non rate limit error occurs but rate limit headers are present" do
stub_get('/user').to_return \
:status => 403,
:headers => {
'content_type' => 'application/json'
},
:body => {:message => "rate limit exceeded"}.to_json
begin
rate_limit_headers = {'X-RateLimit-Limit' => 60, 'X-RateLimit-Remaining' => 42, 'X-RateLimit-Reset' => (Time.now + 60).to_i}
expect_any_instance_of(Faraday::Env).to receive(:headers).at_least(:once).and_return(rate_limit_headers)
Octokit.get('/user')
rescue Octokit::TooManyRequests => rate_limit_error
expect(rate_limit_error.context).to be_an_instance_of(Octokit::RateLimit)
expect(rate_limit_error.context.limit).to eql 60
expect(rate_limit_error.context.remaining).to eql 42
end
end

describe "module call shortcut" do
before do
Octokit.reset!
Expand Down

0 comments on commit dbea2c6

Please sign in to comment.