diff --git a/.ruby-version b/.ruby-version index 276cbf9..005119b 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.3.0 +2.4.1 diff --git a/lib/bitbucket_rest_api/error.rb b/lib/bitbucket_rest_api/error.rb index 5ee3321..7c3c938 100644 --- a/lib/bitbucket_rest_api/error.rb +++ b/lib/bitbucket_rest_api/error.rb @@ -33,6 +33,7 @@ def initialize(message) bad_events no_events blank_value + refresh_token ].each do |error| require "bitbucket_rest_api/error/#{error}" end diff --git a/lib/bitbucket_rest_api/error/refresh_token.rb b/lib/bitbucket_rest_api/error/refresh_token.rb new file mode 100644 index 0000000..a8bb066 --- /dev/null +++ b/lib/bitbucket_rest_api/error/refresh_token.rb @@ -0,0 +1,12 @@ +# encoding: utf-8 + +module BitBucket #:nodoc + # Raised when BitBucket receives a RefreshToken error + module Error + class RefreshToken < BitBucketError + def initialize(env) + super(env) + end + end + end # Error +end # BitBucket diff --git a/lib/bitbucket_rest_api/repos/webhooks.rb b/lib/bitbucket_rest_api/repos/webhooks.rb index f1635e2..f39c2c1 100644 --- a/lib/bitbucket_rest_api/repos/webhooks.rb +++ b/lib/bitbucket_rest_api/repos/webhooks.rb @@ -62,7 +62,7 @@ def get(user_name_or_project_key, repo_name, hook_uuid) _validate_user_repo_params(user, repo) unless user? && repo? get_request( - "/2.0/repositories/#{user_name}/#{repo_name}/hooks/#{hook_uuid}" + "/2.0/repositories/#{user_name_or_project_key}/#{repo_name}/hooks/#{hook_uuid}" ) end diff --git a/lib/bitbucket_rest_api/request.rb b/lib/bitbucket_rest_api/request.rb index e194625..227afc4 100644 --- a/lib/bitbucket_rest_api/request.rb +++ b/lib/bitbucket_rest_api/request.rb @@ -28,6 +28,20 @@ def delete_request(path, params={}, options={}) request(:delete, path, params, options) end + def retry_token_refresh_errors + count = 0 + begin + yield + rescue BitBucket::Error::RefreshToken + count += 1 + if count <= 3 + sleep 0.3 * count + retry + end + raise + end + end + def request(method, path, params, options={}) if !METHODS.include?(method) raise ArgumentError, "unkown http method: #{method}" @@ -36,25 +50,28 @@ def request(method, path, params, options={}) puts "EXECUTED: #{method} - #{path} with #{params} and #{options}" if ENV['DEBUG'] - conn = connection(options) - path_prefix = (path.include?('/ssh') && BitBucket.options[:bitbucket_server]) ? '/rest/keys' : conn.path_prefix - path = (path_prefix + path).gsub(/\/\//,'/') if conn.path_prefix != '/' - - response = conn.send(method) do |request| - request['Authorization'] = "Bearer #{new_access_token}" unless new_access_token.nil? - case method.to_sym - when *(METHODS - METHODS_WITH_BODIES) - request.body = params.delete('data') if params.has_key?('data') - request.url(path, params) - when *METHODS_WITH_BODIES - request.path = path - unless params.empty? - # data = extract_data_from_params(params) - # request.body = MultiJson.dump(data) - request.body = MultiJson.dump(params) + response = retry_token_refresh_errors do + conn = connection(options) + path_prefix = (path.include?('/ssh') && BitBucket.options[:bitbucket_server]) ? '/rest/keys' : conn.path_prefix + path = (path_prefix + path).gsub(/\/\//,'/') if conn.path_prefix != '/' + + response = conn.send(method) do |request| + request['Authorization'] = "Bearer #{new_access_token}" unless new_access_token.nil? + case method.to_sym + when *(METHODS - METHODS_WITH_BODIES) + request.body = params.delete('data') if params.has_key?('data') + request.url(path, params) + when *METHODS_WITH_BODIES + request.path = path + unless params.empty? + # data = extract_data_from_params(params) + # request.body = MultiJson.dump(data) + request.body = MultiJson.dump(params) + end end end end + response.body end diff --git a/lib/bitbucket_rest_api/response/raise_error.rb b/lib/bitbucket_rest_api/response/raise_error.rb index 01724ca..bc0c89b 100644 --- a/lib/bitbucket_rest_api/response/raise_error.rb +++ b/lib/bitbucket_rest_api/response/raise_error.rb @@ -3,6 +3,8 @@ require 'faraday' require 'bitbucket_rest_api/error' +REFRESH_TOKEN = %r{Access token expired. Use your refresh token to obtain a new access token.} + module BitBucket class Response::RaiseError < Faraday::Response::Middleware @@ -11,6 +13,9 @@ def on_complete(env) when 400 raise BitBucket::Error::BadRequest.new(env) when 401 + if env[:body] =~ REFRESH_TOKEN + raise BitBucket::Error::RefreshToken.new(env) + end raise BitBucket::Error::Unauthorized.new(env) when 403 raise BitBucket::Error::Forbidden.new(env)