{"id":20903508,"url":"https://github.com/phly/http","last_synced_at":"2025-04-05T09:08:56.299Z","repository":{"id":20053724,"uuid":"23322235","full_name":"phly/http","owner":"phly","description":"PSR HTTP Message implementations and node-like http.Server implementation","archived":false,"fork":false,"pushed_at":"2016-03-07T18:56:23.000Z","size":1318,"stargazers_count":164,"open_issues_count":1,"forks_count":30,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-03-29T08:08:43.504Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phly.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-08-25T17:23:44.000Z","updated_at":"2024-12-13T09:29:14.000Z","dependencies_parsed_at":"2022-09-01T10:11:42.424Z","dependency_job_id":null,"html_url":"https://github.com/phly/http","commit_stats":null,"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phly%2Fhttp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phly%2Fhttp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phly%2Fhttp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phly%2Fhttp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phly","download_url":"https://codeload.github.com/phly/http/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247312081,"owners_count":20918344,"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":[],"created_at":"2024-11-18T13:13:49.850Z","updated_at":"2025-04-05T09:08:55.663Z","avatar_url":"https://github.com/phly.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"phly/http\n=========\n\n\u003e ## Abandoned! Or, rather, rebranded!\n\u003e\n\u003e phly/http has moved to the zendframework organization as\n\u003e [zend-diactoros](https://github.com/zendframework/zend-diactoros)\n\u003e (Diactoros, literally \"the messenger,\" an epithet for Hermes).\n\u003e\n\u003e Please use that package instead, and contribute issues and pull requests\n\u003e against it I have closed issues and pull requests against phly/http at this\n\u003e time.\n\n[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/phly/http/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/phly/http/?branch=master)\n[![Code Coverage](https://scrutinizer-ci.com/g/phly/http/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/phly/http/?branch=master)\n[![Scrutinizer Build Status](https://scrutinizer-ci.com/g/phly/http/badges/build.png?b=master)](https://scrutinizer-ci.com/g/phly/http/build-status/master)\n\n`phly/http` is a PHP package containing implementations of the [accepted PSR-7 HTTP message interfaces](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message.md), as well as a \"server\" implementation similar to [node's http.Server](http://nodejs.org/api/http.html).\n\nThis package exists:\n\n- to provide a proof-of-concept of the proposed PSR HTTP message interfaces with relation to server-side applications.\n- to provide a node-like paradigm for PHP front controllers.\n- to provide a common methodology for marshaling a request from the server environment.\n\nInstallation and Requirements\n-----------------------------\n\nInstall this library using composer:\n\n```console\n$ composer require phly/http\n```\n\n`phly/http` has the following dependencies (which are managed by Composer):\n\n- `psr/http-message`, which defines interfaces for HTTP messages, including requests and responses. `phly/http` provides implementations of each of these.\n\nUsage\n-----\n\nUsage will differ based on whether you are writing an HTTP client, or a server-side application.\n\nFor HTTP client purposes, you will create and populate a `Request` instance, and the client should return a `Response` instance.\n\nFor server-side applications, you will create a `ServerRequest` instance, and populate and return a `Response` instance.\n\n### HTTP Clients\n\nA client will _send_ a request, and _return_ a response. As a developer, you will _create_ and _populate_ the request, and then _introspect_ the response.  Both requests and responses are immutable; if you make changes -- e.g., by calling setter methods -- you must capture the return value, as it is a new instance.\n\n```php\n// Create a request\n$request = (new Phly\\Http\\Request())\n    -\u003ewithUri(new Phly\\Http\\Uri('http://example.com'))\n    -\u003ewithMethod('PATCH')\n    -\u003ewithAddedHeader('Authorization', 'Bearer ' . $token)\n    -\u003ewithAddedHeader('Content-Type', 'application/json');\n\n// OR:\n$request = new Phly\\Http\\Request(\n    'http://example.com',\n    'PATCH',\n    'php://memory',\n    [\n        'Authorization' =\u003e 'Bearer ' . $token,\n        'Content-Type'  =\u003e 'application/json',\n    ]\n);\n\n// If you want to set a non-origin-form request target, set the\n// request-target explicitly:\n$request = $request-\u003ewithRequestTarget((string) $uri));       // absolute-form\n$request = $request-\u003ewithRequestTarget($uri-\u003egetAuthority()); // authority-form\n$request = $request-\u003ewithRequestTarget('*');                 // asterisk-form\n\n// Once you have the instance:\n$request-\u003egetBody()-\u003ewrite(json_encode($data));\n$response = $client-\u003esend($request);\n\nprintf(\"Response status: %d (%s)\\n\", $response-\u003egetStatusCode(), $response-\u003egetReasonPhrase());\nprintf(\"Headers:\\n\");\nforeach ($response-\u003egetHeaders() as $header =\u003e $values) {\n  printf(\"%s: %s\\n\", $header, implode(', ', $values));\n}\nprintf(\"Message:\\n%s\\n\", $response-\u003egetBody());\n```\n\n(Note: phly/http does NOT ship with a client implementation; the above is just an illustration of a possible implementation.)\n\n### Server-Side Applications\n\nServer-side applications will need to marshal the incoming request based on superglobals, and will then populate and send a response.\n\n#### Marshaling an incoming request\n\nPHP contains a plethora of information about the incoming request, and keeps that information in a variety of locations. `Phly\\Http\\ServerRequestFactory::fromGlobals()` can simplify marshaling that information into a request instance.\n\nYou can call the factory method with or without the following arguments, in the following order:\n\n- `$server`, typically `$_SERVER`\n- `$query`, typically `$_GET`\n- `$body`, typically `$_POST`\n- `$cookies`, typically `$_COOKIE`\n- `$files`, typically `$_FILES`\n\nThe method will then return a `Phly\\Http\\ServerRequest` instance. If any argument is omitted, the associated superglobal will be used.\n\n```php\n$request = Phly\\Http\\ServerRequestFactory::fromGlobals(\n  $_SERVER,\n  $_GET,\n  $_POST,\n  $_COOKIE,\n  $_FILES\n);\n```\n\n#### Manipulating the response\n\nUse the response object to add headers and provide content for the response.  Writing to the body does not create a state change in the response, so it can be done without capturing the return value. Manipulating headers does, however.\n\n```php\n$response = new Phly\\Http\\Response();\n\n// Write to the response body:\n$response-\u003egetBody()-\u003ewrite(\"some content\\n\");\n\n// Multiple calls to write() append:\n$response-\u003egetBody()-\u003ewrite(\"more content\\n\"); // now \"some content\\nmore content\\n\"\n\n// Add headers\n// Note: headers do not need to be added before data is written to the body!\n$response = $response\n    -\u003ewithHeader('Content-Type', 'text/plain')\n    -\u003ewithAddedHeader('X-Show-Something', 'something');\n```\n\n#### \"Serving\" an application\n\n`Phly\\Http\\Server` mimics a portion of the API of node's `http.Server` class. It invokes a callback, passing it an `ServerRequest`, an `Response`, and optionally a callback to use for incomplete/unhandled requests.\n\nYou can create a server in one of three ways:\n\n```php\n// Direct instantiation, with a callback handler, request, and response\n$server = new Phly\\Http\\Server(\n    function ($request, $response, $done) {\n        $response-\u003egetBody()-\u003ewrite(\"Hello world!\");\n    },\n    $request,\n    $response\n);\n\n// Using the createServer factory, providing it with the various superglobals:\n$server = Phly\\Http\\Server::createServer(\n    function ($request, $response, $done) {\n        $response-\u003egetBody()-\u003ewrite(\"Hello world!\");\n    },\n    $_SERVER,\n    $_GET,\n    $_POST,\n    $_COOKIE,\n    $_FILES\n);\n\n// Using the createServerFromRequest factory, and providing it a request:\n$server = Phly\\Http\\Server::createServerfromRequest(\n  function ($request, $response, $done) {\n      $response-\u003egetBody()-\u003ewrite(\"Hello world!\");\n  },\n  $request\n);\n```\n\nServer callbacks can expect up to three arguments, in the following order:\n\n- `$request` - the request object\n- `$response` - the response object\n- `$done` - an optional callback to call when complete\n\nOnce you have your server instance, you must instruct it to listen:\n\n```php\n$server-\u003elisten();\n```\n\nAt this time, you can optionally provide a callback to `listen()`; this will be passed to the handler as the third argument (`$done`):\n\n```php\n$server-\u003elisten(function ($request, $response, $error = null) {\n    if (! $error) {\n        return;\n    }\n    // do something with the error...\n});\n```\n\nTypically, the `listen` callback will be an error handler, and can expect to\nreceive the request, response, and error as its arguments (though the error may\nbe null).\n\nAPI\n---\n\n### Request Message\n\n`Phly\\Http\\Request` implements `Psr\\Http\\Message\\RequestInterface`, and is intended for client-side requests. It includes the following methods:\n\n```php\nclass Request\n{\n    public function __construct(\n        $uri = null,\n        $method = null,\n        $body = 'php://memory',\n        array $headers = []\n    );\n\n    // See psr/http-message's RequestInterface for other methods\n}\n```\n\nRequests are immutable. Any methods that would change state -- those prefixed with `with` and `without` -- all return a new instance with the changes requested.\n\n### ServerRequest Message\n\nFor server-side applications, `Phly\\Http\\ServerRequest` implements `Psr\\Http\\Message\\ServerRequestInterface`, which provides access to the elements of an HTTP request, as well as uniform access to the various elements of incoming data. The methods included are:\n\n```php\nclass ServerRequest\n{\n    public function __construct(\n        array $serverParams = [],\n        array $fileParams = [],\n        $uri = null,\n        $method = null,\n        $body = 'php://input',\n        array $headers = []\n    );\n\n    // See psr/http-message's ServerRequestInterface for other methods.\n}\n```\n\nThe `ServerRequest` is immutable. Any methods that would change state -- those prefixed with `with` and `without` -- all return a new instance with the changes requested. Server parameters are considered completely immutable, however, as they cannot be recalculated, and, rather, is a source for other values.\n\n### Response Message\n\n`Phly\\Http\\Response` provides an implementation of `Psr\\Http\\Message\\ResponseInterface`, an object to be used to aggregate response information for both HTTP clients and server-side applications, including headers and message body content. It includes the following:\n\n```php\nclass Response\n{\n    public function __construct(\n        $body = 'php://memory',\n        $statusCode = 200,\n        array $headers = []\n    );\n\n    // See psr/http-message's ResponseInterface for other methods\n}\n```\n\nLike the `Request` and `ServerRequest`, responses are immutable. Any methods that would change state -- those prefixed with `with` and `without` -- all return a new instance with the changes requested.\n\n#### ServerRequestFactory\n\nThis static class can be used to marshal a `ServerRequest` instance from the PHP environment. The primary entry point is `Phly\\Http\\ServerRequestFactory::fromGlobals(array $server, array $query, array $body, array $cookies, array $files)`. This method will create a new `ServerRequest` instance with the data provided. Examples of usage are:\n\n```php\n// Returns new ServerRequest instance, using values from superglobals:\n$request = ServerRequestFactory::fromGlobals();\n\n// or\n\n// Returns new ServerRequest instance, using values provided (in this\n// case, equivalent to the previous!)\n$request = RequestFactory::fromGlobals(\n  $_SERVER,\n  $_GET,\n  $_POST,\n  $_COOKIE,\n  $_FILES\n);\n```\n\n### URI\n\n`Phly\\Http\\Uri` is an implementation of `Psr\\Http\\Message\\UriInterface`, and models and validates URIs. It implements `__toString()`, allowing it to be represented as a string and `echo()`'d directly. The following methods are pertinent:\n\n```php\nclass Uri\n{\n    public function __construct($uri = '');\n\n    // See psr/http-message's UriInterface for other methods.\n}\n```\n\nLike the various message objects, URIs are immutable. Any methods that would change state -- those prefixed with `with` and `without` -- all return a new instance with the changes requested.\n\n### Stream\n\n`Phly\\Http\\Stream` is an implementation of `Psr\\Http\\Message\\StreamInterface`, and provides a number of facilities around manipulating the composed PHP stream resource. The constructor accepts a stream, which may be either:\n\n- a stream identifier; e.g., `php://input`, a filename, etc.\n- a PHP stream resource\n\nIf a stream identifier is provided, an optional second parameter may be provided, the file mode by which to `fopen` the stream.\n\n`ServerRequest` objects by default use a `php://input` stream set to read-only; `Response` objects by default use a `php://memory` with a mode of `wb+`, allowing binary read/write access.\n\nIn most cases, you will not interact with the Stream object directly.\n\n### UploadedFile\n\n`Phly\\Http\\UploadedFile` is an implementation of `Psr\\Http\\Message\\UploadedFileInterface`, and provides abstraction around a single uploaded file, including behavior for interacting with it as a stream or moving it to a filesystem location.\n\nIn most cases, you will only use the methods defined in the `UploadedFileInterface`.\n\n### Server\n\n`Phly\\Http\\Server` represents a server capable of executing a callback. It has four methods:\n\n```php\nclass Server\n{\n    public function __construct(\n        callable $callback,\n        Psr\\Http\\Message\\ServerRequestInterface $request,\n        Psr\\Http\\Message\\ResponseInterface $response\n    );\n    public static function createServer(\n        callable $callback,\n        array $server,  // usually $_SERVER\n        array $query,   // usually $_GET\n        array $body,    // usually $_POST\n        array $cookies, // usually $_COOKIE\n        array $files    // usually $_FILES\n    );\n    public static function createServerFromRequest(\n        callable $callback,\n        Psr\\Http\\Message\\ServerRequestInterface $request,\n        Psr\\Http\\Message\\ResponseInterface $response = null\n    );\n    public function setEmitter(Response\\EmitterInterface $emitter);\n    public function listen(callable $finalHandler = null);\n}\n```\n\nYou can create an instance of the `Server` using any of the constructor, `createServer()`, or `createServerFromRequest()` methods. If you wish to use the default request and response implementations, `createServer($middleware, $_SERVER, $_GET, $_POST, $_COOKIE, $_FILES)` is the recommended option, as this method will also marshal the `ServerRequest` object based on the PHP request environment.  If you wish to use your own implementations, pass them to the constructor or `createServerFromRequest()` method (the latter will create a default `Response` instance if you omit it).\n\n`listen()` executes the callback. If a `$finalHandler` is provided, it will be passed as the third argument to the `$callback` registered with the server.\n\n## Emitting responses\n\nIf you are using a non-SAPI PHP implementation and wish to use the `Server` class, or if you do not want to use the `Server` implementation but want to emit a response, this package provides an interface, `Phly\\Http\\Response\\EmitterInterface`, defining a method `emit()` for emitting the response. A single implementation is currently available, `Phly\\Http\\Response\\SapiEmitter`, which will use the native PHP functions `header()` and `echo` in order to emit the response. If you are using a non-SAPI implementation, you will need to create your own `EmitterInterface` implementation.\n\n## Serialization\n\nAt times, it's useful to either create a string representation of a message (serialization), or to cast a string or stream message to an object (deserialization). This package provides features for this in `Phly\\Http\\Request\\Serializer` and `Phly\\Http\\Response\\Serializer`; each provides the following static methods:\n\n- `fromString($message)` will create either a `Request` or `Response` instance (based on the serializer used) from the string message.\n- `fromStream(Psr\\Http\\Message\\StreamInterface $stream)` will create either a `Request` or `Response` instance (based on the serializer used) from the provided stream.\n- `toString(Psr\\Http\\Message\\RequestInterface|Psr\\Http\\Message\\ResponseInterface $message)` will create either a string from the provided message.\n\nThe deserialization methods (`from*()`) will raise exceptions if errors occur while parsing the message. The serialization methods (`toString()`) will raise exceptions if required data for serialization is not present in the message instance.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphly%2Fhttp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphly%2Fhttp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphly%2Fhttp/lists"}