支持定期轮询 JSON REST 资源。
身份验证通过 Authorization
标头传递,格式为 bearer <token>
。
预期响应包含一个 Etag
标头字段,该字段表示资源的当前状态,并在后续请求中传递回服务器。
这种机制可以有效轮询服务器以查找更改,并且可以作为速率限制的解决方法(其中未检测到状态变化的请求不计入速率限制)。
发送请求时,会传递一个 ProcessorGroup
,其中包含一个 Processor
对象列表。
当收到响应时,会依次将响应与每个 Processor
匹配,并根据 HTTP 状态代码进行匹配。如果处理器支持该代码,则它有机会解码响应。
如果处理器无法解码响应(抛出错误),则会继续匹配,除非处理器列表已耗尽。第一个成功匹配将结束此过程。如果所有处理器都已耗尽但未成功,则会调用 ProcessorGroup
的 unprocessed
方法;这可用于捕获所有错误处理。
此简单示例轮询端点 https://some.endpoint/v1/
以获取资源 some/rest/resource
。
当发生更改时,将发回一个 JSON 响应。如果 HTTP 状态代码是我们期望的代码,我们将把 JSON 解码为 Swift 对象,并使用它调用我们的一个 Processor 对象。
/// if the response is 200, the server will send us an item
struct ItemProcessor: Processor {
struct Item: Decodable {
let name: String
}
let codes = [200]
func process(_ item: Item, response: HTTPURLResponse, in session: Session) -> RepeatStatus {
print("Received item \(item.name)")
return .inherited
}
}
/// if the response is 400, the server will send us an error
struct ErrorProcessor: Processor {
struct Error: Decodable {
let error: String
}
let codes = [400]
func process(_ payload: Error, response: HTTPURLResponse, in session: Session) -> RepeatStatus {
print("Something went wrong: \(payload.error)")
return .inherited
}
}
// make a session for the service we're targetting, supplying the authorization token
let session = Session(base: URL(string: "https://some.endpoint/v1/")!, token: "<api-token>")
// schedule polling of some REST resource
session.poll(target: Resource("some/rest/request"), processors: [ItemProcessor(), ErrorProcessor()], repeatingEvery: 1.0)
// the endpoint will be queried repeatedly by the session
// when an expected response comes back, the response will be decoded and one of our processor objects will be called to process it
RunLoop.main.run()
swift-tools-version
要求设置为 Swift 5,因为 Foundation Networking API 在 5.3 之前的 Linux 上不太正确。
严格来说,该代码适用于 Apple 平台上的 Swift 5.2,但它需要一个相当现代的 SDK。
这是我构建的用于访问 Github API 的一些代码的概括,并被 Octoid 使用,它是一个更通用的 Github 库。
我分离出 JSONSession 功能,因为我设想其他服务器可能使用相同的机制。这可能是一个不正确的假设,或者这段代码可能需要进一步概括才能与其他服务器一起使用。如果是这样,请通过 issue 告知我。