HTTP Tools for Inspection, Enhancement, and Speed
A small library for easy network requests.
Small project that uses this library: MVArchitectureDemo
- Asynchronous Networking: Utilize modern Swift concurrency features for async network calls.
- Request and Response Interceptors: Customize requests and responses with multiple interceptors.
- Generic Decoding: Automatically decode JSON responses into Swift types.
- HTTP Method Enum: Easily specify HTTP methods with a convenient enum.
- URL Operator Overloading: Simplify URL construction with custom operators.
- Extensive Error Handling: Handle common and custom networking errors with built-in error types.
- Flexible Request Initialization: Support for URL, query parameters, body data, and headers in requests.
Notes:
- The code coverage is as close to 100% as possible (90%+)
- The unit tests were mostly created by ChatGPT :)
In this example, we will perform a GET request to fetch a list of users and decode the JSON response into a Swift object. We also demonstrate the use of an HTTP interceptor to log the request and response details.
First, define a model to represent the JSON response:
struct User: Decodable { let id: Int let name: String let username: String }Set up an HTTP client and add a request logger interceptor:
// import the library import HTTIES // Set up the HTTP client with a logging interceptor (code for the interceptor below) let session = URLSession.shared let client = HTTPClientImpl(httpDataRequestHandler: session, interceptors: [RequestLoggerHTTPInterceptor()])Utilize custom operators to build the URL for the request:
// Use the custom "/" operator to build the URL let baseURL = URL(string: "https://example.com/api")! let endpointURL = baseURL / "api" / "v1" / "users" /? ["sortBy": "name", "ascending": nil] // endpointURL is "https://example.com/api/api/v1/users?ascending&sortBy=name"// Perform a GET request and decode the JSON response into an array of `User` let usersRequest = try HTTPURLRequest(url: endpointURL) let users: [User] = try await client.data(for: usersRequest, decoding: [User].self, decoder: JSONEncoder()) // Handle the fetched users print("Fetched users: \(users)")A simple response interceptor that logs the request and response details is included as follows:
import HTTIES final class RequestLoggerHTTPInterceptor: HTTPResponseInterceptor { func intercept(data: Data, response: HTTPURLResponse, error: Error?, for request: URLRequest) -> (Data, HTTPURLResponse, Error?) { // Consider using a logger class :) print(""" ---- - Request: \(request.url?.path(percentEncoded: false) ?? "nil") - Body parameters: \(request.httpBody.map { String(decoding: $0, as: UTF8.self) } ?? "nil") - Response: \(response.statusCode) - Body content: \(String(decoding: data, as: UTF8.self)) ---- """) return (data, response, error) } }A simple request interceptor that modifies the Authorization http header to include an authentication token:
import HTTIES final class AuthTokenInterceptor: HTTPInoutRequestInterceptor { var token: String init(token: String) { self.token = token } func intercept(request: inout URLRequest) { request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization") } }