A simple way to connect your swift code to your APIs.
Api.send(.get("https://jsonplaceholder.typicode.com/users")) { (result: Result<[User], Error>) in
switch result {
case let .success(users):
break
case let .failure(error):
break
}
}
let users: [User] = try await Api.send(.get("https://jsonplaceholder.typicode.com/users"))
Allows for simple middleware/intercepting of request and response. Which is great for custom authentication / request & response manipulation. Also since it just wraps Apple's URLSession API it is very easy to intergrate into existing codebases.
ProductionEndpoints.swift
Production Target
private let mobileEndpoints = StaticEndpointInfo(url: "https://...")
StagingEndpoints.swift
Staging Target
private let mobileEndpoints = StaticEndpointInfo(url: "https://staging...")
Api.swift
class MyApi: Api {
private var mobileServices: EndpointInfo = mobileEndpoints
init() {
let config = DefaultApiConfig(interceptors: [LogInterceptor(level: .verbose)])
super.init(urlSession: URLSession.shared, config: config)
}
}
extension MyApi: UserResource {
@discardableResult
func getAllUsers(completion: ApiCompletion<[User]>) -> HttpOperation? {
return send(.get(endpoint: mobileServices, path: "/users"),
completion: completion)
}
@discardableResult
func createUser(user: CreateUser, completion: ApiCompletion<User>) -> HttpOperation? {
return send(try! .post(endpoint: mobileServices, path: "/users", body: user),
completion: completion)
}
}
This saves you from having to repeat your base url and default headers that need to be on all requests like API keys.
private let mobileEndpoints = StaticEndpointInfo(url: "https://...", headers: ["API-Key": "..."])
ChaosInterceptor
used to cause chaos. THIS SHOULD ONLY BE USED WHENDEBUG
IS ENABLED AKA#if DEBUG
LogInterceptor
used to add logging to all request and response.OAuthInterceptor
used to add OAuth authentication to an API using anOAuthProvider
.
Creating a custom interceptor allows you modify every request or response, or a specific request and response.
Example of a inceptor that looks for bad status code and decodes a generic error response body.
struct MyApiError {
var code: Int
var message: String
}
class ErrorInterceptor: ApiInterceptor {
func api(_ api: Api,
didReceive result: Result<HttpDataResponse, Error>,
withId identifier: UUID,
for request: URLRequest,
completion: HttpDataCompletion) -> Bool
{
if let .success(response) = result {
if !response.successful {
let apiError = api.config.decoder.decode(MyApiError.self, response.data)
completion(.failure(ApiError.badStatusCode(error: apiError, response: response)))
return true
}
}
return false
}
}
let api = Api(config: DefaultApiConfig(interceptors: [ErrorInterceptor()]))
api.send(.get("https://....")) { (result: Result<[User], Error>) in
switch (result) {
case let .failure(error):
if let Api
}
}