条例 4.1.2

条例 4.1.2

Andrew J. Wagner 维护。



条例 4.1.2

  • 作者:
  • Andrew J. Wagner

Decree - Declarative HTTP Requests

Swift platforms Swift Package Manager compatible CocoaPods Compatible MIT Build Status

Twitter @drewag Blog drewag.me

在 iOS、macOS 和 Linux 上以清晰和类型安全的方式通过声明网络服务和端点进行 HTTP 请求

当谈到使用 Swift 进行 URL 请求时,您有两个主要选项:使用 Foundation 中的 URLSession API 或使用一些重量级框架。

此框架旨在轻量级,同时保持可定制性,以声明性方式集中于声明 API 接口。一旦声明,向各种端点发出请求就非常直接且类型安全。它适用于 iOS、macOS 和 Linux。

Andrew 通过实施许多不同的用于 Swift 的应用程序和后端服务发展了这种策略。他使用这种范例来传达自己的前后端之间的信息(两者都使用 Swift 实现)以及 Spotify、FreshDesk、Stripe 等服务。

我们提供了包含对流行服务声明的单独仓库 DecreeServices

目录

功能

四种端点类型

这些 协议 声明端点是否具有输入和/或输出。

  • EmptyEndpoint(无输入或输出)
  • InEndpoint(仅输入)
  • OutEndpoint(仅输出)
  • InOutEndpoint(输入和输出)

五种输入格式

这些 格式 用来使用 Swift 的 Encodable 协议对端点的输入进行编码。

  • JSON
  • URL 查询
  • 表单 URL 编码
  • 表单数据编码
  • XML

两种输出格式

这些格式用于使用Swift的Decodable协议初始化端点的输出。

  • JSON
  • XML

三种授权方式

允许设置用于一个Web服务中所有端点的授权。每个端点可以指定一个授权需求

可配置

您可以可选地进行请求和响应处理的高级配置

  • 自定义URLRequest(例如,自定义头)
  • 自定义JSON编码器和解码器
  • 自定义响应验证
  • 自定义错误响应格式
  • 自定义标准响应格式

几乎100%代码覆盖率

我们的大部分代码都经过单元测试,以确保可靠性。

请求和响应记录

详细错误报告

Decree抛出并返回的错误旨在便于用户友好,同时提供详细诊断信息。

模拟

允许模拟端点响应以方便自动化测试。

第三方服务

我们创建了一个单独的框架,用于定义多个第三方服务的服务和端点。在DecreeServices中查看。

示例

以下是该框架使用的几个示例。

简单GET

这里我们定义了一个名为CheckStatus的端点,这是一个默认的GET请求,没有输入或输出,存在于路径“/status”。向下滚动查看ExampleService的定义。

struct CheckStatus: EmptyEndpoint {
    typealias Service = ExampleService

    let path = "status"
}

然后我们可以使用这个定义来发起异步请求。

CheckStatus().makeRequest() { result in
    switch result {
    case .success:
        print("Success :)")
    case .failure(let error):
        print("Error :( \(error)")
    }
}

我们还可以创建同步请求,如果发生错误,则直接抛出错误。

try CheckStatus().makeSynchronousRequest()

输入和输出

我们还可以定义具有输入和/或输出的端点。在此,我们定义了一个POST到“/login”的登录端点,其中用户名和密码参数以JSON编码。如果成功,该端点应返回一个令牌。

struct Login: InOutEndpoint {
    typealias Service = ExampleService
    static let method = Method.post

    let path = "login"

    struct Input: Encodable {
        let username: String
        let password: String
    }

    struct Output: Decodable {
        let token: String
    }
}

然后我们可以发起异步请求。

Login().makeRequest(with: .init(username: "username", password: "secret")) { result in
    switch result {
    case .success(let output):
        print("Token: \(output.token)")
    case .failure(let error):
        print("Error :( \(error)")
    }
}

或者我们可以创建同步请求,如果成功则返回输出,如果失败则抛出错误。

let token = try Login().makeSynchronousRequest(with: .init(username: "username", password: "secret")).token

服务定义

使上述示例正常工作的额外代码仅需要定义ExampleService。

struct ExampleService: WebService {
    // There is no service wide standard response format
    typealias BasicResponse = NoBasicResponse

    // Errors will be in the format {"message": "<reason>"}
    struct ErrorResponse: AnyErrorResponse {
        let message: String
    }

    // Requests should use this service instance by default
    static var shared = ExampleService()

    // All requests will be sent to their endpoint at "https://example.com"
    let baseURL = URL(string: "https://example.com")!
}

在此,我们定义了一个名为ExampleService的WebService,并具有几个属性。

这就足够了。然后,您可以定义任意数量的端点,并以清晰和类型安全的方式使用它们。

现实世界示例

要查看现实世界示例,请查看我们在DecreeServices中声明服务的方式。

期望功能

我们希望实施的功能已作为带有增强标签的问题添加。如果您有任何功能请求,请尽管创建一个新问题。

贡献

强烈鼓励您报告任何问题或为新功能创建pull请求。