Skip to content

Instantly share code, notes, and snippets.

@garvankeeley
Created February 27, 2024 20:12
Show Gist options
  • Save garvankeeley/e19ab91155b56e656c725174e7162b1a to your computer and use it in GitHub Desktop.
Save garvankeeley/e19ab91155b56e656c725174e7162b1a to your computer and use it in GitHub Desktop.
import Foundation
import Network
import Combine
struct AuthParams: Encodable {
let staticParam1 = "fixedparam"
let staticParam2 = "anotherfixedparam"
let username: String
let password: String
}
protocol APIResponse {}
struct AuthResponse: Decodable, APIResponse {
let result: String
}
enum APIRequest {
case auth(String, String)
var httpMethod: String {
switch self {
case .auth: return "POST"
}
}
var endpoint: String {
switch self {
case .auth: return "/the/auth/endpoint"
}
}
var contentType: String {
switch self {
case .auth:
return "application/x-www-form-urlencoded"
}
}
var params: Encodable {
switch self {
case .auth(let username, let password):
return AuthParams(username: username, password: password)
}
}
func decode(jsonData: Data) throws -> APIResponse {
switch self {
case .auth:
return try JSONDecoder().decode(AuthResponse.self, from: jsonData)
}
}
func setHttpHeaders(for request: inout URLRequest) {
if self.httpMethod == "POST" {
request.setValue(contentType, forHTTPHeaderField: "Content-Type")
}
}
}
class HTTPRequestService {
private let baseURL = "https://example.com"
func request(_ apiRequest: APIRequest,
retryCount: Int,
completion: @escaping (Result<APIResponse, Error>) -> ()) {
guard let url = URL(string: baseURL + apiRequest.endpoint) else { return } // todo handle err
let urlRequest = {
var request = URLRequest(url: url)
request.httpMethod = apiRequest.httpMethod
do {
let jsonBody = try JSONEncoder().encode(apiRequest.params)
request.httpBody = jsonBody
} catch {
completion(.failure(error))
}
apiRequest.setHttpHeaders(for: &request)
return request
}()
Task {
let (data, response) = try await URLSession.shared.data(for: urlRequest)
guard let response = response as? HTTPURLResponse,
(200..<300).contains(response.statusCode) else {
completion(.failure(URLError(.badServerResponse)))
return
}
do {
let response = try apiRequest.decode(jsonData: data)
completion(.success(response))
} catch {
completion(.failure(error))
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment