{"id":21036422,"url":"https://github.com/nimbly/shuttle","last_synced_at":"2025-05-15T14:31:44.665Z","repository":{"id":57027281,"uuid":"170071009","full_name":"nimbly/Shuttle","owner":"nimbly","description":"Simple PSR-18 HTTP client library.","archived":false,"fork":false,"pushed_at":"2025-02-27T20:46:14.000Z","size":181,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-20T11:18:46.959Z","etag":null,"topics":["http-client","http-requests","http-response","psr-18"],"latest_commit_sha":null,"homepage":"","language":"PHP","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/nimbly.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":"2019-02-11T05:06:00.000Z","updated_at":"2025-02-27T20:43:57.000Z","dependencies_parsed_at":"2024-06-21T19:02:01.731Z","dependency_job_id":"8736ff64-e5db-46b4-85cf-5b5c9fe77356","html_url":"https://github.com/nimbly/Shuttle","commit_stats":{"total_commits":64,"total_committers":2,"mean_commits":32.0,"dds":0.015625,"last_synced_commit":"7aad232168b790ca11c843ab8ce4d3f320d84862"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nimbly%2FShuttle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nimbly%2FShuttle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nimbly%2FShuttle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nimbly%2FShuttle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nimbly","download_url":"https://codeload.github.com/nimbly/Shuttle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254358798,"owners_count":22057980,"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-client","http-requests","http-response","psr-18"],"created_at":"2024-11-19T13:19:54.743Z","updated_at":"2025-05-15T14:31:44.653Z","avatar_url":"https://github.com/nimbly.png","language":"PHP","readme":"# Shuttle\n[![Latest Stable Version](https://img.shields.io/packagist/v/nimbly/Shuttle.svg?style=flat-square)](https://packagist.org/packages/nimbly/Shuttle)\n[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/nimbly/shuttle/coverage.yml?style=flat-square)](https://github.com/nimbly/Shuttle/actions/workflows/coverage.yml)\n[![Codecov branch](https://img.shields.io/codecov/c/github/nimbly/shuttle/master?style=flat-square)](https://app.codecov.io/github/nimbly/Shuttle)\n[![License](https://img.shields.io/github/license/nimbly/Shuttle.svg?style=flat-square)](https://packagist.org/packages/nimbly/Shuttle)\n\n\nA simple PSR-18 HTTP client library.\n\n## Requirements\n\n* PHP 8.2+\n* ext-curl\n\n## Installation\n\n```bash\ncomposer require nimbly/shuttle\n```\n\n## Features\n* Responses create php://temp response body stream and swap to disk when necessary.\n* cURL (default) and Stream Context handlers supported.\n* Middleware support out of the box.\n* Easy body transformations when creating requests with JsonBody and FormBody helper classes.\n* Support for multipart form bodies.\n\n## Not features\n* Asynchronous calls.\n\n## A note on PSR-7 and PSR-17\n\nShuttle makes use of PSR-7 HTTP Message and will default to using `nimbly/capsule`. You can override this by providing your perferred choice in PSR-7 implementations by passing PSR-17 HTTP Factories instances into the constructor of `Shuttle`.\n\n```php\n$http_factory = new GuzzleHttp\\Psr7\\HttpFactory;\n\n$shuttle = new Shuttle(\n\trequestFactory: $http_factory,\n\tresponseFactory: $http_factory,\n\tstreamFactory: $http_factory,\n\turiFactory: $http_factory,\n);\n```\n\n## Making requests: The easy way\n\nThe quickest and easiest way to begin making requests in Shuttle is to use the HTTP method name:\n\n```php\nuse Nimbly\\Shuttle\\Shuttle;\n\n$shuttle = new Shuttle;\n\n$response = $shuttle-\u003eget(\"https://www.google.com\");\n$response = $shuttle-\u003epost(\"https://example.com/search\", \"Form data\"));\n```\n\nShuttle has built-in methods to support the major HTTP verbs: get, post, put, patch, delete, head, and options. However, you can make **any** HTTP verb request using the **request** method directly.\n\n```php\n$response = $shuttle-\u003erequest(\"connect\", \"https://api.example.com/v1/books\");\n```\n\n## Handling responses\n\nResponses in Shuttle implement PSR-7 ResponseInterface and as such are streamable resources.\n\n```php\n$response = $shuttle-\u003eget(\"https://api.example.com/v1/books\");\n\necho $response-\u003egetStatusCode(); // 200\necho $response-\u003egetReasonPhrase(); // OK\n\n$body = $response-\u003egetBody()-\u003egetContents(); // {\"title\": \"Do Androids Dream of Electric Sheep?\", \"author\": \"Philip K. Dick\"}\n```\n\n## Handling failed requests\n\nShuttle will throw a `RequestException` by default if the request failed. This includes things like host name not found, connection timeouts, etc.\n\nResponses with HTTP 4xx or 5xx status codes *will not* throw an exception and must be handled properly within your business logic.\n\n## Making requests: The PSR-7 way\n\nIf code reusability and portability is your thing, future proof your code by making requests the PSR-7 way. Remember, PSR-7 stipulates that Request and Response messages be immutable.\n\n```php\n// Build Request message with your favorite PSR-7 library.\n$request = new Request(\"get\", \"https://www.example.com\");\n\n// Send the Request.\n$shuttle = new Shuttle;\n$response = $shuttle-\u003esendRequest($request);\n```\n\nUsing the `sendRequest()` method *does not* apply any `base_url` or default `headers` passed into the Shuttle constructor. However, the request is still passed through the middleware chain.\n\n## Request bodies\nAn easy way to submit data with your request is to use the `Nimbly\\Shuttle\\Body\\*` helper classes. These classes will automatically transform the data, convert to a **BufferStream**, and set a default **Content-Type** header on the request.\n\nThe request bodies supported are:\n\n* `JsonBody` Converts an associative array or instance of `JsonSerializable` into JSON and sets the `Content-Type` header to `application/json`.\n* `FormBody` Converts an associative array into a query string, sets `Content-Type` header to `application/x-www-form-urlencoded`.\n\nTo submit a JSON payload with a request:\n\n```php\nuse Nimbly\\Shuttle\\Body\\JsonBody;\n\n$book = [\n    \"title\" =\u003e \"Breakfast Of Champions\",\n    \"author\" =\u003e \"Kurt Vonnegut\",\n];\n\n$shuttle-\u003epost(\"https://api.example.com/v1/books\", new JsonBody($book));\n```\n\n## Middleware\n\nShuttle supports dual (aka double) pass middleware by implementing `MiddlewareInterface`. The request and response instance are both available to the middleware and can be manipulated to your specific needs.\n\n```php\nclass AuthMiddleware implements MiddlewareInterface\n{\n\tpublic function __construct(\n\t\tprivate string $api_key)\n\t{\n\t}\n\n\tpublic function process(RequestInterface $request, callable $next): ResponseInterface\n\t{\n\t\t// Add the Authorization header with every outgoing request.\n\t\t$request = $request-\u003ewithAddedHeader(\"Authorization\", \"Bearer \" . $this-\u003eapi_key);\n\n\t\t// Pass request object to next middleware layer.\n\t\t$response = $next($request);\n\n\t\t// Return response back with custom header added.\n\t\treturn $response-\u003ewithAddedHeader(\"X-Custom-Header\", \"Foo\");\n\t}\n}\n```\n\nYou may add as many middleware layers as you need and pass them to the Shuttle constructor. The middleware are executed in the order given.\n\n```php\n$shuttle = new Shuttle(\n\tmiddleware: [\n\t\tnew AuthMiddleware(\\getenv(\"API_KEY\")),\n\t\tnew FooMiddleware,\n\t\tnew BazMiddleware,\n\t]\n);\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnimbly%2Fshuttle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnimbly%2Fshuttle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnimbly%2Fshuttle/lists"}