一个 Swift 包,包含用于通过 HTTP 协议与 API 交互的构造。
URLSession
很棒,但它有一些小的缺点。特别是,在使用基于 HTTP 的 RESTful API 时。例如,URLRequest
有一个 httpMethod
属性,类型为 String
。我发现自己创建了 HTTPMethod
枚举很多次,所以我决定围绕 http 约定进行这些抽象,并将它们放在一个框架中。
您可以使用 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
类型是一个枚举,您可以直接与 URLRequest
一起使用,如下所示
request.method = .get
HTTP.Header
类型是一个枚举,为您提供类型安全的 HTTP 标头,如下所示
request.add(.contentType(.json))
如果您需要支持其他标头,请提出 issue 或贡献并添加它们!
HTTP.ResponseStatus
类型也是一个枚举,它为您提供状态代码的强类型,因此您无需担心记住代码的含义。您可以直接从 URLResponse
获取 HTTP.ResponseStatus
,如下所示
if case .created = response?.status {
...
}
还有 HTTP.Method
到 HTTP.Response
的映射,因此您无需担心确保响应对于请求中使用的方法是正确的,如下所示
if response.hasValidResponseStatus(for: response.originalRequest) { ...
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
是一个协议,它包含泛型类型的基本 CRUD 方法,并继承自 HTTPNetworkController
。 这设置了 URLRequest
的 HTTP.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
是一个类,它使用 构建器模式 来构建您的 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! 我希望得到社区的投入,使这个项目成为最好的项目。