[Add] com-qqsdk-control-Tools 1.2.1
[CocoaPods.git] / Specs / d / 7 / b / RestingKit / 0.0.6 / RestingKit.podspec.json
blobf46ced6b6db7547a6af493a66e27214ead037d3b
2   "name": "RestingKit",
3   "version": "0.0.6",
4   "summary": "Networking made easy.",
5   "description": "# RestingKit\n\n[![CI Status](https://img.shields.io/travis/moray95/RestingKit.svg?style=flat)](https://travis-ci.org/moray95/RestingKit)\n[![Version](https://img.shields.io/cocoapods/v/RestingKit.svg?style=flat)](https://cocoapods.org/pods/RestingKit)\n[![License](https://img.shields.io/cocoapods/l/RestingKit.svg?style=flat)](https://cocoapods.org/pods/RestingKit)\n[![Platform](https://img.shields.io/cocoapods/p/RestingKit.svg?style=flat)](https://cocoapods.org/pods/RestingKit)\n\n## Introduction\n\nRestingKit is a higher-level wrapper around [Alamofire](https://github.com/Alamofire/Alamofire) and [PromiseKit](https://github.com/mxcl/PromiseKit) written in Swift that allows developers to concentrate on the important stuff instead of writing boiler-plate code for their REST API.\n\n## Features\n\n- Configurable HTTP client (Alamofire is currently the only one provided, but you can write your own!)\n- Path variable expansion powered by [GRMustache.swift](https://github.com/groue/GRMustache.swift)\n- Interception (and modification) of all requests and responses\n\n## Requirements\n\n- iOS 10.0+\n\n- Swift 5.0+\n\n## Installation\n\nRestingKit is available through [CocoaPods](https://cocoapods.org). To install it, simply add the following line to your Podfile:\n\n```ruby\npod 'RestingKit'\n```\n\n## Example project\n\nAn example project is included within the repositry. To run it, first execute `pod install`, then open `RestingKit.xcworkspace`. If you want to test file uploads with the example app, go into the `image_server` directory and run `php -S 0.0.0.0:9000 -c .`, which will start a dummy server for your uploads. The uploads will be stored in the `uploads` directory.\n\n## Usage\n\n### Basic example\n\n1. Create a `RestingClient`\n\n```swift\nimport RestingKit\n\nlet restingClient = RestingClient(baseUrl: \"https://jsonplaceholder.typicode.com\")\n```\n\n`RestingClient` is the core class within RestingKit that does the heavy lifting by executing the requests. It is configured to use a single base URL, so if you need to access multiple APIs, you'll need to create multiple clients.\n\n2. Define your models and endpoints\n\n   ```swift\n   struct PostCreateModel: Codable {\n       let userId: Int\n       let title: String\n       let body: String\n\n       init(userId: Int, title: String, body: String) {\n           self.userId = userId\n           self.title = title\n           self.body = body\n       }\n   }\n\n   struct PostModel: Codable {\n       let id: Int\n       let userId: Int\n       let title: String\n       let body: String\n   }\n\n   let createPostEndpoint = Endpoint<PostCreateModel, PostModel>(.post,\n                                                                 \"/posts\",\n                                                                 encoding: .json)\n   ```\n\n   An `Endpoint` is defined by the models of the request and response, the path (relative to the `RestingClient`'s `baseUrl`), the HTTP method to use and the encoding. If the request doesn't expect any content or doesn't return anything, you can use the special `Nothing` class. Ideally, we would use `Void`, but it is not possible to make it `Encodable` or `Decodable`.\n\n3. Create the request and make the actual call\n\n   ```swift\n   let postCreateModel = PostCreateModel(userId: 1,\n                                         title: \"Hello world\",\n                                         body: \"Some awesome message\")\n   let request = RestingRequest(endpoint createPostEndpoint,\n                                body: postCreateModel)\n   restingClient.perform(request).done { response in\n        print(\"Headers: \\(response.headers)\")\n        let post = response.body\n        print(\"Created post with id: \\(post.id)\")\n   }.catch { error in\n        print(\"An error occurred: \\(error)\")\n   }\n   ```\n\n   The promise will fail when the server responds with an HTTP status >299, so you don't have to handle this case.\n\n   And that's it!\n\n### Handling responses with no content\n\nIf a request might provide a response that might be empty, you can create an `Endpoint` with an optional response type. That way, if the response is empty, `nil` will be returned.\n\n```swift\nlet createPostEndpoint = Endpoint<PostCreateModel, PostModel?>(.post,\n                                                               \"/posts\",\n                                                               encoding: .json)\nlet postCreateModel = PostCreateModel(userId: 1,\n                                      title: \"Hello world\",\n                                      body: \"Some awesome message\")\nlet request = RestingRequest(endpoint createPostEndpoint,\n                             body: postCreateModel)\nrestingClient.perform(request).done { response in\n    print(\"Headers: \\(response.headers)\")\n    if let post = response.body {\n        print(\"Created post with id: \\(post.id)\")\n    } else {\n        print(\"Empty body\")\n    }\n}.catch { error in\n    print(\"An error occurred: \\(error)\")\n}\n```\n\n**Note:** For this feature to work, the response needs to be truely empty (ie. a content-length of 0). An empty JSON object will produce a decoding error.\n\n### Path variables\n\nThe provided `RestingRequestConverter` allows templating in paths by using [Mustache.swift](https://github.com/groue/GRMustache.swift).\n\n```swift\nlet getPostEndpoint = Endpoint<Nothing, PostModel>(.get,\n                                                   \"/posts/{{post_id}}\",\n                                                   encoding: .query)\nlet request = RestingRequest(endpoint: getPostEndpoint,\n                             body: Nothing(),\n                             pathVariables: [\"post_id\": 1])\n\nrestingClient.perform(request).done { response in\n    print(\"Got post: \\(response.body)\")\n}.catch { error in\n    print(\"An error occurred: \\(error)\")\n}\n```\n\n### Multipart form data & file upload\n\nIt is possible to perform a multipart form data request with RestingKit. The only thing to make the request is to set the `Endpoint`'s encoding to `.multipartFormData`:\n\n```swift\nlet multipartEndpoint = Endpoint<MyModel, Nothing>(.post,\n                                                   \"/some_resource\",\n                                                   encoding: .multipartFormData)\n```\n\nNow, each request using this endpoint will be encoded as `multipart/form-data`.\nUploading files is also that easy. You can use the provided `MultipartFile` class within your models, and magically, the file will be uploaded.\n\n```swift\nclass ImageUploadModel: Encodable {\n    let file: MultipartFile\n    init(imageURL: URL) {\n        self.file = MultipartFile(url: imageURL)\n    }\n}\n\nlet request = RestingRequest(endpoint: multipartEndpoint,\n                             body: ImageUploadModel(url: imageUrl))\nrestingClient.upload(request).promise.done { _ in\n    print(\"Success!\")\n}.catch {\n    print(\"Error: \\($0)\")\n}\n```\n\n**Note:** You should use `upload` methods on the `RestingClient` instead of `perform` when dealing with files and large amounts of data. `perform` will load the whole request body into memory,\nwhile `upload` will store it into a temporary file and stream it without loading into memory.\n\nThe encoding is handled by the `MultipartFormDataEncoder`, which provides an interface and configuration options similar to `JSONEncoder`. You can customize the `MultipartFormDataEncoder`\nused by the `RestingRequestConverter`:\n\n```swift\nlet formDataEncoder = MultipartFormDataEncoder()\nformDataEncoder.keyEncodingStrategy = .convertToSnakeCase\nformDataEncoder.dateEncodingStrategy = .secondsSince1970\nformDataEncoder.dataEncodingStrategy = .raw\nlet configuration = RestingRequestConverter.Configuration(multipartFormDataEncoder: formDataEncoder)\nlet converter = RestingRequestConverter(configuration: configuration)\n```\n\n### Progress handlers\n\n`RestingClient`'s `upload` methods returns a `ProgressablePromise`, which acts like classic promisses but also\naccept a progress handlers.\n\n```swift\nrestingClient.upload(request).progress { progress in\n    print(\"Upload \\(progress.fractionCompleted * 100)% completed\")\n}.done { response in\n    print(\"Uploaded completed with response: \\(response)\")\n}.catch { error in\n    print(\"An error occurred\")\n}\n```\n\n### Interceptors\n\nInterceptors allow to intercept any request and response, and modify it before the request is sent or the response processed. Some basic usages of interceptors include:\n\n- Logging requests and responses\n- Injecting headers\n- Retrying failed requests\n\nTo use interceptors, you will need to implement the `RestingInterceptor` protocol and provide your interceptor to your `RestingClient`.\n\n```swift\nclass LogInterceptor: RestingInterceptor {\n    func intercept(request: HTTPRequest, execution: Execution)\n        -> ProgressablePromise<HTTPDataResponse> {\n        print(\"sending request \\(request)\")\n        return execution(request).get { response in\n            print(\"got response \\(response)\")\n        }\n    }\n}\n\nclass DeviceIdInjector: RestingInterceptor {\n    func intercept(request: HTTPRequest, execution: Execution) -> ProgressablePromise<HTTPDataResponse> {\n        var urlRequest = request.urlRequest\n        urlRequest.setValue(UIDevice.current.identifierForVendor?.uuidString,\n                           forHTTPHeaderField: \"device-id\")\n        let request = BasicHTTPRequest(urlRequest: urlRequest, fileUrl: request.fileUrl)\n        return execution(request)\n    }\n}\n\nlet restingClient = RestingClient(baseUrl: \"https://jsonplaceholder.typicode.com\",\n                                  decoder: decoder,\n                                  requestConverter: requestConverter,\n                                  interceptors: [DeviceIdInjector(), LogInterceptor()])\n```\n\nThe `RestingClient` will pass the request to the interceptors in the provided order, while the response is passed in the reverse order. Therefore, it is important to place `LogInterceptor` at the end of the array (otherwise, it will not be able to log the `device-id` header added by `DeviceIdInjector`).\n\nRestingKit provides an interceptor for logging requests and responses: `RequestResponseLoggingInterceptor`.\n\n**Important**: It is required for each interceptor to call the `execution` parameter, as it is what will run the next interceptors and finally the request. Unless, of course, you do not want to run additional interceptors or send the request.\n\n### Using a custom HTTPClient\n\n`HTTPClient`s are the classes that performs the requests. They take an `HTTPRequest` and return a `(Progressable)Promise<HTTPDataResponse>` without doing anything. `AlamofireClient` is the provided implementation that uses Alamofire to perform the requests and the default client used by `RestingClient`. You can configure a `RestingClient` to use your own implementation:\n\n```swift\nclass MyHTTPClient: HTTPClient {\n    public func perform(urlRequest: URLRequest) -> Promise<HTTPDataResponse> {\n        // Handle classic request\n    }\n    func upload(request: HTTPRequest) -> ProgressablePromise<HTTPDataResponse> {\n        // Handle uplaod request, with a progress handler\n    }\n}\n\nlet restingClient = RestingClient(baseUrl: \"https://jsonplaceholder.typicode.com\",\n                                  httpClient: MyHTTPClient())\n```\n\n### Always-on headers and path variables\n\nSometimes, you need to include the same headers or path variables in all requests. RestingKit has you covered! `RestingRequestConverter` can be configured add headers and include path variables in all requests.\n\nFor example, the `DeviceIdInjector` interceptor can be re-written the following way:\n\n```swift\nlet headerProvider = RestingHeaderProvider(providers: [ \"device-id\": { UIDevice.current.identifierForVendor?.uuidString } ])\n\n// Or\n\nheaderProvider.addHeader(key: \"device-id\") { UIDevice.current.identifierForVendor?.uuidString }\n\n// Or\n\nif let deviceId = UIDevice.current.identifierForVendor?.uuidString {\n    headerProvider.addHeader(key: \"device-id\", value: deviceId)\n}\n\nlet configuration = RestingRequestConverter.Configuration(headerProvider: headerProvider)\nlet requestConverter = RestingRequestConverter(configuration: configuration)\n```\n\nNow, `device-id` will be present in all requests.\n\nIn the same way, you can provide path variables:\n\n```swift\nlet pathVariableProvider = RestingPathVariableProvider(providers: [ \"userId\": { AuthManager.user?.id } ])\n\n// Or\n\npathVariableProvider.addVariable(key: \"user-id\") { AuthManager.user?.id }\n\n// Or\n\nif let userId = AuthManager.user?.id {\n    pathVariableProvider.addVariable(key: \"user-id\", value: userId)\n}\n\nlet configuration = RestingRequestConverter.Configuration(pathVariableProvider: pathVariableProvider)\nlet requestConverter = RestingRequestConverter(configuration: configuration)\n```\n\nYou will now be able to use a path like `/users/{{userId}}/info` without providing the `userId` to the `RestingRequest`.\n\nWhen using header and path variable providers, the values added to individual requests overrides the one provided by providers.\n\n## Work in progress\n\nAs RestingKit is still new and in development, there are some missing features that needs implementation:\n\n- File downloads\n- Any other feature you might request!\n\nAdditionally, there might be some api-breaking changes until the project reaches full maturity.\n\n## Contributing\n\nIf you need help with getting started or have a feature request, just open up an issue. Pull requests are also welcome for bug fixes and new features.\n\n## Author\n\nMoray Baruh\n\n## License\n\nRestingKit is available under the MIT license. See the LICENSE file for more info.",
6   "homepage": "https://github.com/moray95/RestingKit",
7   "license": {
8     "type": "MIT",
9     "file": "LICENSE"
10   },
11   "authors": {
12     "Moray Baruh": "contact@moraybaruh.com"
13   },
14   "source": {
15     "git": "https://github.com/moray95/RestingKit.git",
16     "tag": "0.0.6"
17   },
18   "platforms": {
19     "ios": "10.0"
20   },
21   "source_files": [
22     "RestingKit/*.swift",
23     "RestingKit/**/*.swift"
24   ],
25   "swift_versions": [
26     "5.0"
27   ],
28   "dependencies": {
29     "Alamofire": [
30       "~> 4.8"
31     ],
32     "GRMustache.swift": [
33       "~> 4.0"
34     ],
35     "PromiseKit": [
36       "~> 6.8"
37     ]
38   },
39   "swift_version": "5.0"