EasyRest 1.2.0

EasyRest 1.2.0

测试已测试
Lang语言 SwiftSwift
许可协议 MIT
发布最后发布2019年11月
SPM支持 SPM

Lucas Paim 维护。



EasyRest 1.2.0

  • 撰写的
  • Lucas

Build Status

动机

在审查了许多 iOS REST 客户端后,我们发现它们都非常冗长,这是不必要的。这个库是从简化客户端与服务器之间通信的需求中产生的。

要求

  • Swift 4+

对于 Swift 2.2、2.3 和 3,请查看分支。

文档

您可以在此 wiki 中阅读文档

用法

要将 EasyRest 添加到项目中,请在 Podfile 中添加以下内容

pod 'EasyRest'
pod 'EasyRest/PromiseKit'

模型示例

class Post : Codable {

    var id: String?
    var title: String?
    
}

路由示例

// Maps API calls and infos, like method and query params
enum JsonPlaceholderRoutable: Routable {
    // Each API interaction is a case
    case posts
    // Using query params
    case postsFilter(userId: Int)
    // Example with path
    case post(id: Int)
    case deletePost(id: Int)
    // Example with body
    case makePost(body: PostModel)
    // Example with path, body and header
    case editPost(id: Int, body: PostModel)
    case editTitle(id: Int, body: PostModel)
    
    // Now test every possibility in a fashion Swift syntax
    var rule: Rule {
        switch(self) {
        case .posts:
            return Rule(
                method: .get, // HTTP verb
                path: "/posts/", // Endpoint
                isAuthenticable: false, // Uses EasyRest Authenticated Service?
                parameters: [:]) // query/path/header params? Header Body? Multipart form data? Put here!
        case let .postsFilter(userId):
            return Rule(
                method: .get,
                path: "/posts/",
                isAuthenticable: false,
                parameters: [.query: ["userId": "\(userId)"]])
        case let .post(id):
            return Rule(
                method: .get,
                path: "/posts/{id}/",
                isAuthenticable: false,
                parameters: [.path: ["id": id]])
        case let .deletePost(id):
            return Rule(
                method: .delete,
                path: "/posts/{id}/",
                isAuthenticable: false,
                parameters: [.path: ["id": id]])
        case let .makePost(body):
            return Rule(
                method: .post,
                path: "/posts/",
                isAuthenticable: false,
                parameters: [.body: body])
        case let .editPost(id, body):
            return Rule(
                method: .put,
                path: "/posts/{id}",
                isAuthenticable: false,
                parameters: [
                    .path: ["id": id],
                    .body: body,
                    .header: ["Content-type": "application/json; charset=UTF-8"]])
        case let .editTitle(id, body):
            return Rule(
                method: .patch,
                path: "/posts/{id}",
                isAuthenticable: false,
                parameters: [
                    .path: ["id": id],
                    .body: body,
                    .header: ["Content-type": "application/json; charset=UTF-8"]])
        }
    }
}
enum TestRoute: Routable{

    case me(String)
    case post(String)

    var rule: Rule {
        switch(self) {
            case let .me(name):
                return Rule(method: .get, path: "/api/v1/users/me/", isAuthenticable: true, parameters: [.query : ["name": name]])
            case let .post(id):
                let parameters : [ParametersType: AnyObject] = [:]
                return Rule(method: .get, path: "/api/v1/posts/\(id)/",   isAuthenticable: true, parameters: parameters)
            }
    }

}

服务示例

class TestRouteService : OAuth2Service<TestRoute> {
    override var base: String { return BASE_URL }
    override var interceptors: [Interceptor] { return [DefaultHeadersInterceptor()] }
    
    convenience init() {
        self.init()
    }
    
    func me(name: String, onSuccess: (result: Response<UserTest>?) -> Void, onError: (ErrorType?) -> Void, always: () -> Void) {
        try! call(.me(name), type: UserTest.self, onSuccess: onSuccess, onError: defaultErrorHandler(onError), always: always)
    }
    
    func post(id: Int, onSuccess: (result: Response<Post>?) -> Void, onError: (ErrorType?) -> Void, always: () -> Void) {
        try! call(.post(id), type: Post.self, onSuccess: onSuccess, onError: defaultErrorHandler(onError), always: always)
    }
    
    func defaultErrorHandler(onError: (ErrorType?) -> Void) -> (ErrorType?) -> Void {
        return { error in
            /* Do whatever is default for all errors, like
                switch error.cause {
                    case .InternetConnection:
                        // backOff()
                    case .FailedJsonSerialization:
                        Crashlytics.sendMessage(error....)
                        Sentry.captureEvent(...)
                }
            */
            
            onError(error)
        }
    }
}

另外,我们也支持PromiseKit调用

class JsonPlaceholderService : Service<JsonPlaceholderRoutable> {
    override public var base: String { return "https://jsonplaceholder.typicode.com" }
}

然后

let service = JsonPlaceholderService()
try! service.call(.post(id: 1), type: PostModel.self).promise
    .done { result in
        print("RESPONSE ITEM ID: \(result!.body!.id!)")
    }.catch { error in
        print("Error : \(error.localizedDescription)")
    }.finally {
        print("This code will be called all the time")
    }

拦截器示例

class DefaultHeadersInterceptor : Interceptor {
    required init() {}

    func requestInterceptor<T: Codable>(_ api: API<T>) {
        api.headers["Content-Type"] = "application/json"
        api.headers["Accept"] = "application/json"
        api.headers["Device-Token"] = "8ec3bba7de23cda5e8a2726c081be79204faede67529e617b625c984d61cf5c1"
        api.headers["Device-Agent"] = "iOS_SANDBOX"
        api.headers["Accept-Language"] = "pt-br"
    }

    func responseInterceptor<T: Codable, U>(_ api: API<T>, response: DataResponse<U>) {

    }
}

待办事项

  • 移除基因组并使用Swift 4 Codable
  • 重试调用
  • 发送请求以连接到互联网
  • 为主功能创建单元测试
  • 为可验证服务创建单元测试
  • 为多部分数据上传创建单元测试
  • 取消请求
  • 创建一个维基库
  • 添加响应模型以发送额外信息,如HTTP状态代码
  • 文件上传
  • 改进请求语法
  • 错误处理程序
  • 添加对AppCode中着色的支持
  • 在内存中下载文件
  • 直接将文件下载到存储(内存优化)

第三方库和引用

许可证

EasyRest可在MIT许可证下使用。有关更多信息,请参阅LICENSE文件。