{"id":23413686,"url":"https://github.com/http-rpc/echo","last_synced_at":"2025-06-18T07:36:53.201Z","repository":{"id":56917922,"uuid":"138212802","full_name":"HTTP-RPC/Echo","owner":"HTTP-RPC","description":"Lightweight REST for Swift","archived":false,"fork":false,"pushed_at":"2025-02-18T18:31:59.000Z","size":5339,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-12T05:43:46.897Z","etag":null,"topics":["json","rest","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HTTP-RPC.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-06-21T19:20:58.000Z","updated_at":"2025-02-18T12:55:47.000Z","dependencies_parsed_at":"2024-06-20T05:07:42.487Z","dependency_job_id":null,"html_url":"https://github.com/HTTP-RPC/Echo","commit_stats":null,"previous_names":["gk-brown/kilo"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HTTP-RPC%2FEcho","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HTTP-RPC%2FEcho/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HTTP-RPC%2FEcho/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HTTP-RPC%2FEcho/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HTTP-RPC","download_url":"https://codeload.github.com/HTTP-RPC/Echo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248525156,"owners_count":21118616,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json","rest","swift"],"created_at":"2024-12-22T19:54:07.106Z","updated_at":"2025-04-12T05:44:02.669Z","avatar_url":"https://github.com/HTTP-RPC.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Releases](https://img.shields.io/github/release/HTTP-RPC/Echo.svg)](https://github.com/HTTP-RPC/Echo/releases)\n\n# Introduction\nEcho is a Swift package for consuming RESTful and REST-like web services. It provides a lightweight, API-centric wrapper around the more general `URLSesssion` class provided by the Foundation framework. The project's name comes from the nautical _E_ or _Echo_ flag:\n\n![](echo.png)\n\nFor example, the following code uses Echo's `WebServiceProxy` class to access a simple web service that returns the first _n_ values of the Fibonacci sequence:\n\n```swift\nlet webServiceProxy = WebServiceProxy(session: URLSession.shared, baseURL: baseURL)\n\ndo {\n    // GET test/fibonacci?count=8\n    let response: [Int] = try await webServiceProxy.invoke(.get, path: \"test/fibonacci\", arguments: [\n        \"count\": 8\n    ])\n    \n    print(response) // [0, 1, 1, 2, 3, 5, 8, 13]\n} catch {\n    print(error.localizedDescription)\n}\n```\n\niOS 16 or later is required.\n\n# WebServiceProxy\nThe `WebServiceProxy` class is used to issue API requests to the server. This class provides a single initializer that accepts the following arguments:\n\n* `session` - a `URLSession` instance\n* `baseURL` - the base URL of the service\n\nService operations are initiated via one of the following methods:\n\n```swift\npublic func invoke(_ method: Method, path: String, \n    arguments: [String: Any] = [:],\n    content: Data? = nil, \n    contentType: String? = nil) async throws { ... }\n\npublic func invoke\u003cB: Encodable\u003e(_ method: Method, path: String, \n    arguments: [String: Any] = [:], \n    body: B) async throws { ... }\n\npublic func invoke\u003cT: Decodable\u003e(_ method: Method, path: String,\n    arguments: [String: Any] = [:],\n    content: Data? = nil, \n    contentType: String? = nil) async throws -\u003e T { ... }\n\npublic func invoke\u003cB: Encodable, T: Decodable\u003e(_ method: Method, path: String,\n    arguments: [String: Any] = [:],\n    body: B) async throws -\u003e T { ... }\n\npublic func invoke\u003cT\u003e(_ method: Method, path: String,\n    arguments: [String: Any] = [:],\n    content: Data? = nil, \n    contentType: String? = nil,\n    responseHandler: @escaping ResponseHandler\u003cT\u003e) async throws -\u003e T { ... }\n```\n\nAll variants accept the following arguments:\n\n* `method` - the HTTP method to execute\n* `path` - the path to the requested resource, relative to the base URL\n* `arguments` - a dictionary containing the query arguments as name/value pairs\n\nThe first two versions execute a service method that does not return a value. The following two versions deserialize a service response of type `T` using `JSONDecoder`. The final version accepts a `ResponseHandler` callback to facilitate decoding of custom response content:\n\n```swift\npublic typealias ResponseHandler\u003cT\u003e = (_ content: Data, _ contentType: String?) throws -\u003e T\n```\n\nThree of the methods accept the following arguments for specifying custom request body content:\n\n* `content` - an optional `Data` instance representing the body of the request\n* `contentType` - an optional string value containing the MIME type of the content\n\nThe other two methods accept a `body` argument of type `B` that is serialized using `JSONEncoder`. JSON data is encoded and decoded using a date strategy of `millisecondsSince1970`.\n\n## Query Arguments\nAny value may be used as a query argument and will generally be encoded using its string representation. However, `Date` instances are first converted to a 64-bit integer value representing epoch time. Additionally, array instances represent multi-value parameters and behave similarly to `\u003cselect multiple\u003e` tags in HTML forms.\n\nThe `undefined` property of the `WebServiceProxy` class can be used to represent unspecified or unknown argument values.\n\n## Return Values\nA value representing the server response is returned upon successful completion of an operation. If an operation does not complete successfully, a `WebServiceError` will be thrown. The error's `statusCode` property can be used to determine the nature of the error. If the type of the error response is \"text/plain\", the response content will be provided in the error's localized description:\n\n```swift\nif let webServiceError = error as? WebServiceError {\n    print(webServiceError.statusCode)\n}\n\nprint(error.localizedDescription)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhttp-rpc%2Fecho","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhttp-rpc%2Fecho","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhttp-rpc%2Fecho/lists"}