Swiftpack.co - Package - Chandlerdea/HTTPKit

HTTPKit

swift 5.1 iOS macOS tvOS Build Status codecov

A Swift package containing constructs for interacting with APIs over the HTTP protocol.

Motivation

URLSession is great, but it has some small shortcomings. Specifically, when it comes to using RESTful APIs over HTTP. For example, URLRequest has a httpMethod property of type String. I have found myself making a HTTPMethod enum so many times, I decided to take these abstractions around http conventions, and put them in a framework.

Installation

Swift Package Manager

You can use the Swift Package Manager to install HTTPKit by adding the proper description to your Package.swift file:

// swift-tools-version:5.0
import PackageDescription

let package = Package(
    name: "YOUR_PROJECT_NAME",
    dependencies: [
        .package(url: "https://github.com/Chandlerdea/HTTPKit.git", from: "1.1"),
    ]
)

Then run swift build whenever you get prepared.

Manual

Clone the repo with git clone git@github.com:Chandlerdea/HTTPKit.git, and drag the Sources/HTTPKit directory into your project

HTTP.Method

The HTTP.Method type is an enum that you can use directly with URLRequest, like this:

request.method = .get

HTTP.Header

The HTTP.Header type is an enum giving you type safe HTTP headers, like this:

request.add(.contentType(.json))

If there are headers that you need supported, open a an issue, or contribute and add them!

HTTP.ResponseStatus

The HTTP.ResponseStatus type is also an enum that gives you strong typing of status codes, so you don't need to worry about remembering what the codes mean. You can get a HTTP.ResponseStatus directly from a URLResponse, like this:

if case .created = response?.status {
    ...
}

There is also mapping of HTTP.Method to HTTP.Response, so you don't need to worry about making sure the response is correct for the method used in the request, like this:

if response.hasValidResponseStatus(for: response.originalRequest) { ...

HTTPNetworkController

HTTPNetworkController is a protocol which sends a URLRequest, and decodes the returned json into the supplied generic type. The nice thing about this protocol is that it contains the logic for mapping the response code to the request method, validating the response, and decoding the json. When using this protocol, you don't even need to worry about HTTP.ResponseStatus.

final class UsersController: HTTPNetworkController {

    func getUser(for post: Post, completion: @escaping (Result<User, Error>) -> Void) {
        let request: URLRequest = UsersRequestBuilder().user(for: post).build()
        self.sendRequest(request, completion)
    }

}

HTTPModelController

HTTPModelController is a protocol that contains basic CRUD methods for generic types, that inherits from HTTPNetworkController. This sets the HTTP.Method of the URLRequest, and creates and sends the URLRequest.

final class PostsController: HTTPModelController {

    func uploadPost(_ post: Post, completion: @escaping (Result<Void, Error>) -> Void) {
        let requestBuilder: PostsRequestBuilder().create(post)
        self.postModel(
            with: requestBuilder,
            completion: { (result: Result<Post, Error>) in
                switch result {
                case .success:
                    ...
                case .failure:
                    ...
                }
            }
        )
    }

}

HTTP.RequestBuilder

HTTP.RequestBuilder is a class which uses the builder pattern to build your URLRequests. There are examples of this class being used in the example project. Ideally you would make a subclass, and use it like this:

final class PostRequestBuilder: HTTP.RequestBuilder {

    func posts(for user: User) -> PostsRequestBuilder  {
        let result: PostsRequestBuilder = self
        result.appendPathComponent("posts")
        result.appendQueryItem(name: "userId", value: String(describing: user.id))
        let authToken: String = ...
        result.add(.authorization(authToken))
        return result
    }

}

let request: URLRequest = PostRequestBuilder().posts(for: user).build()

Contributing

If you would like to contribute, fork and submit a PR! Or open Issues! I would love input from the community to make this project the best it can be.

Github

link
Stars: 2
Help us keep the lights on

Dependencies

Used By

Total: 0

Releases

1.2.0 - Sep 10, 2019

Added CI and code coverage reporting

v1.1 - Sep 6, 2019

Making project into a swift package

v1.0 - May 3, 2019

Initial Release