122 lines
3.3 KiB
Ruby
122 lines
3.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module BitbucketServer
|
|
class Connection
|
|
include ActionView::Helpers::SanitizeHelper
|
|
|
|
DEFAULT_API_VERSION = '1.0'
|
|
SEPARATOR = '/'
|
|
|
|
attr_reader :api_version, :base_uri, :username, :token
|
|
|
|
ConnectionError = Class.new(StandardError)
|
|
|
|
def initialize(options = {})
|
|
@api_version = options.fetch(:api_version, DEFAULT_API_VERSION)
|
|
@base_uri = options[:base_uri]
|
|
@username = options[:user]
|
|
@token = options[:password]
|
|
end
|
|
|
|
def get(path, extra_query = {})
|
|
response = Gitlab::HTTP.get(build_url(path),
|
|
basic_auth: auth,
|
|
headers: accept_headers,
|
|
query: extra_query)
|
|
|
|
check_errors!(response)
|
|
|
|
response.parsed_response
|
|
end
|
|
|
|
def post(path, body)
|
|
response = Gitlab::HTTP.post(build_url(path),
|
|
basic_auth: auth,
|
|
headers: post_headers,
|
|
body: body)
|
|
|
|
check_errors!(response)
|
|
|
|
response.parsed_response
|
|
end
|
|
|
|
# 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,
|
|
basic_auth: auth,
|
|
headers: post_headers,
|
|
body: body)
|
|
|
|
check_errors!(response)
|
|
|
|
response.parsed_response
|
|
end
|
|
|
|
private
|
|
|
|
def check_errors!(response)
|
|
raise ConnectionError, "Response is not valid JSON" unless response.parsed_response.is_a?(Hash)
|
|
|
|
return if response.code >= 200 && response.code < 300
|
|
|
|
details = sanitize(response.parsed_response.dig('errors', 0, 'message'))
|
|
message = "Error #{response.code}"
|
|
message += ": #{details}" if details
|
|
|
|
raise ConnectionError, message
|
|
rescue JSON::ParserError
|
|
raise ConnectionError, "Unable to parse the server response as JSON"
|
|
end
|
|
|
|
def auth
|
|
@auth ||= { username: username, password: token }
|
|
end
|
|
|
|
def accept_headers
|
|
@accept_headers ||= { 'Accept' => 'application/json' }
|
|
end
|
|
|
|
def post_headers
|
|
@post_headers ||= accept_headers.merge({ 'Content-Type' => 'application/json' })
|
|
end
|
|
|
|
def build_url(path)
|
|
return path if path.starts_with?(root_url)
|
|
|
|
url_join_paths(root_url, path)
|
|
end
|
|
|
|
def root_url
|
|
url_join_paths(base_uri, "/rest/api/#{api_version}")
|
|
end
|
|
|
|
def delete_url(resource, path)
|
|
if resource == :branches
|
|
url_join_paths(base_uri, "/rest/branch-utils/#{api_version}#{path}")
|
|
else
|
|
build_url(path)
|
|
end
|
|
end
|
|
|
|
# URI.join is stupid in that slashes are important:
|
|
#
|
|
# # URI.join('http://example.com/subpath', 'hello')
|
|
# => http://example.com/hello
|
|
#
|
|
# We really want http://example.com/subpath/hello
|
|
#
|
|
def url_join_paths(*paths)
|
|
paths.map { |path| strip_slashes(path) }.join(SEPARATOR)
|
|
end
|
|
|
|
def strip_slashes(path)
|
|
path = path[1..-1] if path.starts_with?(SEPARATOR)
|
|
path.chomp(SEPARATOR)
|
|
end
|
|
end
|
|
end
|