HTTPKit

swift 5.1 iOS macOS tvOS watchOS Build Status codecov

一个 Swift 包,包含用于通过 HTTP 协议与 API 交互的构造。

动机

URLSession 很棒,但它有一些小的缺点。特别是,在使用基于 HTTP 的 RESTful API 时。例如,URLRequest 有一个 httpMethod 属性,类型为 String。我发现自己创建了 HTTPMethod 枚举很多次,所以我决定围绕 http 约定进行这些抽象,并将它们放在一个框架中。

安装

Swift 包管理器

您可以使用 Swift 包管理器 安装 HTTPKit,方法是将正确的描述添加到您的 Package.swift 文件中

// swift-tools-version:5.1
import PackageDescription

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

然后,在您准备就绪时运行 swift build

手动

使用 git clone git@github.com:Chandlerdea/HTTPKit.git 克隆 repo,并将 Sources/HTTPKit 目录拖到您的项目中

HTTP.Method

HTTP.Method 类型是一个枚举,您可以直接与 URLRequest 一起使用,如下所示

request.method = .get

HTTP.Header

HTTP.Header 类型是一个枚举,为您提供类型安全的 HTTP 标头,如下所示

request.add(.contentType(.json))

如果您需要支持其他标头,请提出 issue 或贡献并添加它们!

HTTP.ResponseStatus

HTTP.ResponseStatus 类型也是一个枚举,它为您提供状态代码的强类型,因此您无需担心记住代码的含义。您可以直接从 URLResponse 获取 HTTP.ResponseStatus,如下所示

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

还有 HTTP.MethodHTTP.Response 的映射,因此您无需担心确保响应对于请求中使用的方法是正确的,如下所示

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

HTTPNetworkController

HTTPNetworkController 是一个协议,它发送一个 URLRequest,并将返回的 json 解码为提供的泛型类型。这个协议的好处在于它包含将响应代码映射到请求方法、验证响应和解码 json 的逻辑。使用此协议时,您甚至无需担心 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 是一个协议,它包含泛型类型的基本 CRUD 方法,并继承自 HTTPNetworkController。 这设置了 URLRequestHTTP.Method,并创建和发送 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 是一个类,它使用 构建器模式 来构建您的 URLRequest。在示例项目中使用了此类的示例。 理想情况下,您应该创建一个子类,并像这样使用它

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()

贡献

如果您想贡献,请 fork 并提交 PR! 或者打开 Issues! 我希望得到社区的投入,使这个项目成为最好的项目。