{"id":17068651,"url":"https://github.com/drewag/decree","last_synced_at":"2025-10-14T03:42:19.021Z","repository":{"id":56908341,"uuid":"197983782","full_name":"drewag/Decree","owner":"drewag","description":"Framework for making Declarative HTTP Requests","archived":false,"fork":false,"pushed_at":"2020-09-19T19:23:09.000Z","size":418,"stargazers_count":34,"open_issues_count":2,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-10T03:48:36.364Z","etag":null,"topics":["http","ios","linux","macos","swift"],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/drewag.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}},"created_at":"2019-07-20T21:43:43.000Z","updated_at":"2024-01-13T12:55:37.000Z","dependencies_parsed_at":"2022-08-21T01:50:55.575Z","dependency_job_id":null,"html_url":"https://github.com/drewag/Decree","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drewag%2FDecree","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drewag%2FDecree/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drewag%2FDecree/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drewag%2FDecree/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/drewag","download_url":"https://codeload.github.com/drewag/Decree/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248611666,"owners_count":21133149,"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":["http","ios","linux","macos","swift"],"created_at":"2024-10-14T11:14:27.192Z","updated_at":"2025-10-14T03:42:18.906Z","avatar_url":"https://github.com/drewag.png","language":"Swift","readme":"![Decree - Declarative HTTP Requests](https://github.com/drewag/Decree/raw/master/Assets/Header.jpg)\n\n[![Swift](https://img.shields.io/badge/Swift-5-lightgrey.svg?colorA=28a745\u0026colorB=4E4E4E)](https://swift.org)\n![platforms](https://img.shields.io/badge/Platforms-iOS%208%20%7C%20macOS%2010.10%20%7C%20Linux-lightgrey.svg?colorA=28a745\u0026colorB=4E4E4E)\n[![Swift Package Manager compatible](https://img.shields.io/badge/SPM-compatible-brightgreen.svg?style=flat\u0026colorA=28a745\u0026\u0026colorB=4E4E4E)](https://github.com/apple/swift-package-manager)\n[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/CryptoSwift.svg?style=flat\u0026label=CocoaPods\u0026colorA=28a745\u0026\u0026colorB=4E4E4E)](https://cocoapods.org/pods/CryptoSwift)\n[![MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](/LICENSE)\n[![Build Status](https://dev.azure.com/accounts-microsoft/Drewag/_apis/build/status/drewag.Decree?branchName=master)](https://dev.azure.com/accounts-microsoft/Drewag/_build/latest?definitionId=1\u0026branchName=master)\n\n[![Twitter @drewag](https://img.shields.io/badge/Twitter-@drewag-blue.svg?style=flat)](http://twitter.com/drewag)\n[![Blog drewag.me](https://img.shields.io/badge/Blog-drewag.me-blue.svg?style=flat)](http://drewag.me)\n\n*Make HTTP requests in a clear and type safe way by declaring web services and endpoints on **iOS**, **macOS**, and **Linux***\n\nWhen it comes to making URL requests with Swift, you largely have two options: use the URLSession APIs in Foundation or use some heavy handed framework.\n\nThis framework is designed to be light-weight while remaining customizable and focusing on declaring the interface to an API in a declarative manner. Once declared, making requests to the various endpoints is very straight-forward and type safe. It works on iOS, macOS, and Linux.\n\nAndrew developed this strategy through the implementation of many different apps and backend services written in Swift. He's used this paradigm for communicating between his own front and back-ends (both implemented in Swift) as well as to services such as Spotify, FreshDesk, Stripe, and more.\n\n**We offer a separate repository [DecreeServices](https://github.com/drewag/DecreeServices) with service declarations for popular services** \n\nTable of Contents\n--------------\n\n- [Features](#features)\n- [Getting Started](https://github.com/drewag/Decree/wiki)\n- [Examples](#examples)\n- [Hopeful Features](#hopeful-features)\n- [Contributing](#contributing)\n\nFeatures\n--------\n\n**Four types of Endpoints**\n\nThese [protocols](https://github.com/drewag/Decree/wiki/Declaring-Endpoints#endpoint-types) declare if an endpoint has input and/or output.\n\n- `EmptyEndpoint` (no input or output)\n- `InEndpoint` (only input)\n- `OutEndpoint` (only output)\n- `InOutEndpoint` (input and output)\n\n**Five Input formats**\n\nThese [formats](https://github.com/drewag/Decree/wiki/Declaring-Endpoints#input-format) are used to encode the endpoint's input using the Swift [Encodable](https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types) protocol.\n\n- JSON\n- URL Query\n- Form URL Encoded\n- Form Data Encoded\n- XML\n\n**Two Output formats**\n\nThese [formats](https://github.com/drewag/Decree/wiki/Declaring-Endpoints#output-format) are used to initialize the endpoint's output using the Swift [Decodable](https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types) protocol.\n\n- JSON\n- XML\n\n**Three types of Authorization**\n\nAllows setting [authorization](https://github.com/drewag/Decree/wiki/Declaring-Web-Services#authorization) to be used for all endpoints in a web service. Each endpoint can then specify an [authorization requirement](https://github.com/drewag/Decree/wiki/Declaring-Endpoints#authorization-requirement).\n\n- [Basic](https://en.wikipedia.org/wiki/Basic_access_authentication)\n- [Bearer](https://swagger.io/docs/specification/authentication/bearer-authentication)\n- Custom - Custom HTTP header key and value\n\n**Advanced Functionality**\n\n- Download result to a file for to save memory on large requests.\n- Optionally get progress updates through an onProgress handler\n\n**Configurable**\n\nYou can *optionally* perform [advanced configuration](https://github.com/drewag/Decree/wiki/Declaring-Web-Services#configuration) to the processing of a request and response.\n\n- Customize URLRequest (e.g. custom headers)\n- Customize JSON encoders and decoders\n- Custom response validation\n- Custom error response format\n- Custom standard response format\n\n**Virtually 100% Code Coverage**\n\nThe vast majority of our code is covered by unit tests to ensure reliability.\n\n**Request and Response Logging**\n- Option to [enable logging out of requests and response](https://github.com/drewag/Decree/wiki/Debugging-Helpers) for debugging\n- Option to specify filter to only log particular endpoints\n\n**Thorough Error Reporting**\n\nThe [errors thrown and returned by Decree](https://github.com/drewag/Decree/wiki/Debugging-Helpers#errors) are designed to be user friendly while also exposing detailed diagnostic information.\n\n**Mocking**\n\nAllows [mocking endpoint responses](https://github.com/drewag/Decree/wiki/Mocking) for easy automated testing.\n\n**Third-Party Services**\n\nWe created a separate framework that defines services and endpoints for several third-party services. Check it out at [DecreeServices](https://github.com/drewag/DecreeServices).\n\nExamples\n----------\nHere are a few examples of how this framework is used.\n\n### Simple Get\n\nHere we define a `CheckStatus` endpoint that is a GET (the default) with no input or output that exists at the path “/status”.\nScroll down to see the definition of ExampleService.\n\n```swift\nstruct CheckStatus: EmptyEndpoint {\n    typealias Service = ExampleService\n\n    let path = \"status\"\n}\n```\n\nWe can then use that definition to make asynchronous requests.\n\n```swift\nCheckStatus().makeRequest() { result in\n    switch result {\n    case .success:\n        print(\"Success :)\")\n    case .failure(let error):\n        print(\"Error :( \\(error)\")\n    }\n}\n```\n\nWe can also make synchronous requests that simply throw an error if an error occurs.\n\n```swift\ntry CheckStatus().makeSynchronousRequest()\n```\n\n### Input and Output\n\nWe can also define endpoints that have input and/or output. Here, we define a Login endpoint that is a\nPOST to “/login” with username and password parameters encoded as JSON. If successful, the endpoint is\nexpected to return a token.\n\n```swift\nstruct Login: InOutEndpoint {\n    typealias Service = ExampleService\n    static let method = Method.post\n\n    let path = \"login\"\n\n    struct Input: Encodable {\n        let username: String\n        let password: String\n    }\n\n    struct Output: Decodable {\n        let token: String\n    }\n}\n```\n\nThen we can make an asynchronous request.\n\n```swift\nLogin().makeRequest(with: .init(username: \"username\", password: \"secret\")) { result in\n    switch result {\n    case .success(let output):\n        print(\"Token: \\(output.token)\")\n    case .failure(let error):\n        print(\"Error :( \\(error)\")\n    }\n}\n```\n\nOr we can make a synchronous requests that returns the output if successful and throws otherwise.\n\n```swift\nlet token = try Login().makeSynchronousRequest(with: .init(username: \"username\", password: \"secret\")).token\n```\n\n### Download\n\nFor endpoints with larger output, we can download them directly to a file instead of holding the whole response in memory.\n\n```swift\nstruct GetDocument: OutEndpoint {\n    typealias Service = ExampleService\n    typealias Output = Data\n\n\tlet id: Int\n\n    var path: String {\n\t    return \"documents/\\(id)\"\n    }\n}\n\nGetDocument(id: 42).makeDownloadRequest() { result in\n    switch result {\n    case .success(let url):\n        // open or move the url\n    case .failure(let error):\n        print(\"Error :( \\(error)\")\n    }\n}\n```\n\nNote, you use a the `makeDownloadRequest` method on any endpoint with output (regardless of it's format), but it often makes most sense with raw data output.\n\n### The Service Definition\n\nThe only extra code necessary to make the above examples work, is to define the ExampleService:\n\n```swift\nstruct ExampleService: WebService {\n    // There is no service wide standard response format\n    typealias BasicResponse = NoBasicResponse\n\n    // Errors will be in the format {\"message\": \"\u003creason\u003e\"}\n    struct ErrorResponse: AnyErrorResponse {\n        let message: String\n    }\n\n    // Requests should use this service instance by default\n    static var shared = ExampleService()\n\n    // All requests will be sent to their endpoint at \"https://example.com\"\n    let baseURL = URL(string: \"https://example.com\")!\n}\n```\n\nHere we define a `WebService` called `ExampleService` with the a few properties.\n\nThat's all you need. You can then define as many endpoints as you like and use them in a clear and type safe way.\n\n### Real World Examples\n\nTo see real world examples, check out how we declared services in [DecreeServices](https://github.com/drewag/DecreeServices/tree/master/Sources/DecreeServices).\n\nHopeful Features\n------------\n\nFeatures we are hoping to implement are added as [issues with the enhancement tag](https://github.com/drewag/Decree/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement). If you have any feature requests, please don't hesitate to create a new issue.\n\nContributing\n---------\n\nIt is very much encouraged for you to report any issues and/or make pull requests for new functionality.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrewag%2Fdecree","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrewag%2Fdecree","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrewag%2Fdecree/lists"}