{"id":15066930,"url":"https://github.com/4rays/http-request-builder","last_synced_at":"2025-04-10T16:40:33.967Z","repository":{"id":255745107,"uuid":"853077550","full_name":"4rays/http-request-builder","owner":"4rays","description":"Build URL requests using functional composition and result builders.","archived":false,"fork":false,"pushed_at":"2025-02-02T19:53:56.000Z","size":28,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-03-24T14:21:23.811Z","etag":null,"topics":["composition","foundation","functional","http","ios","middleware","networking","rest","resultbuilder","swift"],"latest_commit_sha":null,"homepage":"","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/4rays.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":"2024-09-06T00:22:19.000Z","updated_at":"2025-03-02T16:19:42.000Z","dependencies_parsed_at":"2025-02-17T14:33:51.872Z","dependency_job_id":"324a0346-4991-44d2-870a-a7535143333a","html_url":"https://github.com/4rays/http-request-builder","commit_stats":null,"previous_names":["4rays/http-request-builder"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4rays%2Fhttp-request-builder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4rays%2Fhttp-request-builder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4rays%2Fhttp-request-builder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4rays%2Fhttp-request-builder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/4rays","download_url":"https://codeload.github.com/4rays/http-request-builder/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248252725,"owners_count":21072702,"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":["composition","foundation","functional","http","ios","middleware","networking","rest","resultbuilder","swift"],"created_at":"2024-09-25T01:14:04.390Z","updated_at":"2025-04-10T16:40:33.945Z","avatar_url":"https://github.com/4rays.png","language":"Swift","readme":"# HTTPRequestBuilder\n\nA Swift package to help build HTTP requests in a composable and type-safe way.\n\n## Installation\n\nAdd the following to your `Package.swift` file:\n\n```swift\ndependencies: [\n  .package(url: \"\", from: \"0.9.0\")\n]\n```\n\n## Overview\n\nThis library provides a result builder and supporting types\nto define HTTP requests in Swift. It relies on function composition (`pipe`)\nto create reusable request middleware that can be used in turn to create\nplatform specific requests, such as `URLRequest` in Foundation.\n\nFunction composition shines in this task as REST APIs are often built\nusing the same middleware approach, resulting in most requests sharing\na lot of the same logic such as paths, authentication, headers, etc.\n\nAuthor note: I gave a talk about this topic here.\n\n## Usage\n\nDefine one request middleware per endpoint.\nThe library comes with a few commonly used middleware functions that can\nbe further composed to build your own middleware, such as `header(key:value:)` used below.\n\n```swift\nimport HTTPRequestBuilder\n\n// Use a variable if the request does not take any parameters\n@RequestBuilder\nvar getUsers: RequestMiddleware = {\n  \"/users\"\n  Method.post\n  header(key: \"Content-Type\", value: \"application/json\")\n  header(key: \"Accept\", value: \"application/json\")\n}\n\n// Use a function if the request takes parameters\n@RequestBuilder\nfunc getUser(id: Int) -\u003e RequestMiddleware {\n  \"/users/\\(id)\"\n  Method.get\n  header(key: \"Accept\", value: \"application/json\")\n}\n```\n\nNote that the order inside the builder only matters for middleware that are not idempotent, such as the built-in `pathAppending`.\n\nOnce you have an endpoint defined, you can use it to create a request for Foundation.\n\n```swift\nimport Foundation\n\nlet urlRequest = URLRequest(\n  getUsers(),\n  baseURL: URL(string: \"https://api.example.com\")!\n)\n\nfunc getUser(id: Int) -\u003e URLRequest {\n  URLRequest(\n    getUser(id: id),\n    baseURL: URL(string: \"https://api.example.com\")!\n  )\n}\n```\n\n## Paths\n\nThis library comes with a `Path` type that can be used to define paths in a type-safe way.\nPaths can be defined as string literals or arrays. There is even a custom operator that works on strings or other paths.\n\n```swift\nlet path1: Path = \"/users/12\"\nprint(path1.fragments) // [\"users\", \"12\"]\n\nlet users = \"users\"\n\nlet path2 = Path(users).appending(\"12\")\nprint(path2.fragments) // [\"users\", \"12\"]\n\nenum Action: String {\n  case edit\n  case view\n}\n\nlet path3 = Path(users).appending(\"12\").appending(Action.edit)\nprint(path3.fragments) // [\"users\", \"12\", \"edit\"]\n```\n\nMy composing paths this way, it's easy to reuse parts of the path across different endpoints.\n\n```swift\nlet version = \"v1\"\nlet api = \"api\"/version\n\nlet users = api/\"users\"\nlet createUser = users/Action.create\n\nlet games = api/\"games\"\nlet createGame = games/\"create\"\nlet featuredGames = games/\"featured\"\n```\n\nYou can also compose paths using the built-in `pathAppending` middleware.\n\n```swift\nimport HTTPRequestBuilder\n\n@RequestBuilder\nvar userEndpoints: RequestMiddleware = {\n  path(\"/users\")\n}\n\n@RequestBuilder\nfunc editUser(id: Int) -\u003e RequestMiddleware {\n  userEndpoints\n  pathAppending(\"/edit\")\n  pathAppending(id)\n  Method.put\n}\n```\n\n## Authentication Middleware\n\nThis library comes with a couple middleware functions to help with authentication.\n\n### Basic Authentication\n\n```swift\nimport HTTPRequestBuilder\n\n@RequestBuilder\nvar signIn: RequestMiddleware = {\n  \"/sing-in\"\n  Method.get\n  basicAuth(username: \"user\", password: \"password\")\n}\n```\n\n### Bearer Token Authentication\n\n```swift\nimport HTTPRequestBuilder\n\n@RequestBuilder\nvar signIn: RequestMiddleware = {\n  \"/sing-in\"\n  Method.get\n  bearerToken(\"some-token\")\n}\n```\n\n## Custom Middleware\n\nA middleware is a function that takes a request and returns a new request.\n\n```swift\n(Request) throws -\u003e (Request)\n```\n\nYou can define your own middleware functions to encapsulate common logic\nunique to your use case.\n\n```swift\nimport HTTPRequestBuilder\n\nfunc myHeaderMiddleware(\n  value: String\n) -\u003e RequestMiddleware {\n  header(key: \"X-Custom-Header\", value: value)\n}\n```\n\nYour custom middleware can then be used in the same way as the built-in middleware.\n\n```swift\nimport HTTPRequestBuilder\n\n@RequestBuilder\nvar myRequest: RequestMiddleware = {\n  \"/path\"\n  Method.get\n  myHeaderMiddleware(value: \"some-value\")\n}\n```\n\n## License\n\nThis library is released under the MIT license. See LICENSE for details.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F4rays%2Fhttp-request-builder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F4rays%2Fhttp-request-builder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F4rays%2Fhttp-request-builder/lists"}