请注意 - 此软件包正处于大量开发中!👨🏻💻 🚀
SwiftyNetworking 是一个简单的软件包,它支持网络层,并提供类似于 SwiftUI 的 ViewBuilder 的请求构建模式。
注意: 该软件包正在进行大量开发。类型和方法的结构似乎已最终确定,但随着时间的推移,可能会因需要实现新功能而进行一些更改。0.8 版本非常接近最终版本。在此之前,我想添加模拟和测试,以完成我希望在此软件包中拥有的所有内容。
struct ExampleService: Service {
var baseURL: URL { URL(string: "https://www.example.com")! }
}
struct ExampleResponseModel: Codable {
let foo: String
let bar: Int
let buzz: Bool
}
struct ExampleErrorModel: Codable {
let status: Int
let message: String
}
Request
宏描述请求。@Request
struct ExampleRequest {
let bar: String
var body: some Request {
Get("foo", bar, "buzz", from: ExampleService())
.headers {
X_Api_Key(value: "sample_token")
}
.queryItems {
Key("hello", value: "world")
}
.body {
Key("array") {
Key("int", value: 42)
Key("double", value: 3.14)
Key("bool", value: true)
Key("string", value: "foo")
Key("array", value: ["foo", "bar", "buzz"])
}
.responseBody(ExampleResponseModel.self)
.responseError(ExampleErrorModel.self)
}
}
}
session
并发送请求。当然,您可以根据需要取消它。😉let session = Session()
let (result, error) = await session.send(request: ExampleRequest(bar: "buzz"))
if sometingIsWrong {
session.cancel(requests: .only(request.id))
}
就是这样!
我们喜欢优化我们的工作!这就是我为 Request
的基本实现准备模板的原因之一。另一个原因是发现了令牌菜单!你喜欢这种方法吗?给它一个星星吧!⭐️ 您可以通过运行位于
Templates
目录中的 install.sh
脚本轻松安装模板。
SwiftyNetworking 提供了易于使用且灵活的授权模型。假设大多数授权包括从一个请求中获取令牌并在其他请求中使用它,此软件包包含一个简单的系统,允许您捕获和使用此类值。
AuthorizationService
创建一个新的继承结构。有两个变量和一个方法需要存储敏感数据。最重要的部分是 func authorize<R: Request>(_ request: R) -> R
,您可以在其中注入来自存储的令牌。struct BackendAuthorization: AuthorizationProvider {
var store: AuthorizationStore = BackendAuthorizationStore()
var afterAuthorization: ((Codable, AuthorizationStore) -> Void)? = nil
func authorize<R: Request>(_ request: R) -> R {
if let token = store.get(key: .token) {
return request.headers {
Authorization(.bearer(token: token))
}
} else {
return request
}
}
}
KeychainAuthorizationStore
或从 AuthorizationStore
创建一个新的继承结构。struct BackendAuthorizationStore: AuthorizationStore {
let keychain = Keychain(service: "com.example.app")
static var tokenKey: String { "com.example.app.token" }
static var refreshTokenKey: String { "com.example.app.refresh-token" }
static var usernameKey: String { "com.example.app.username" }
static var passwordKey: String { "com.example.app.password" }
//I would like to make it better
func store(key: AuthorizationKey, value: String) {
try? keychain.set(value, key: key.representant(for: Self.self))
}
func get(key: AuthorizationKey) -> String? {
try? keychain.get(key.representant(for: Self.self))
}
}
@Request
struct ExampleLoginRequest {
var body: some Request {
Get("login", from: ExampleService())
//[...]
.responseBody(LoginResponse.self)
.afterAutorization { response, store in
store.value(.token(response.token))
}
}
authorize()
修饰符添加到每个需要授权的请求。@Request
struct ExampleAuthorizedRequest {
var body: some Request {
Get("foo", bar, "buzz", from: ExampleService())
//[...]
.authorize()
}
}
}
就是这样!
在使用网络层时,我们经常执行重复性操作,例如添加适当的授权标头或希望保存已发送请求的效果。SwiftyNetworking 允许您在完成查询之前和收到响应之后执行操作。
struct ExampleService: Service {
//[...]
func beforeEach<R>(_ request: R) -> R where R: Request {
request
.headers {
X_Api_Key(value: "secret_token")
}
}
func afterEach<B>(_ response: Response<B>) -> Response<B> where B: Codable {
statistics.store(response.statusCode)
}
}
SwiftyNetworking 提供默认的 OSLog 实体。您可以使用自己的 Logger 对象。
import OSLog
struct ExampleService: Service {
//[...]
let logger = Logger(subsystem: "com.example.app", category: "networking")
}
Mock
结果,这将是 Request
的替代输出我希望添加和支持更多内容:
// Dummy code
request
.mocked(where: { response in
switch response {
case successed:
//do something
case failed:
//do something
}
})
// Dummy code
@Request
struct ExampleRequest {
var body: some Request {
Queue {
Get("/example/1", from: ExampleService())
Get("/example/2", from: ExampleService())
Get("/example/3", from: ExampleService())
}
}
}
// Dummy code
@Request
struct ExampleRequest {
var body: some Request { }
}
#NetworkingPreview {
ExampleRequest()
}
// Dummy code
@Request
struct ExampleRequest {
typealias Response = ExampleResponseModel
typealias ResponseError = ExampleErrorModel
var body: some Request {
"curl -X POST https://www.example/login/ -d 'username=example&password=examle'"
}
}
更多修饰符,更多设置!