Swift中的Web API客户端 | kean.blog
自从我在 Swift 的上一篇 API 客户端文章发布以来,已经过去了四年多。在这段时间里,Swift 发生了许多变化,尤其是引入了 Async/Await 和 Actors,使得在 Swift 中设计自定义 Web API 客户端变得更加简单和有趣。本文将以 GitHub API 为例,探讨如何利用这些新特性设计一个高效的 API 客户端。
实现 API 客户端
实现一个 API 客户端的第一步是定义一个表示请求的类型。这个类型可以根据需求变得非常复杂,但以下是一个良好的起点:
struct Request {
let path: String
let method: String
let headers: [String: String]
let body: Data?
}
接下来,需要一个客户端来执行这些请求。这个客户端是基于 URLSession 的轻量封装,便于修改和扩展。以下是一个简单的实现:
class APIClient {
private let session: URLSession
private let baseURL: URL
init(baseURL: URL, session: URLSession = .shared) {
self.baseURL = baseURL
self.session = session
} func send(_ request: Request, responseType: T.Type) async throws -> T {
let urlRequest = try makeRequest(from: request)
let (data, _) = try await session.data(for: urlRequest)
return try JSONDecoder().decode(T.self, from: data)
} private func makeRequest(from request: Request) throws -> URLRequest {
var components = URLComponents(url: baseURL.appendingPathComponent(request.path), resolvingAgainstBaseURL: false)
components?.queryItems = request.queryItems
guard let url = components?.url else {
throw URLError(.badURL)
}
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = request.method
urlRequest.allHTTPHeaderFields = request.headers
urlRequest.httpBody = request.body
return urlRequest
}
}
这个基础的 APIClient 已经能够满足大多数需求,同时也为进一步扩展提供了灵活性。
扩展 API 客户端功能
虽然基础功能容易实现,但更高级的用例需要额外的处理。以下是一些常见的扩展场景:
用户授权
在需要用户授权的场景中,可以通过 async/await 实现令牌刷新逻辑。例如:
func client(_ client: APIClient, willSendRequest request: inout URLRequest) async throws {
if let token = await refreshTokenIfNeeded() {
request.setValue("Bearer (token)", forHTTPHeaderField: "Authorization")
}
}
相比传统的回调方式,async/await 的实现更加简洁且不易出错。
双向 TLS(mTLS)
在双向 TLS 中,客户端需要向服务器提供证书。URLSession 原生支持 mTLS,以下是一个简单的实现:
func configureSession() -> URLSession {
let configuration = URLSessionConfiguration.default
configuration.tlsMinimumSupportedProtocol = .tlsProtocol12
return URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
}
主要挑战在于如何安全地管理私钥,例如通过嵌入模糊化的 .p12 文件。
HTTP 缓存
HTTP 缓存是一个灵活的系统,允许服务器和客户端共同决定缓存策略。URLSession 和 URLCache 提供了开箱即用的支持:
let request = URLRequest(url: url, cachePolicy: .returnCacheDataElseLoad, timeoutInterval: 60)
通过调整 CachePolicy,可以灵活控制缓存行为。
定义 API
对于较小的应用,可以直接使用 APIClient 发起请求。但在更复杂的场景中,定义 API 是一个更好的选择。例如,可以为每个资源创建一个单独的类型,并在其上定义可用的 HTTP 方法:
struct UserAPI {
let client: APIClient
func getUserDetails(userID: String) async throws -> User {
let request = Request(path: "/users/(userID)", method: "GET", headers: [:], body: nil)
return try await client.send(request, responseType: User.self)
}
}
这种方式虽然稍显繁琐,但可以减少代码重复并提高可维护性。
现代工具的支持
现代工具如 Pulse 提供了强大的日志记录功能,可以无缝集成到 APIClient 中:

通过简单的设置,即可收集详尽的网络请求信息,帮助开发者快速定位问题。
总结
借助 Swift 的 Async/Await 和 Actors 特性,构建自定义 Web API 客户端变得更加高效和直观。无论是基础功能还是高级用例,这些新特性都提供了极大的灵活性和便利性。通过合理设计和扩展,开发者可以轻松应对各种复杂的 API 场景。
原文链接: https://kean.blog/post/new-api-client
最新文章
- Tesults博客:API自动化测试指南
- 介绍全新的Rust REST API客户端库
- DeepSeek R1 × 飞书多维表格赋能教育领域
- 深入解析什么是API安全
- 使用 C++ 和 Win32 API 创建 GUI 窗口应用程序:从零构建 Windows 桌面界面
- 一个平台对接所有API:企业级API集成解决方案
- 台湾可以用支付宝吗?:支付与收款指南
- 深入解读 API Gateway:设计原则、实践与最佳架构
- 什么是 LangSmith
- 为API网关构建ChatGPT自定义插件 – API7.ai
- 更快的API,更高效的开发者:API Gateway自定义授权器
- 如何使用 node.js 和 express 创建 rest api