2018-07-25 08:22:53 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2018-06-25 16:06:10 -04:00
|
|
|
module BitbucketServer
|
|
|
|
class Connection
|
2018-07-05 17:09:01 -04:00
|
|
|
include ActionView::Helpers::SanitizeHelper
|
|
|
|
|
2018-07-25 08:22:53 -04:00
|
|
|
DEFAULT_API_VERSION = '1.0'
|
2018-08-01 00:14:36 -04:00
|
|
|
SEPARATOR = '/'
|
2018-06-25 16:06:10 -04:00
|
|
|
|
2019-01-12 18:18:22 -05:00
|
|
|
NETWORK_ERRORS = [
|
|
|
|
SocketError,
|
|
|
|
OpenSSL::SSL::SSLError,
|
|
|
|
Errno::ECONNRESET,
|
|
|
|
Errno::ECONNREFUSED,
|
|
|
|
Errno::EHOSTUNREACH,
|
|
|
|
Net::OpenTimeout,
|
|
|
|
Net::ReadTimeout,
|
|
|
|
Gitlab::HTTP::BlockedUrlError
|
|
|
|
].freeze
|
|
|
|
|
2018-06-25 16:06:10 -04:00
|
|
|
attr_reader :api_version, :base_uri, :username, :token
|
|
|
|
|
2018-07-13 01:33:36 -04:00
|
|
|
ConnectionError = Class.new(StandardError)
|
|
|
|
|
2018-06-25 16:06:10 -04:00
|
|
|
def initialize(options = {})
|
2018-08-01 13:44:45 -04:00
|
|
|
@api_version = options.fetch(:api_version, DEFAULT_API_VERSION)
|
|
|
|
@base_uri = options[:base_uri]
|
|
|
|
@username = options[:user]
|
|
|
|
@token = options[:password]
|
2018-06-25 16:06:10 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def get(path, extra_query = {})
|
|
|
|
response = Gitlab::HTTP.get(build_url(path),
|
|
|
|
basic_auth: auth,
|
2018-07-27 15:58:03 -04:00
|
|
|
headers: accept_headers,
|
2018-07-06 00:11:16 -04:00
|
|
|
query: extra_query)
|
2018-07-05 17:09:01 -04:00
|
|
|
|
|
|
|
check_errors!(response)
|
2018-07-13 01:33:36 -04:00
|
|
|
|
2018-06-25 16:06:10 -04:00
|
|
|
response.parsed_response
|
2019-01-12 18:18:22 -05:00
|
|
|
rescue *NETWORK_ERRORS => e
|
|
|
|
raise ConnectionError, e
|
2018-06-25 16:06:10 -04:00
|
|
|
end
|
|
|
|
|
2018-07-03 19:37:17 -04:00
|
|
|
def post(path, body)
|
2018-07-05 17:09:01 -04:00
|
|
|
response = Gitlab::HTTP.post(build_url(path),
|
2018-07-18 01:29:18 -04:00
|
|
|
basic_auth: auth,
|
|
|
|
headers: post_headers,
|
|
|
|
body: body)
|
2018-07-05 17:09:01 -04:00
|
|
|
|
|
|
|
check_errors!(response)
|
2018-07-13 01:33:36 -04:00
|
|
|
|
2018-07-13 02:17:05 -04:00
|
|
|
response.parsed_response
|
2019-01-12 18:18:22 -05:00
|
|
|
rescue *NETWORK_ERRORS => e
|
|
|
|
raise ConnectionError, e
|
2018-07-03 19:37:17 -04:00
|
|
|
end
|
|
|
|
|
2018-07-13 18:39:24 -04:00
|
|
|
# We need to support two different APIs for deletion:
|
|
|
|
#
|
|
|
|
# /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/branches/default
|
|
|
|
# /rest/branch-utils/1.0/projects/{projectKey}/repos/{repositorySlug}/branches
|
|
|
|
def delete(resource, path, body)
|
|
|
|
url = delete_url(resource, path)
|
|
|
|
|
|
|
|
response = Gitlab::HTTP.delete(url,
|
2018-07-18 01:29:18 -04:00
|
|
|
basic_auth: auth,
|
|
|
|
headers: post_headers,
|
|
|
|
body: body)
|
2018-07-13 18:39:24 -04:00
|
|
|
|
|
|
|
check_errors!(response)
|
|
|
|
|
|
|
|
response.parsed_response
|
2019-01-12 18:18:22 -05:00
|
|
|
rescue *NETWORK_ERRORS => e
|
|
|
|
raise ConnectionError, e
|
2018-07-13 18:39:24 -04:00
|
|
|
end
|
|
|
|
|
2018-06-25 16:06:10 -04:00
|
|
|
private
|
|
|
|
|
2018-07-05 17:09:01 -04:00
|
|
|
def check_errors!(response)
|
2019-02-16 18:30:02 -05:00
|
|
|
return if ActionDispatch::Response::NO_CONTENT_CODES.include?(response.code)
|
2018-07-27 17:29:05 -04:00
|
|
|
raise ConnectionError, "Response is not valid JSON" unless response.parsed_response.is_a?(Hash)
|
2018-07-13 02:17:05 -04:00
|
|
|
|
2018-07-27 17:29:05 -04:00
|
|
|
return if response.code >= 200 && response.code < 300
|
2018-07-13 02:17:05 -04:00
|
|
|
|
2018-07-27 17:29:05 -04:00
|
|
|
details = sanitize(response.parsed_response.dig('errors', 0, 'message'))
|
2018-07-13 02:17:05 -04:00
|
|
|
message = "Error #{response.code}"
|
2018-07-31 15:58:26 -04:00
|
|
|
message += ": #{details}" if details
|
2018-07-27 17:29:05 -04:00
|
|
|
|
2018-07-13 02:17:05 -04:00
|
|
|
raise ConnectionError, message
|
2018-07-27 17:29:05 -04:00
|
|
|
rescue JSON::ParserError
|
|
|
|
raise ConnectionError, "Unable to parse the server response as JSON"
|
2018-07-05 17:09:01 -04:00
|
|
|
end
|
|
|
|
|
2018-07-03 19:37:17 -04:00
|
|
|
def auth
|
|
|
|
@auth ||= { username: username, password: token }
|
|
|
|
end
|
|
|
|
|
2018-07-27 15:58:03 -04:00
|
|
|
def accept_headers
|
|
|
|
@accept_headers ||= { 'Accept' => 'application/json' }
|
|
|
|
end
|
|
|
|
|
2018-07-03 19:37:17 -04:00
|
|
|
def post_headers
|
2018-07-27 15:58:03 -04:00
|
|
|
@post_headers ||= accept_headers.merge({ 'Content-Type' => 'application/json' })
|
2018-07-03 19:37:17 -04:00
|
|
|
end
|
|
|
|
|
2018-06-25 16:06:10 -04:00
|
|
|
def build_url(path)
|
|
|
|
return path if path.starts_with?(root_url)
|
|
|
|
|
2018-11-09 18:31:26 -05:00
|
|
|
Gitlab::Utils.append_path(root_url, path)
|
2018-06-25 16:06:10 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def root_url
|
2018-11-09 18:31:26 -05:00
|
|
|
Gitlab::Utils.append_path(base_uri, "rest/api/#{api_version}")
|
2018-06-25 16:06:10 -04:00
|
|
|
end
|
2018-07-13 18:39:24 -04:00
|
|
|
|
|
|
|
def delete_url(resource, path)
|
|
|
|
if resource == :branches
|
2018-11-09 18:31:26 -05:00
|
|
|
Gitlab::Utils.append_path(base_uri, "rest/branch-utils/#{api_version}#{path}")
|
2018-07-13 18:39:24 -04:00
|
|
|
else
|
|
|
|
build_url(path)
|
|
|
|
end
|
|
|
|
end
|
2018-06-25 16:06:10 -04:00
|
|
|
end
|
|
|
|
end
|