Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save AlexanderBollbach/696f7a88af4b9c568b92c5fa979e022c to your computer and use it in GitHub Desktop.
Save AlexanderBollbach/696f7a88af4b9c568b92c5fa979e022c to your computer and use it in GitHub Desktop.
protocol APIType {
var currentEnvironment: API.RemoteEnv { get }
func update(environment: API.RemoteEnv)
@discardableResult func perform<T>(_ request: T, complete: @escaping (APIResult<T>) -> Void) -> Cancellable
}
class API: APIType {
struct Configuration {
typealias AuthenticationHeaders = (() -> [String: String])
let environment: API.RemoteEnv
let commonHeaders: [String: String]
let authenticationHeaders: AuthenticationHeaders
init(environment: RemoteEnv, commonHeaders: [String: String], authenticationHeaders: @escaping AuthenticationHeaders) {
self.environment = environment
self.commonHeaders = commonHeaders
self.authenticationHeaders = authenticationHeaders
}
}
private let http: HTTP
private var configuration: Configuration
var currentEnvironment: API.RemoteEnv {
return configuration.environment
}
init(
http: HTTP,
configuration: Configuration = Configuration(environment: RemoteEnv.dev, commonHeaders: [:], authenticationHeaders: { [:] })
) {
self.http = http
self.configuration = configuration
}
@discardableResult
func perform<T>(_ request: T, complete: @escaping (APIResult<T>) -> Void) -> Cancellable {
let httpRequest = request
.httpRequest(baseUrl: request.host(from: configuration.environment))
.adding(headers: configuration.commonHeaders)
.signed(with: configuration, required: request.authenticationRequired)
env.logger.log(type: .api, message: "sending request", log: request)
return http.perform(httpRequest) { result in
env.logger.log(type: .http, message: "RESULT", log: result)
switch result {
case .success(let response):
do {
complete(APIResult<T>.success(try request.handle(response: response)))
} catch let error {
complete(.failure(error))
}
case .failure(let error):
switch error {
case .connectivity:
complete(APIResult.failure(APIError.connectivity))
case .serverUnreachable:
complete(APIResult.failure(APIError.serverUnreachable))
default:
complete(APIResult.failure(APIError.http(message: error.description)))
}
}
}
}
func update(environment: API.RemoteEnv) {
configuration = Configuration(
environment: environment,
commonHeaders: configuration.commonHeaders,
authenticationHeaders: configuration.authenticationHeaders
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment