{"id":13404979,"url":"https://github.com/reactphp/http","last_synced_at":"2025-05-13T19:03:04.277Z","repository":{"id":3249878,"uuid":"4287609","full_name":"reactphp/http","owner":"reactphp","description":"Event-driven, streaming HTTP client and server implementation for ReactPHP.","archived":false,"fork":false,"pushed_at":"2024-11-25T18:14:29.000Z","size":1619,"stargazers_count":760,"open_issues_count":20,"forks_count":151,"subscribers_count":40,"default_branch":"3.x","last_synced_at":"2025-05-05T09:29:56.233Z","etag":null,"topics":["http","http-client","http-server","https","php","reactphp","response-stream","streaming-request","streaming-response"],"latest_commit_sha":null,"homepage":"https://reactphp.org/http/","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/reactphp.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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},"funding":{"github":["reactphp","clue","WyriHaximus"],"open_collective":"reactphp"}},"created_at":"2012-05-10T17:31:28.000Z","updated_at":"2025-05-01T19:56:30.000Z","dependencies_parsed_at":"2023-02-13T21:46:14.624Z","dependency_job_id":"f9408d93-1cd2-46eb-a046-c421de3e4119","html_url":"https://github.com/reactphp/http","commit_stats":{"total_commits":540,"total_committers":40,"mean_commits":13.5,"dds":0.6981481481481482,"last_synced_commit":"fc5f0a6739ba4a10de3847bab4688c602e5fe948"},"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactphp%2Fhttp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactphp%2Fhttp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactphp%2Fhttp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactphp%2Fhttp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reactphp","download_url":"https://codeload.github.com/reactphp/http/tar.gz/refs/heads/3.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254010792,"owners_count":21998993,"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","http-client","http-server","https","php","reactphp","response-stream","streaming-request","streaming-response"],"created_at":"2024-07-30T19:01:54.046Z","updated_at":"2025-05-13T19:03:04.248Z","avatar_url":"https://github.com/reactphp.png","language":"PHP","readme":"# HTTP\n\n[![CI status](https://github.com/reactphp/http/actions/workflows/ci.yml/badge.svg)](https://github.com/reactphp/http/actions)\n[![installs on Packagist](https://img.shields.io/packagist/dt/react/http?color=blue\u0026label=installs%20on%20Packagist)](https://packagist.org/packages/react/http)\n\nEvent-driven, streaming HTTP client and server implementation for [ReactPHP](https://reactphp.org/).\n\n\u003e **Development version:** This branch contains the code for the upcoming v3\n\u003e release. For the code of the current stable v1 release, check out the\n\u003e [`1.x` branch](https://github.com/reactphp/http/tree/1.x).\n\u003e\n\u003e The upcoming v3 release will be the way forward for this package. However,\n\u003e we will still actively support v1 for those not yet on the latest version.\n\u003e See also [installation instructions](#install) for more details.\n\nThis HTTP library provides re-usable implementations for an HTTP client and\nserver based on ReactPHP's [`Socket`](https://github.com/reactphp/socket) and\n[`EventLoop`](https://github.com/reactphp/event-loop) components.\nIts client component allows you to send any number of async HTTP/HTTPS requests\nconcurrently.\nIts server component allows you to build plaintext HTTP and secure HTTPS servers\nthat accept incoming HTTP requests from HTTP clients (such as web browsers).\nThis library provides async, streaming means for all of this, so you can handle\nmultiple concurrent HTTP requests without blocking.\n\n**Table of contents**\n\n* [Quickstart example](#quickstart-example)\n* [Client Usage](#client-usage)\n    * [Request methods](#request-methods)\n    * [Promises](#promises)\n    * [Cancellation](#cancellation)\n    * [Timeouts](#timeouts)\n    * [Authentication](#authentication)\n    * [Redirects](#redirects)\n    * [Blocking](#blocking)\n    * [Concurrency](#concurrency)\n    * [Streaming response](#streaming-response)\n    * [Streaming request](#streaming-request)\n    * [HTTP proxy](#http-proxy)\n    * [SOCKS proxy](#socks-proxy)\n    * [SSH proxy](#ssh-proxy)\n    * [Unix domain sockets](#unix-domain-sockets)\n* [Server Usage](#server-usage)\n    * [HttpServer](#httpserver)\n    * [listen()](#listen)\n    * [Server Request](#server-request)\n        * [Request parameters](#request-parameters)\n        * [Query parameters](#query-parameters)\n        * [Request body](#request-body)\n        * [Streaming incoming request](#streaming-incoming-request)\n        * [Request method](#request-method)\n        * [Cookie parameters](#cookie-parameters)\n        * [Invalid request](#invalid-request)\n    * [Server Response](#server-response)\n        * [Deferred response](#deferred-response)\n        * [Streaming outgoing response](#streaming-outgoing-response)\n        * [Response length](#response-length)\n        * [Invalid response](#invalid-response)\n        * [Default response headers](#default-response-headers)\n    * [Middleware](#middleware)\n        * [Custom middleware](#custom-middleware)\n        * [Third-Party Middleware](#third-party-middleware)\n* [API](#api)\n    * [Browser](#browser)\n        * [get()](#get)\n        * [post()](#post)\n        * [head()](#head)\n        * [patch()](#patch)\n        * [put()](#put)\n        * [delete()](#delete)\n        * [request()](#request)\n        * [requestStreaming()](#requeststreaming)\n        * [withTimeout()](#withtimeout)\n        * [withFollowRedirects()](#withfollowredirects)\n        * [withRejectErrorResponse()](#withrejecterrorresponse)\n        * [withBase()](#withbase)\n        * [withProtocolVersion()](#withprotocolversion)\n        * [withResponseBuffer()](#withresponsebuffer)\n        * [withHeader()](#withheader)\n        * [withoutHeader()](#withoutheader)\n    * [React\\Http\\Message](#reacthttpmessage)\n        * [Response](#response)\n            * [html()](#html)\n            * [json()](#json)\n            * [plaintext()](#plaintext)\n            * [xml()](#xml)\n        * [Request](#request-1)\n        * [ServerRequest](#serverrequest)\n        * [Uri](#uri)\n        * [ResponseException](#responseexception)\n    * [React\\Http\\Middleware](#reacthttpmiddleware)\n        * [StreamingRequestMiddleware](#streamingrequestmiddleware)\n        * [LimitConcurrentRequestsMiddleware](#limitconcurrentrequestsmiddleware)\n        * [RequestBodyBufferMiddleware](#requestbodybuffermiddleware)\n        * [RequestBodyParserMiddleware](#requestbodyparsermiddleware)\n* [Install](#install)\n* [Tests](#tests)\n* [License](#license)\n\n## Quickstart example\n\nOnce [installed](#install), you can use the following code to access an\nHTTP web server and send some simple HTTP GET requests:\n\n```php\n\u003c?php\n\nrequire __DIR__ . '/vendor/autoload.php';\n\n$client = new React\\Http\\Browser();\n\n$client-\u003eget('http://www.google.com/')-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    var_dump($response-\u003egetHeaders(), (string)$response-\u003egetBody());\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nThis is an HTTP server which responds with `Hello World!` to every request.\n\n```php\n\u003c?php\n\nrequire __DIR__ . '/vendor/autoload.php';\n\n$http = new React\\Http\\HttpServer(function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n    return React\\Http\\Message\\Response::plaintext(\n        \"Hello World!\\n\"\n    );\n});\n\n$socket = new React\\Socket\\SocketServer('127.0.0.1:8080');\n$http-\u003elisten($socket);\n```\n\nSee also the [examples](examples/).\n\n## Client Usage\n\n### Request methods\n\nMost importantly, this project provides a [`Browser`](#browser) object that\noffers several methods that resemble the HTTP protocol methods:\n\n```php\n$browser-\u003eget($url, array $headers = []);\n$browser-\u003ehead($url, array $headers = []);\n$browser-\u003epost($url, array $headers = [], string|ReadableStreamInterface $body = '');\n$browser-\u003edelete($url, array $headers = [], string|ReadableStreamInterface $body = '');\n$browser-\u003eput($url, array $headers = [], string|ReadableStreamInterface $body = '');\n$browser-\u003epatch($url, array $headers = [], string|ReadableStreamInterface $body = '');\n```\n\nEach of these methods requires a `$url` and some optional parameters to send an\nHTTP request. Each of these method names matches the respective HTTP request\nmethod, for example the [`get()`](#get) method sends an HTTP `GET` request.\n\nYou can optionally pass an associative array of additional `$headers` that will be\nsent with this HTTP request. Additionally, each method will automatically add a\nmatching `Content-Length` request header if an outgoing request body is given and its\nsize is known and non-empty. For an empty request body, if will only include a\n`Content-Length: 0` request header if the request method usually expects a request\nbody (only applies to `POST`, `PUT` and `PATCH` HTTP request methods).\n\nIf you're using a [streaming request body](#streaming-request), it will default\nto using `Transfer-Encoding: chunked` unless you explicitly pass in a matching `Content-Length`\nrequest header. See also [streaming request](#streaming-request) for more details.\n\nBy default, all of the above methods default to sending requests using the\nHTTP/1.1 protocol version. If you want to explicitly use the legacy HTTP/1.0\nprotocol version, you can use the [`withProtocolVersion()`](#withprotocolversion)\nmethod. If you want to use any other or even custom HTTP request method, you can\nuse the [`request()`](#request) method.\n\nEach of the above methods supports async operation and either *fulfills* with a\n[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface)\nor *rejects* with an `Exception`.\nPlease see the following chapter about [promises](#promises) for more details.\n\n### Promises\n\nSending requests is async (non-blocking), so you can actually send multiple\nrequests in parallel.\nThe `Browser` will respond to each request with a\n[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface)\nmessage, the order is not guaranteed.\nSending requests uses a [Promise](https://github.com/reactphp/promise)-based\ninterface that makes it easy to react to when an HTTP request is completed\n(i.e. either successfully fulfilled or rejected with an error):\n\n```php\n$browser-\u003eget($url)-\u003ethen(\n    function (Psr\\Http\\Message\\ResponseInterface $response) {\n        var_dump('Response received', $response);\n    },\n    function (Exception $e) {\n        echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n    }\n);\n```\n\nIf this looks strange to you, you can also use the more traditional [blocking API](#blocking).\n\nKeep in mind that resolving the Promise with the full response message means the\nwhole response body has to be kept in memory.\nThis is easy to get started and works reasonably well for smaller responses\n(such as common HTML pages or RESTful or JSON API requests).\n\nYou may also want to look into the [streaming API](#streaming-response):\n\n* If you're dealing with lots of concurrent requests (100+) or\n* If you want to process individual data chunks as they happen (without having to wait for the full response body) or\n* If you're expecting a big response body size (1 MiB or more, for example when downloading binary files) or\n* If you're unsure about the response body size (better be safe than sorry when accessing arbitrary remote HTTP endpoints and the response body size is unknown in advance).\n\n### Cancellation\n\nThe returned Promise is implemented in such a way that it can be cancelled\nwhen it is still pending.\nCancelling a pending promise will reject its value with an Exception and\nclean up any underlying resources.\n\n```php\n$promise = $browser-\u003eget($url);\n\nLoop::addTimer(2.0, function () use ($promise) {\n    $promise-\u003ecancel();\n});\n```\n\n### Timeouts\n\nThis library uses a very efficient HTTP implementation, so most HTTP requests\nshould usually be completed in mere milliseconds. However, when sending HTTP\nrequests over an unreliable network (the internet), there are a number of things\nthat can go wrong and may cause the request to fail after a time. As such, this\nlibrary respects PHP's `default_socket_timeout` setting (default 60s) as a timeout\nfor sending the outgoing HTTP request and waiting for a successful response and\nwill otherwise cancel the pending request and reject its value with an Exception.\n\nNote that this timeout value covers creating the underlying transport connection,\nsending the HTTP request, receiving the HTTP response headers and its full\nresponse body and following any eventual [redirects](#redirects). See also\n[redirects](#redirects) below to configure the number of redirects to follow (or\ndisable following redirects altogether) and also [streaming](#streaming-response)\nbelow to not take receiving large response bodies into account for this timeout.\n\nYou can use the [`withTimeout()` method](#withtimeout) to pass a custom timeout\nvalue in seconds like this:\n\n```php\n$browser = $browser-\u003ewithTimeout(10.0);\n\n$browser-\u003eget($url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    // response received within 10 seconds maximum\n    var_dump($response-\u003egetHeaders());\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nSimilarly, you can use a bool `false` to not apply a timeout at all\nor use a bool `true` value to restore the default handling.\nSee [`withTimeout()`](#withtimeout) for more details.\n\nIf you're using a [streaming response body](#streaming-response), the time it\ntakes to receive the response body stream will not be included in the timeout.\nThis allows you to keep this incoming stream open for a longer time, such as\nwhen downloading a very large stream or when streaming data over a long-lived\nconnection.\n\nIf you're using a [streaming request body](#streaming-request), the time it\ntakes to send the request body stream will not be included in the timeout. This\nallows you to keep this outgoing stream open for a longer time, such as when\nuploading a very large stream.\n\nNote that this timeout handling applies to the higher-level HTTP layer. Lower\nlayers such as socket and DNS may also apply (different) timeout values. In\nparticular, the underlying socket connection uses the same `default_socket_timeout`\nsetting to establish the underlying transport connection. To control this\nconnection timeout behavior, you can [inject a custom `Connector`](#browser)\nlike this:\n\n```php\n$browser = new React\\Http\\Browser(\n    new React\\Socket\\Connector(\n        [\n            'timeout' =\u003e 5\n        ]\n    )\n);\n```\n\n### Authentication\n\nThis library supports [HTTP Basic Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication)\nusing the `Authorization: Basic …` request header or allows you to set an explicit\n`Authorization` request header.\n\nBy default, this library does not include an outgoing `Authorization` request\nheader. If the server requires authentication, if may return a `401` (Unauthorized)\nstatus code which will reject the request by default (see also the\n[`withRejectErrorResponse()` method](#withrejecterrorresponse) below).\n\nIn order to pass authentication details, you can simply pass the username and\npassword as part of the request URL like this:\n\n```php\n$promise = $browser-\u003eget('https://user:pass@example.com/api');\n```\n\nNote that special characters in the authentication details have to be\npercent-encoded, see also [`rawurlencode()`](https://www.php.net/manual/en/function.rawurlencode.php).\nThis example will automatically pass the base64-encoded authentication details\nusing the outgoing `Authorization: Basic …` request header. If the HTTP endpoint\nyou're talking to requires any other authentication scheme, you can also pass\nthis header explicitly. This is common when using (RESTful) HTTP APIs that use\nOAuth access tokens or JSON Web Tokens (JWT):\n\n```php\n$token = 'abc123';\n\n$promise = $browser-\u003eget(\n    'https://example.com/api',\n    [\n        'Authorization' =\u003e 'Bearer ' . $token\n    ]\n);\n```\n\nWhen following redirects, the `Authorization` request header will never be sent\nto any remote hosts by default. When following a redirect where the `Location`\nresponse header contains authentication details, these details will be sent for\nfollowing requests. See also [redirects](#redirects) below.\n\n### Redirects\n\nBy default, this library follows any redirects and obeys `3xx` (Redirection)\nstatus codes using the `Location` response header from the remote server.\nThe promise will be fulfilled with the last response from the chain of redirects.\n\n```php\n$browser-\u003eget($url, $headers)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    // the final response will end up here\n    var_dump($response-\u003egetHeaders());\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nAny redirected requests will follow the semantics of the original request and\nwill include the same request headers as the original request except for those\nlisted below.\nIf the original request is a temporary (307) or a permanent (308) redirect, request\nbody and headers will be passed to the redirected request. Otherwise, the request \nbody will never be passed to the redirected request. Accordingly, each redirected \nrequest will remove any `Content-Length` and `Content-Type` request headers.\n\nIf the original request used HTTP authentication with an `Authorization` request\nheader, this request header will only be passed as part of the redirected\nrequest if the redirected URL is using the same host. In other words, the\n`Authorizaton` request header will not be forwarded to other foreign hosts due to\npossible privacy/security concerns. When following a redirect where the `Location`\nresponse header contains authentication details, these details will be sent for\nfollowing requests.\n\nYou can use the [`withFollowRedirects()`](#withfollowredirects) method to\ncontrol the maximum number of redirects to follow or to return any redirect\nresponses as-is and apply custom redirection logic like this:\n\n```php\n$browser = $browser-\u003ewithFollowRedirects(false);\n\n$browser-\u003eget($url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    // any redirects will now end up here\n    var_dump($response-\u003egetHeaders());\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nSee also [`withFollowRedirects()`](#withfollowredirects) for more details.\n\n### Blocking\n\nAs stated above, this library provides you a powerful, async API by default.\n\nYou can also integrate this into your traditional, blocking environment by using\n[reactphp/async](https://github.com/reactphp/async). This allows you to simply\nawait async HTTP requests like this:\n\n```php\nuse function React\\Async\\await;\n\n$browser = new React\\Http\\Browser();\n\n$promise = $browser-\u003eget('http://example.com/');\n\ntry {\n    $response = await($promise);\n    // response successfully received\n} catch (Exception $e) {\n    // an error occurred while performing the request\n}\n```\n\nSimilarly, you can also process multiple requests concurrently and await an array of `Response` objects:\n\n```php\nuse function React\\Async\\await;\nuse function React\\Promise\\all;\n\n$promises = [\n    $browser-\u003eget('http://example.com/'),\n    $browser-\u003eget('http://www.example.org/'),\n];\n\n$responses = await(all($promises));\n```\n\nThis is made possible thanks to fibers available in PHP 8.1+ and our\ncompatibility API that also works on all supported PHP versions.\nPlease refer to [reactphp/async](https://github.com/reactphp/async#readme) for more details.\n\nKeep in mind the above remark about buffering the whole response message in memory.\nAs an alternative, you may also see one of the following chapters for the\n[streaming API](#streaming-response).\n\n### Concurrency\n\nAs stated above, this library provides you a powerful, async API. Being able to\nsend a large number of requests at once is one of the core features of this\nproject. For instance, you can easily send 100 requests concurrently while\nprocessing SQL queries at the same time.\n\nRemember, with great power comes great responsibility. Sending an excessive\nnumber of requests may either take up all resources on your side or it may even\nget you banned by the remote side if it sees an unreasonable number of requests\nfrom your side.\n\n```php\n// watch out if array contains many elements\nforeach ($urls as $url) {\n    $browser-\u003eget($url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n        var_dump($response-\u003egetHeaders());\n    }, function (Exception $e) {\n        echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n    });\n}\n```\n\nAs a consequence, it's usually recommended to limit concurrency on the sending\nside to a reasonable value. It's common to use a rather small limit, as doing\nmore than a dozen of things at once may easily overwhelm the receiving side. You\ncan use [clue/reactphp-mq](https://github.com/clue/reactphp-mq) as a lightweight\nin-memory queue to concurrently do many (but not too many) things at once:\n\n```php\n// wraps Browser in a Queue object that executes no more than 10 operations at once\n$q = new Clue\\React\\Mq\\Queue(10, null, function ($url) use ($browser) {\n    return $browser-\u003eget($url);\n});\n\nforeach ($urls as $url) {\n    $q($url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n        var_dump($response-\u003egetHeaders());\n    }, function (Exception $e) {\n        echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n    });\n}\n```\n\nAdditional requests that exceed the concurrency limit will automatically be\nenqueued until one of the pending requests completes. This integrates nicely\nwith the existing [Promise-based API](#promises). Please refer to\n[clue/reactphp-mq](https://github.com/clue/reactphp-mq) for more details.\n\nThis in-memory approach works reasonably well for some thousand outstanding\nrequests. If you're processing a very large input list (think millions of rows\nin a CSV or NDJSON file), you may want to look into using a streaming approach\ninstead. See [clue/reactphp-flux](https://github.com/clue/reactphp-flux) for\nmore details.\n\n### Streaming response\n\nAll of the above examples assume you want to store the whole response body in memory.\nThis is easy to get started and works reasonably well for smaller responses.\n\nHowever, there are several situations where it's usually a better idea to use a\nstreaming approach, where only small chunks have to be kept in memory:\n\n* If you're dealing with lots of concurrent requests (100+) or\n* If you want to process individual data chunks as they happen (without having to wait for the full response body) or\n* If you're expecting a big response body size (1 MiB or more, for example when downloading binary files) or\n* If you're unsure about the response body size (better be safe than sorry when accessing arbitrary remote HTTP endpoints and the response body size is unknown in advance). \n\nYou can use the [`requestStreaming()`](#requeststreaming) method to send an\narbitrary HTTP request and receive a streaming response. It uses the same HTTP\nmessage API, but does not buffer the response body in memory. It only processes\nthe response body in small chunks as data is received and forwards this data\nthrough [ReactPHP's Stream API](https://github.com/reactphp/stream). This works\nfor (any number of) responses of arbitrary sizes.\n\nThis means it resolves with a normal\n[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface),\nwhich can be used to access the response message parameters as usual.\nYou can access the message body as usual, however it now also\nimplements [ReactPHP's `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface)\nas well as parts of the [PSR-7 `StreamInterface`](https://www.php-fig.org/psr/psr-7/#34-psrhttpmessagestreaminterface).\n\n```php\n$browser-\u003erequestStreaming('GET', $url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    $body = $response-\u003egetBody();\n    assert($body instanceof Psr\\Http\\Message\\StreamInterface);\n    assert($body instanceof React\\Stream\\ReadableStreamInterface);\n\n    $body-\u003eon('data', function ($chunk) {\n        echo $chunk;\n    });\n\n    $body-\u003eon('error', function (Exception $e) {\n        echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n    });\n\n    $body-\u003eon('close', function () {\n        echo '[DONE]' . PHP_EOL;\n    });\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nSee also the [stream download benchmark example](examples/91-client-benchmark-download.php) and\nthe [stream forwarding example](examples/21-client-request-streaming-to-stdout.php).\n\nYou can invoke the following methods on the message body:\n\n```php\n$body-\u003eon($event, $callback);\n$body-\u003eeof();\n$body-\u003eisReadable();\n$body-\u003epipe(React\\Stream\\WritableStreamInterface $dest, array $options = []);\n$body-\u003eclose();\n$body-\u003epause();\n$body-\u003eresume();\n```\n\nBecause the message body is in a streaming state, invoking the following methods\ndoesn't make much sense:\n\n```php\n$body-\u003e__toString(); // ''\n$body-\u003edetach(); // throws BadMethodCallException\n$body-\u003egetSize(); // null\n$body-\u003etell(); // throws BadMethodCallException\n$body-\u003eisSeekable(); // false\n$body-\u003eseek(); // throws BadMethodCallException\n$body-\u003erewind(); // throws BadMethodCallException\n$body-\u003eisWritable(); // false\n$body-\u003ewrite(); // throws BadMethodCallException\n$body-\u003eread(); // throws BadMethodCallException\n$body-\u003egetContents(); // throws BadMethodCallException\n```\n\nNote how [timeouts](#timeouts) apply slightly differently when using streaming.\nIn streaming mode, the timeout value covers creating the underlying transport\nconnection, sending the HTTP request, receiving the HTTP response headers and\nfollowing any eventual [redirects](#redirects). In particular, the timeout value\ndoes not take receiving (possibly large) response bodies into account.\n\nIf you want to integrate the streaming response into a higher level API, then\nworking with Promise objects that resolve with Stream objects is often inconvenient.\nConsider looking into also using [react/promise-stream](https://github.com/reactphp/promise-stream).\nThe resulting streaming code could look something like this:\n\n```php\nuse function React\\Promise\\Stream\\unwrapReadable;\n\nfunction download(Browser $browser, string $url): React\\Stream\\ReadableStreamInterface {\n    return unwrapReadable(\n        $browser-\u003erequestStreaming('GET', $url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n            return $response-\u003egetBody();\n        })\n    );\n}\n\n$stream = download($browser, $url);\n$stream-\u003eon('data', function ($data) {\n    echo $data;\n});\n$stream-\u003eon('error', function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nSee also the [`requestStreaming()`](#requeststreaming) method for more details.\n\n### Streaming request\n\nBesides streaming the response body, you can also stream the request body.\nThis can be useful if you want to send big POST requests (uploading files etc.)\nor process many outgoing streams at once.\nInstead of passing the body as a string, you can simply pass an instance\nimplementing [ReactPHP's `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface)\nto the [request methods](#request-methods) like this:\n\n```php\n$browser-\u003epost($url, [], $stream)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    echo 'Successfully sent.';\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nIf you're using a streaming request body (`React\\Stream\\ReadableStreamInterface`), it will\ndefault to using `Transfer-Encoding: chunked` or you have to explicitly pass in a\nmatching `Content-Length` request header like so:\n\n```php\n$body = new React\\Stream\\ThroughStream();\nLoop::addTimer(1.0, function () use ($body) {\n    $body-\u003eend(\"hello world\");\n});\n\n$browser-\u003epost($url, ['Content-Length' =\u003e '11'], $body);\n```\n\nIf the streaming request body emits an `error` event or is explicitly closed\nwithout emitting a successful `end` event first, the request will automatically\nbe closed and rejected.\n\n### HTTP proxy\n\nYou can also establish your outgoing connections through an HTTP CONNECT proxy server\nby adding a dependency to [clue/reactphp-http-proxy](https://github.com/clue/reactphp-http-proxy).\n\nHTTP CONNECT proxy servers (also commonly known as \"HTTPS proxy\" or \"SSL proxy\")\nare commonly used to tunnel HTTPS traffic through an intermediary (\"proxy\"), to\nconceal the origin address (anonymity) or to circumvent address blocking\n(geoblocking). While many (public) HTTP CONNECT proxy servers often limit this\nto HTTPS port `443` only, this can technically be used to tunnel any TCP/IP-based\nprotocol, such as plain HTTP and TLS-encrypted HTTPS.\n\n```php\n$proxy = new Clue\\React\\HttpProxy\\ProxyConnector('127.0.0.1:8080');\n\n$connector = new React\\Socket\\Connector([\n    'tcp' =\u003e $proxy,\n    'dns' =\u003e false\n]);\n\n$browser = new React\\Http\\Browser($connector);\n```\n\nSee also the [HTTP proxy example](examples/11-client-http-proxy.php).\n\n### SOCKS proxy\n\nYou can also establish your outgoing connections through a SOCKS proxy server\nby adding a dependency to [clue/reactphp-socks](https://github.com/clue/reactphp-socks).\n\nThe SOCKS proxy protocol family (SOCKS5, SOCKS4 and SOCKS4a) is commonly used to\ntunnel HTTP(S) traffic through an intermediary (\"proxy\"), to conceal the origin\naddress (anonymity) or to circumvent address blocking (geoblocking). While many\n(public) SOCKS proxy servers often limit this to HTTP(S) port `80` and `443`\nonly, this can technically be used to tunnel any TCP/IP-based protocol.\n\n```php\n$proxy = new Clue\\React\\Socks\\Client('127.0.0.1:1080');\n\n$connector = new React\\Socket\\Connector([\n    'tcp' =\u003e $proxy,\n    'dns' =\u003e false\n]);\n\n$browser = new React\\Http\\Browser($connector);\n```\n\nSee also the [SOCKS proxy example](examples/12-client-socks-proxy.php).\n\n### SSH proxy\n\nYou can also establish your outgoing connections through an SSH server\nby adding a dependency to [clue/reactphp-ssh-proxy](https://github.com/clue/reactphp-ssh-proxy).\n\n[Secure Shell (SSH)](https://en.wikipedia.org/wiki/Secure_Shell) is a secure\nnetwork protocol that is most commonly used to access a login shell on a remote\nserver. Its architecture allows it to use multiple secure channels over a single\nconnection. Among others, this can also be used to create an \"SSH tunnel\", which\nis commonly used to tunnel HTTP(S) traffic through an intermediary (\"proxy\"), to\nconceal the origin address (anonymity) or to circumvent address blocking\n(geoblocking). This can be used to tunnel any TCP/IP-based protocol (HTTP, SMTP,\nIMAP etc.), allows you to access local services that are otherwise not accessible\nfrom the outside (database behind firewall) and as such can also be used for\nplain HTTP and TLS-encrypted HTTPS.\n\n```php\n$proxy = new Clue\\React\\SshProxy\\SshSocksConnector('alice@example.com');\n\n$connector = new React\\Socket\\Connector([\n    'tcp' =\u003e $proxy,\n    'dns' =\u003e false\n]);\n\n$browser = new React\\Http\\Browser($connector);\n```\n\nSee also the [SSH proxy example](examples/13-client-ssh-proxy.php).\n\n### Unix domain sockets\n\nBy default, this library supports transport over plaintext TCP/IP and secure\nTLS connections for the `http://` and `https://` URL schemes respectively.\nThis library also supports Unix domain sockets (UDS) when explicitly configured.\n\nIn order to use a UDS path, you have to explicitly configure the connector to\noverride the destination URL so that the hostname given in the request URL will\nno longer be used to establish the connection:\n\n```php\n$connector = new React\\Socket\\FixedUriConnector(\n    'unix:///var/run/docker.sock',\n    new React\\Socket\\UnixConnector()\n);\n\n$browser = new React\\Http\\Browser($connector);\n\n$client-\u003eget('http://localhost/info')-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    var_dump($response-\u003egetHeaders(), (string)$response-\u003egetBody());\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nSee also the [Unix Domain Sockets (UDS) example](examples/14-client-unix-domain-sockets.php).\n\n\n## Server Usage\n\n### HttpServer\n\nThe `React\\Http\\HttpServer` class is responsible for handling incoming connections and then\nprocessing each incoming HTTP request.\n\nWhen a complete HTTP request has been received, it will invoke the given\nrequest handler function. This request handler function needs to be passed to\nthe constructor and will be invoked with the respective [request](#server-request)\nobject and expects a [response](#server-response) object in return:\n\n```php\n$http = new React\\Http\\HttpServer(function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n    return React\\Http\\Message\\Response::plaintext(\n        \"Hello World!\\n\"\n    );\n});\n```\n\nEach incoming HTTP request message is always represented by the\n[PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface),\nsee also following [request](#server-request) chapter for more details.\n\nEach outgoing HTTP response message is always represented by the\n[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface),\nsee also following [response](#server-response) chapter for more details.\n\nThis class takes an optional `LoopInterface|null $loop` parameter that can be used to\npass the event loop instance to use for this object. You can use a `null` value\nhere in order to use the [default loop](https://github.com/reactphp/event-loop#loop).\nThis value SHOULD NOT be given unless you're sure you want to explicitly use a\ngiven event loop instance.\n\nIn order to start listening for any incoming connections, the `HttpServer` needs\nto be attached to an instance of\n[`React\\Socket\\ServerInterface`](https://github.com/reactphp/socket#serverinterface)\nthrough the [`listen()`](#listen) method as described in the following\nchapter. In its most simple form, you can attach this to a\n[`React\\Socket\\SocketServer`](https://github.com/reactphp/socket#socketserver)\nin order to start a plaintext HTTP server like this:\n\n```php\n$http = new React\\Http\\HttpServer($handler);\n\n$socket = new React\\Socket\\SocketServer('0.0.0.0:8080');\n$http-\u003elisten($socket);\n```\n\nSee also the [`listen()`](#listen) method and the\n[hello world server example](examples/51-server-hello-world.php)\nfor more details.\n\nBy default, the `HttpServer` buffers and parses the complete incoming HTTP\nrequest in memory. It will invoke the given request handler function when the\ncomplete request headers and request body has been received. This means the\n[request](#server-request) object passed to your request handler function will be\nfully compatible with PSR-7 (http-message). This provides sane defaults for\n80% of the use cases and is the recommended way to use this library unless\nyou're sure you know what you're doing.\n\nOn the other hand, buffering complete HTTP requests in memory until they can\nbe processed by your request handler function means that this class has to\nemploy a number of limits to avoid consuming too much memory. In order to\ntake the more advanced configuration out your hand, it respects setting from\nyour [`php.ini`](https://www.php.net/manual/en/ini.core.php) to apply its\ndefault settings. This is a list of PHP settings this class respects with\ntheir respective default values:\n\n```\nmemory_limit 128M\npost_max_size 8M // capped at 64K\n\nenable_post_data_reading 1\nmax_input_nesting_level 64\nmax_input_vars 1000\n\nfile_uploads 1\nupload_max_filesize 2M\nmax_file_uploads 20\n```\n\nIn particular, the `post_max_size` setting limits how much memory a single\nHTTP request is allowed to consume while buffering its request body. This\nneeds to be limited because the server can process a large number of requests\nconcurrently, so the server may potentially consume a large amount of memory\notherwise. To support higher concurrency by default, this value is capped\nat `64K`. If you assign a higher value, it will only allow `64K` by default.\nIf a request exceeds this limit, its request body will be ignored and it will\nbe processed like a request with no request body at all. See below for\nexplicit configuration to override this setting.\n\nBy default, this class will try to avoid consuming more than half of your\n`memory_limit` for buffering multiple concurrent HTTP requests. As such, with\nthe above default settings of `128M` max, it will try to consume no more than\n`64M` for buffering multiple concurrent HTTP requests. As a consequence, it\nwill limit the concurrency to `1024` HTTP requests with the above defaults.\n\nIt is imperative that you assign reasonable values to your PHP ini settings.\nIt is usually recommended to not support buffering incoming HTTP requests\nwith a large HTTP request body (e.g. large file uploads). If you want to\nincrease this buffer size, you will have to also increase the total memory\nlimit to allow for more concurrent requests (set `memory_limit 512M` or more)\nor explicitly limit concurrency.\n\nIn order to override the above buffering defaults, you can configure the\n`HttpServer` explicitly. You can use the\n[`LimitConcurrentRequestsMiddleware`](#limitconcurrentrequestsmiddleware) and\n[`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) (see below)\nto explicitly configure the total number of requests that can be handled at\nonce like this:\n\n```php\n$http = new React\\Http\\HttpServer(\n    new React\\Http\\Middleware\\StreamingRequestMiddleware(),\n    new React\\Http\\Middleware\\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers\n    new React\\Http\\Middleware\\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request\n    new React\\Http\\Middleware\\RequestBodyParserMiddleware(),\n    $handler\n);\n```\n\nIn this example, we allow processing up to 100 concurrent requests at once\nand each request can buffer up to `2M`. This means you may have to keep a\nmaximum of `200M` of memory for incoming request body buffers. Accordingly,\nyou need to adjust the `memory_limit` ini setting to allow for these buffers\nplus your actual application logic memory requirements (think `512M` or more).\n\n\u003e Internally, this class automatically assigns these middleware handlers\n  automatically when no [`StreamingRequestMiddleware`](#streamingrequestmiddleware)\n  is given. Accordingly, you can use this example to override all default\n  settings to implement custom limits.\n\nAs an alternative to buffering the complete request body in memory, you can\nalso use a streaming approach where only small chunks of data have to be kept\nin memory:\n\n```php\n$http = new React\\Http\\HttpServer(\n    new React\\Http\\Middleware\\StreamingRequestMiddleware(),\n    $handler\n);\n```\n\nIn this case, it will invoke the request handler function once the HTTP\nrequest headers have been received, i.e. before receiving the potentially\nmuch larger HTTP request body. This means the [request](#server-request) passed to\nyour request handler function may not be fully compatible with PSR-7. This is\nspecifically designed to help with more advanced use cases where you want to\nhave full control over consuming the incoming HTTP request body and\nconcurrency settings. See also [streaming incoming request](#streaming-incoming-request)\nbelow for more details.\n\n### listen()\n\nThe `listen(React\\Socket\\ServerInterface $socket): void` method can be used to\nstart listening for HTTP requests on the given socket server instance.\n\nThe given [`React\\Socket\\ServerInterface`](https://github.com/reactphp/socket#serverinterface)\nis responsible for emitting the underlying streaming connections. This\nHTTP server needs to be attached to it in order to process any\nconnections and pase incoming streaming data as incoming HTTP request\nmessages. In its most common form, you can attach this to a\n[`React\\Socket\\SocketServer`](https://github.com/reactphp/socket#socketserver)\nin order to start a plaintext HTTP server like this:\n\n```php\n$http = new React\\Http\\HttpServer($handler);\n\n$socket = new React\\Socket\\SocketServer('0.0.0.0:8080');\n$http-\u003elisten($socket);\n```\n\nSee also [hello world server example](examples/51-server-hello-world.php)\nfor more details.\n\nThis example will start listening for HTTP requests on the alternative\nHTTP port `8080` on all interfaces (publicly). As an alternative, it is\nvery common to use a reverse proxy and let this HTTP server listen on the\nlocalhost (loopback) interface only by using the listen address\n`127.0.0.1:8080` instead. This way, you host your application(s) on the\ndefault HTTP port `80` and only route specific requests to this HTTP\nserver.\n\nLikewise, it's usually recommended to use a reverse proxy setup to accept\nsecure HTTPS requests on default HTTPS port `443` (TLS termination) and\nonly route plaintext requests to this HTTP server. As an alternative, you\ncan also accept secure HTTPS requests with this HTTP server by attaching\nthis to a [`React\\Socket\\SocketServer`](https://github.com/reactphp/socket#socketserver)\nusing a secure TLS listen address, a certificate file and optional\n`passphrase` like this:\n\n```php\n$http = new React\\Http\\HttpServer($handler);\n\n$socket = new React\\Socket\\SocketServer('tls://0.0.0.0:8443', [\n    'tls' =\u003e [\n        'local_cert' =\u003e __DIR__ . '/localhost.pem'\n    ]\n]);\n$http-\u003elisten($socket);\n```\n\nSee also [hello world HTTPS example](examples/61-server-hello-world-https.php)\nfor more details.\n\n### Server Request\n\nAs seen above, the [`HttpServer`](#httpserver) class is responsible for handling\nincoming connections and then processing each incoming HTTP request.\n\nThe request object will be processed once the request has\nbeen received by the client.\nThis request object implements the\n[PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface)\nwhich in turn extends the\n[PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface)\nand will be passed to the callback function like this.\n\n ```php \n$http = new React\\Http\\HttpServer(function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n    $body = \"The method of the request is: \" . $request-\u003egetMethod() . \"\\n\";\n    $body .= \"The requested path is: \" . $request-\u003egetUri()-\u003egetPath() . \"\\n\";\n\n    return React\\Http\\Message\\Response::plaintext(\n        $body\n    );\n});\n```\n\nFor more details about the request object, also check out the documentation of\n[PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface)\nand\n[PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface).\n\n#### Request parameters\n\nThe `getServerParams(): mixed[]` method can be used to\nget server-side parameters similar to the `$_SERVER` variable.\nThe following parameters are currently available:\n\n* `REMOTE_ADDR`\n  The IP address of the request sender\n* `REMOTE_PORT`\n  Port of the request sender\n* `SERVER_ADDR`\n  The IP address of the server\n* `SERVER_PORT`\n  The port of the server\n* `REQUEST_TIME`\n  Unix timestamp when the complete request header has been received,\n  as integer similar to `time()`\n* `REQUEST_TIME_FLOAT`\n  Unix timestamp when the complete request header has been received,\n  as float similar to `microtime(true)`\n* `HTTPS`\n  Set to 'on' if the request used HTTPS, otherwise it won't be set\n\n```php \n$http = new React\\Http\\HttpServer(function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n    $body = \"Your IP is: \" . $request-\u003egetServerParams()['REMOTE_ADDR'] . \"\\n\";\n\n    return React\\Http\\Message\\Response::plaintext(\n        $body\n    );\n});\n```\n\nSee also [whatsmyip server example](examples/53-server-whatsmyip.php).\n\n\u003e Advanced: Note that address parameters will not be set if you're listening on\n  a Unix domain socket (UDS) path as this protocol lacks the concept of\n  host/port.\n\n#### Query parameters\n\nThe `getQueryParams(): array` method can be used to get the query parameters\nsimiliar to the `$_GET` variable.\n\n```php\n$http = new React\\Http\\HttpServer(function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n    $queryParams = $request-\u003egetQueryParams();\n\n    $body = 'The query parameter \"foo\" is not set. Click the following link ';\n    $body .= '\u003ca href=\"/?foo=bar\"\u003eto use query parameter in your request\u003c/a\u003e';\n\n    if (isset($queryParams['foo'])) {\n        $body = 'The value of \"foo\" is: ' . htmlspecialchars($queryParams['foo']);\n    }\n\n    return React\\Http\\Message\\Response::html(\n        $body\n    );\n});\n```\n\nThe response in the above example will return a response body with a link.\nThe URL contains the query parameter `foo` with the value `bar`.\nUse [`htmlentities`](https://www.php.net/manual/en/function.htmlentities.php)\nlike in this example to prevent\n[Cross-Site Scripting (abbreviated as XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting).\n\nSee also [server query parameters example](examples/54-server-query-parameter.php).\n\n#### Request body\n\nBy default, the [`Server`](#httpserver) will buffer and parse the full request body\nin memory. This means the given request object includes the parsed request body\nand any file uploads.\n\n\u003e As an alternative to the default buffering logic, you can also use the\n  [`StreamingRequestMiddleware`](#streamingrequestmiddleware). Jump to the next\n  chapter to learn more about how to process a\n  [streaming incoming request](#streaming-incoming-request).\n\nAs stated above, each incoming HTTP request is always represented by the\n[PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface).\nThis interface provides several methods that are useful when working with the\nincoming request body as described below.\n\nThe `getParsedBody(): null|array|object` method can be used to\nget the parsed request body, similar to\n[PHP's `$_POST` variable](https://www.php.net/manual/en/reserved.variables.post.php).\nThis method may return a (possibly nested) array structure with all body\nparameters or a `null` value if the request body could not be parsed.\nBy default, this method will only return parsed data for requests using\n`Content-Type: application/x-www-form-urlencoded` or `Content-Type: multipart/form-data`\nrequest headers (commonly used for `POST` requests for HTML form submission data).\n\n```php\n$http = new React\\Http\\HttpServer(function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n    $name = $request-\u003egetParsedBody()['name'] ?? 'anonymous';\n\n    return React\\Http\\Message\\Response::plaintext(\n        \"Hello $name!\\n\"\n    );\n});\n```\n\nSee also [form upload example](examples/62-server-form-upload.php) for more details.\n\nThe `getBody(): StreamInterface` method can be used to\nget the raw data from this request body, similar to\n[PHP's `php://input` stream](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.input).\nThis method returns an instance of the request body represented by the\n[PSR-7 `StreamInterface`](https://www.php-fig.org/psr/psr-7/#34-psrhttpmessagestreaminterface).\nThis is particularly useful when using a custom request body that will not\notherwise be parsed by default, such as a JSON (`Content-Type: application/json`) or\nan XML (`Content-Type: application/xml`) request body (which is commonly used for\n`POST`, `PUT` or `PATCH` requests in JSON-based or RESTful/RESTish APIs).\n\n```php\n$http = new React\\Http\\HttpServer(function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n    $data = json_decode((string)$request-\u003egetBody());\n    $name = $data-\u003ename ?? 'anonymous';\n\n    return React\\Http\\Message\\Response::json(\n        ['message' =\u003e \"Hello $name!\"]\n    );\n});\n```\n\nSee also [JSON API server example](examples/59-server-json-api.php) for more details.\n\nThe `getUploadedFiles(): array` method can be used to\nget the uploaded files in this request, similar to\n[PHP's `$_FILES` variable](https://www.php.net/manual/en/reserved.variables.files.php).\nThis method returns a (possibly nested) array structure with all file uploads, each represented by the\n[PSR-7 `UploadedFileInterface`](https://www.php-fig.org/psr/psr-7/#36-psrhttpmessageuploadedfileinterface).\nThis array will only be filled when using the `Content-Type: multipart/form-data`\nrequest header (commonly used for `POST` requests for HTML file uploads).\n\n```php\n$http = new React\\Http\\HttpServer(function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n    $files = $request-\u003egetUploadedFiles();\n    $name = isset($files['avatar']) ? $files['avatar']-\u003egetClientFilename() : 'nothing';\n\n    return React\\Http\\Message\\Response::plaintext(\n        \"Uploaded $name\\n\"\n    );\n});\n```\n\nSee also [form upload server example](examples/62-server-form-upload.php) for more details.\n\nThe `getSize(): ?int` method can be used to\nget the size of the request body, similar to PHP's `$_SERVER['CONTENT_LENGTH']` variable.\nThis method returns the complete size of the request body measured in number\nof bytes as defined by the message boundaries.\nThis value may be `0` if the request message does not contain a request body\n(such as a simple `GET` request).\nThis method operates on the buffered request body, i.e. the request body size\nis always known, even when the request does not specify a `Content-Length` request\nheader or when using `Transfer-Encoding: chunked` for HTTP/1.1 requests.\n\n\u003e Note: The `HttpServer` automatically takes care of handling requests with the\n  additional `Expect: 100-continue` request header. When HTTP/1.1 clients want to\n  send a bigger request body, they MAY send only the request headers with an\n  additional `Expect: 100-continue` request header and wait before sending the actual\n  (large) message body. In this case the server will automatically send an\n  intermediary `HTTP/1.1 100 Continue` response to the client. This ensures you\n  will receive the request body without a delay as expected.\n\n#### Streaming incoming request\n\nIf you're using the advanced [`StreamingRequestMiddleware`](#streamingrequestmiddleware),\nthe request object will be processed once the request headers have been received.\nThis means that this happens irrespective of (i.e. *before*) receiving the\n(potentially much larger) request body.\n\n\u003e Note that this is non-standard behavior considered advanced usage. Jump to the\n  previous chapter to learn more about how to process a buffered [request body](#request-body).\n\nWhile this may be uncommon in the PHP ecosystem, this is actually a very powerful\napproach that gives you several advantages not otherwise possible:\n\n* React to requests *before* receiving a large request body,\n  such as rejecting an unauthenticated request or one that exceeds allowed\n  message lengths (file uploads).\n* Start processing parts of the request body before the remainder of the request\n  body arrives or if the sender is slowly streaming data.\n* Process a large request body without having to buffer anything in memory,\n  such as accepting a huge file upload or possibly unlimited request body stream.\n\nThe `getBody(): StreamInterface` method can be used to\naccess the request body stream.\nIn the streaming mode, this method returns a stream instance that implements both the\n[PSR-7 `StreamInterface`](https://www.php-fig.org/psr/psr-7/#34-psrhttpmessagestreaminterface)\nand the [ReactPHP `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface).\nHowever, most of the\n[PSR-7 `StreamInterface`](https://www.php-fig.org/psr/psr-7/#34-psrhttpmessagestreaminterface)\nmethods have been designed under the assumption of being in control of a\nsynchronous request body.\nGiven that this does not apply to this server, the following\n[PSR-7 `StreamInterface`](https://www.php-fig.org/psr/psr-7/#34-psrhttpmessagestreaminterface)\nmethods are not used and SHOULD NOT be called:\n`tell()`, `eof()`, `seek()`, `rewind()`, `write()` and `read()`.\nIf this is an issue for your use case and/or you want to access uploaded files,\nit's highly recommended to use a buffered [request body](#request-body) or use the\n[`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) instead.\nThe [ReactPHP `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface)\ngives you access to the incoming request body as the individual chunks arrive:\n\n```php\n$http = new React\\Http\\HttpServer(\n    new React\\Http\\Middleware\\StreamingRequestMiddleware(),\n    function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n        $body = $request-\u003egetBody();\n        assert($body instanceof Psr\\Http\\Message\\StreamInterface);\n        assert($body instanceof React\\Stream\\ReadableStreamInterface);\n\n        return new React\\Promise\\Promise(function ($resolve, $reject) use ($body) {\n            $bytes = 0;\n            $body-\u003eon('data', function ($data) use (\u0026$bytes) {\n                $bytes += strlen($data);\n            });\n\n            $body-\u003eon('end', function () use ($resolve, \u0026$bytes){\n                $resolve(React\\Http\\Message\\Response::plaintext(\n                    \"Received $bytes bytes\\n\"\n                ));\n            });\n\n            // an error occures e.g. on invalid chunked encoded data or an unexpected 'end' event\n            $body-\u003eon('error', function (Exception $e) use ($resolve, \u0026$bytes) {\n                $resolve(React\\Http\\Message\\Response::plaintext(\n                    \"Encountered error after $bytes bytes: {$e-\u003egetMessage()}\\n\"\n                )-\u003ewithStatus(React\\Http\\Message\\Response::STATUS_BAD_REQUEST));\n            });\n        });\n    }\n);\n```\n\nThe above example simply counts the number of bytes received in the request body.\nThis can be used as a skeleton for buffering or processing the request body.\n\nSee also [streaming request server example](examples/63-server-streaming-request.php) for more details.\n\nThe `data` event will be emitted whenever new data is available on the request\nbody stream.\nThe server also automatically takes care of decoding any incoming requests using\n`Transfer-Encoding: chunked` and will only emit the actual payload as data.\n\nThe `end` event will be emitted when the request body stream terminates\nsuccessfully, i.e. it was read until its expected end.\n\nThe `error` event will be emitted in case the request stream contains invalid\ndata for `Transfer-Encoding: chunked` or when the connection closes before\nthe complete request stream has been received.\nThe server will automatically stop reading from the connection and discard all\nincoming data instead of closing it.\nA response message can still be sent (unless the connection is already closed).\n\nA `close` event will be emitted after an `error` or `end` event.\n\nFor more details about the request body stream, check out the documentation of\n[ReactPHP `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface).\n\nThe `getSize(): ?int` method can be used to\nget the size of the request body, similar to PHP's `$_SERVER['CONTENT_LENGTH']` variable.\nThis method returns the complete size of the request body measured in number\nof bytes as defined by the message boundaries.\nThis value may be `0` if the request message does not contain a request body\n(such as a simple `GET` request).\nThis method operates on the streaming request body, i.e. the request body size\nmay be unknown (`null`) when using `Transfer-Encoding: chunked` for HTTP/1.1 requests.\n\n```php \n$http = new React\\Http\\HttpServer(\n    new React\\Http\\Middleware\\StreamingRequestMiddleware(),\n    function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n        $size = $request-\u003egetBody()-\u003egetSize();\n        if ($size === null) {\n            $body = \"The request does not contain an explicit length. \";\n            $body .= \"This example does not accept chunked transfer encoding.\\n\";\n\n            return React\\Http\\Message\\Response::plaintext(\n                $body\n            )-\u003ewithStatus(React\\Http\\Message\\Response::STATUS_LENGTH_REQUIRED);\n        }\n\n        return React\\Http\\Message\\Response::plaintext(\n            \"Request body size: \" . $size . \" bytes\\n\"\n        );\n    }\n);\n```\n\n\u003e Note: The `HttpServer` automatically takes care of handling requests with the\n  additional `Expect: 100-continue` request header. When HTTP/1.1 clients want to\n  send a bigger request body, they MAY send only the request headers with an\n  additional `Expect: 100-continue` request header and wait before sending the actual\n  (large) message body. In this case the server will automatically send an\n  intermediary `HTTP/1.1 100 Continue` response to the client. This ensures you\n  will receive the streaming request body without a delay as expected.\n\n#### Request method\n\nNote that the server supports *any* request method (including custom and non-\nstandard ones) and all request-target formats defined in the HTTP specs for each\nrespective method, including *normal* `origin-form` requests as well as\nproxy requests in `absolute-form` and `authority-form`.\nThe `getUri(): UriInterface` method can be used to get the effective request\nURI which provides you access to individiual URI components.\nNote that (depending on the given `request-target`) certain URI components may\nor may not be present, for example the `getPath(): string` method will return\nan empty string for requests in `asterisk-form` or `authority-form`.\nIts `getHost(): string` method will return the host as determined by the\neffective request URI, which defaults to the local socket address if an HTTP/1.0\nclient did not specify one (i.e. no `Host` header).\nIts `getScheme(): string` method will return `http` or `https` depending\non whether the request was made over a secure TLS connection to the target host.\n\nThe `Host` header value will be sanitized to match this host component plus the\nport component only if it is non-standard for this URI scheme.\n\nYou can use `getMethod(): string` and `getRequestTarget(): string` to\ncheck this is an accepted request and may want to reject other requests with\nan appropriate error code, such as `400` (Bad Request) or `405` (Method Not\nAllowed).\n\n\u003e The `CONNECT` method is useful in a tunneling setup (HTTPS proxy) and not\n  something most HTTP servers would want to care about.\n  Note that if you want to handle this method, the client MAY send a different\n  request-target than the `Host` header value (such as removing default ports)\n  and the request-target MUST take precendence when forwarding.\n\n#### Cookie parameters\n\nThe `getCookieParams(): string[]` method can be used to\nget all cookies sent with the current request.\n\n```php \n$http = new React\\Http\\HttpServer(function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n    $key = 'greeting';\n\n    if (isset($request-\u003egetCookieParams()[$key])) {\n        $body = \"Your cookie value is: \" . $request-\u003egetCookieParams()[$key] . \"\\n\";\n\n        return React\\Http\\Message\\Response::plaintext(\n            $body\n        );\n    }\n\n    return React\\Http\\Message\\Response::plaintext(\n        \"Your cookie has been set.\\n\"\n    )-\u003ewithHeader('Set-Cookie', $key . '=' . urlencode('Hello world!'));\n});\n```\n\nThe above example will try to set a cookie on first access and\nwill try to print the cookie value on all subsequent tries.\nNote how the example uses the `urlencode()` function to encode\nnon-alphanumeric characters.\nThis encoding is also used internally when decoding the name and value of cookies\n(which is in line with other implementations, such as PHP's cookie functions).\n\nSee also [cookie server example](examples/55-server-cookie-handling.php) for more details.\n\n#### Invalid request\n\nThe `HttpServer` class supports both HTTP/1.1 and HTTP/1.0 request messages.\nIf a client sends an invalid request message, uses an invalid HTTP\nprotocol version or sends an invalid `Transfer-Encoding` request header value,\nthe server will automatically send a `400` (Bad Request) HTTP error response\nto the client and close the connection.\nOn top of this, it will emit an `error` event that can be used for logging\npurposes like this:\n\n```php\n$http-\u003eon('error', function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nNote that the server will also emit an `error` event if you do not return a\nvalid response object from your request handler function. See also\n[invalid response](#invalid-response) for more details.\n\n### Server Response\n\nThe callback function passed to the constructor of the [`HttpServer`](#httpserver) is\nresponsible for processing the request and returning a response, which will be\ndelivered to the client.\n\nThis function MUST return an instance implementing\n[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface)\nobject or a \n[ReactPHP Promise](https://github.com/reactphp/promise)\nwhich resolves with a [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) object.\n\nThis projects ships a [`Response` class](#response) which implements the\n[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface).\nIn its most simple form, you can use it like this:\n\n```php \n$http = new React\\Http\\HttpServer(function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n    return React\\Http\\Message\\Response::plaintext(\n        \"Hello World!\\n\"\n    );\n});\n```\n\nWe use this [`Response` class](#response) throughout our project examples, but\nfeel free to use any other implementation of the\n[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface).\nSee also the [`Response` class](#response) for more details.\n\n#### Deferred response\n\nThe example above returns the response directly, because it needs\nno time to be processed.\nUsing a database, the file system or long calculations \n(in fact every action that will take \u003e=1ms) to create your\nresponse, will slow down the server.\nTo prevent this you SHOULD use a\n[ReactPHP Promise](https://github.com/reactphp/promise#reactpromise).\nThis example shows how such a long-term action could look like:\n\n```php\n$http = new React\\Http\\HttpServer(function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n    $promise = new Promise(function ($resolve, $reject) {\n        Loop::addTimer(1.5, function() use ($resolve) {\n            $resolve();\n        });\n    });\n\n    return $promise-\u003ethen(function () { \n        return React\\Http\\Message\\Response::plaintext(\n            \"Hello World!\"\n        );\n    });\n});\n```\n\nThe above example will create a response after 1.5 second.\nThis example shows that you need a promise,\nif your response needs time to created.\nThe `ReactPHP Promise` will resolve in a `Response` object when the request\nbody ends.\nIf the client closes the connection while the promise is still pending, the\npromise will automatically be cancelled.\nThe promise cancellation handler can be used to clean up any pending resources\nallocated in this case (if applicable).\nIf a promise is resolved after the client closes, it will simply be ignored.\n\n#### Streaming outgoing response\n\nThe `Response` class in this project supports to add an instance which implements the\n[ReactPHP `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface)\nfor the response body.\nSo you are able stream data directly into the response body.\nNote that other implementations of the\n[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface)\nmay only support strings.\n\n```php\n$http = new React\\Http\\HttpServer(function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n    $stream = new ThroughStream();\n\n    // send some data every once in a while with periodic timer\n    $timer = Loop::addPeriodicTimer(0.5, function () use ($stream) {\n        $stream-\u003ewrite(microtime(true) . PHP_EOL);\n    });\n\n    // end stream after a few seconds\n    $timeout = Loop::addTimer(5.0, function() use ($stream, $timer) {\n        Loop::cancelTimer($timer);\n        $stream-\u003eend();\n    });\n\n    // stop timer if stream is closed (such as when connection is closed)\n    $stream-\u003eon('close', function () use ($timer, $timeout) {\n        Loop::cancelTimer($timer);\n        Loop::cancelTimer($timeout);\n    });\n\n    return new React\\Http\\Message\\Response(\n        React\\Http\\Message\\Response::STATUS_OK,\n        [\n            'Content-Type' =\u003e 'text/plain'\n        ],\n        $stream\n    );\n});\n```\n\nThe above example will emit every 0.5 seconds the current Unix timestamp \nwith microseconds as float to the client and will end after 5 seconds.\nThis is just a example you could use of the streaming,\nyou could also send a big amount of data via little chunks \nor use it for body data that needs to calculated.\n\nIf the request handler resolves with a response stream that is already closed,\nit will simply send an empty response body.\nIf the client closes the connection while the stream is still open, the\nresponse stream will automatically be closed.\nIf a promise is resolved with a streaming body after the client closes, the\nresponse stream will automatically be closed.\nThe `close` event can be used to clean up any pending resources allocated\nin this case (if applicable).\n\n\u003e Note that special care has to be taken if you use a body stream instance that\n  implements ReactPHP's\n  [`DuplexStreamInterface`](https://github.com/reactphp/stream#duplexstreaminterface)\n  (such as the `ThroughStream` in the above example).\n\u003e\n\u003e For *most* cases, this will simply only consume its readable side and forward\n  (send) any data that is emitted by the stream, thus entirely ignoring the\n  writable side of the stream.\n  If however this is either a `101` (Switching Protocols) response or a `2xx`\n  (Successful) response to a `CONNECT` method, it will also *write* data to the\n  writable side of the stream.\n  This can be avoided by either rejecting all requests with the `CONNECT`\n  method (which is what most *normal* origin HTTP servers would likely do) or\n  or ensuring that only ever an instance of\n  [ReactPHP's `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface)\n  is used.\n\u003e\n\u003e The `101` (Switching Protocols) response code is useful for the more advanced\n  `Upgrade` requests, such as upgrading to the WebSocket protocol or\n  implementing custom protocol logic that is out of scope of the HTTP specs and\n  this HTTP library.\n  If you want to handle the `Upgrade: WebSocket` header, you will likely want\n  to look into using [Ratchet](http://socketo.me/) instead.\n  If you want to handle a custom protocol, you will likely want to look into the\n  [HTTP specs](https://tools.ietf.org/html/rfc7230#section-6.7) and also see\n  [examples #81 and #82](examples/) for more details.\n  In particular, the `101` (Switching Protocols) response code MUST NOT be used\n  unless you send an `Upgrade` response header value that is also present in\n  the corresponding HTTP/1.1 `Upgrade` request header value.\n  The server automatically takes care of sending a `Connection: upgrade`\n  header value in this case, so you don't have to.\n\u003e\n\u003e The `CONNECT` method is useful in a tunneling setup (HTTPS proxy) and not\n  something most origin HTTP servers would want to care about.\n  The HTTP specs define an opaque \"tunneling mode\" for this method and make no\n  use of the message body.\n  For consistency reasons, this library uses a `DuplexStreamInterface` in the\n  response body for tunneled application data.\n  This implies that that a `2xx` (Successful) response to a `CONNECT` request\n  can in fact use a streaming response body for the tunneled application data,\n  so that any raw data the client sends over the connection will be piped\n  through the writable stream for consumption.\n  Note that while the HTTP specs make no use of the request body for `CONNECT`\n  requests, one may still be present. Normal request body processing applies\n  here and the connection will only turn to \"tunneling mode\" after the request\n  body has been processed (which should be empty in most cases).\n  See also [HTTP CONNECT server example](examples/72-server-http-connect-proxy.php) for more details.\n\n#### Response length\n\nIf the response body size is known, a `Content-Length` response header will be\nadded automatically. This is the most common use case, for example when using\na `string` response body like this:\n\n```php \n$http = new React\\Http\\HttpServer(function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n    return React\\Http\\Message\\Response::plaintext(\n        \"Hello World!\\n\"\n    );\n});\n```\n\nIf the response body size is unknown, a `Content-Length` response header can not\nbe added automatically. When using a [streaming outgoing response](#streaming-outgoing-response)\nwithout an explicit `Content-Length` response header, outgoing HTTP/1.1 response\nmessages will automatically use `Transfer-Encoding: chunked` while legacy HTTP/1.0\nresponse messages will contain the plain response body. If you know the length\nof your streaming response body, you MAY want to specify it explicitly like this:\n\n```php\n$http = new React\\Http\\HttpServer(function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n    $stream = new ThroughStream();\n\n    Loop::addTimer(2.0, function () use ($stream) {\n        $stream-\u003eend(\"Hello World!\\n\");\n    });\n\n    return new React\\Http\\Message\\Response(\n        React\\Http\\Message\\Response::STATUS_OK,\n        [\n            'Content-Length' =\u003e '13',\n            'Content-Type' =\u003e 'text/plain',\n        ],\n        $stream\n    );\n});\n```\n\nAny response to a `HEAD` request and any response with a `1xx` (Informational),\n`204` (No Content) or `304` (Not Modified) status code will *not* include a\nmessage body as per the HTTP specs.\nThis means that your callback does not have to take special care of this and any\nresponse body will simply be ignored.\n\nSimilarly, any `2xx` (Successful) response to a `CONNECT` request, any response\nwith a `1xx` (Informational) or `204` (No Content) status code will *not*\ninclude a `Content-Length` or `Transfer-Encoding` header as these do not apply\nto these messages.\nNote that a response to a `HEAD` request and any response with a `304` (Not\nModified) status code MAY include these headers even though\nthe message does not contain a response body, because these header would apply\nto the message if the same request would have used an (unconditional) `GET`.\n\n#### Invalid response\n\nAs stated above, each outgoing HTTP response is always represented by the\n[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface).\nIf your request handler function returns an invalid value or throws an\nunhandled `Exception` or `Throwable`, the server will automatically send a `500`\n(Internal Server Error) HTTP error response to the client.\nOn top of this, it will emit an `error` event that can be used for logging\npurposes like this:\n\n```php\n$http-\u003eon('error', function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n    if ($e-\u003egetPrevious() !== null) {\n        echo 'Previous: ' . $e-\u003egetPrevious()-\u003egetMessage() . PHP_EOL;\n    }\n});\n```\n\nNote that the server will also emit an `error` event if the client sends an\ninvalid HTTP request that never reaches your request handler function. See\nalso [invalid request](#invalid-request) for more details.\nAdditionally, a [streaming incoming request](#streaming-incoming-request) body\ncan also emit an `error` event on the request body.\n\nThe server will only send a very generic `500` (Interval Server Error) HTTP\nerror response without any further details to the client if an unhandled\nerror occurs. While we understand this might make initial debugging harder,\nit also means that the server does not leak any application details or stack\ntraces to the outside by default. It is usually recommended to catch any\n`Exception` or `Throwable` within your request handler function or alternatively\nuse a [`middleware`](#middleware) to avoid this generic error handling and\ncreate your own HTTP response message instead.\n\n#### Default response headers\n\nWhen a response is returned from the request handler function, it will be\nprocessed by the [`HttpServer`](#httpserver) and then sent back to the client.\n\nA `Server: ReactPHP/1` response header will be added automatically. You can add\na custom `Server` response header like this:\n\n```php\n$http = new React\\Http\\HttpServer(function (ServerRequestInterface $request) {\n    return new React\\Http\\Message\\Response(\n        React\\Http\\Message\\Response::STATUS_OK,\n        [\n            'Server' =\u003e 'PHP/3'\n        ]\n    );\n});\n```\n\nIf you do not want to send this `Sever` response header at all (such as when you\ndon't want to expose the underlying server software), you can use an empty\nstring value like this:\n\n```php\n$http = new React\\Http\\HttpServer(function (ServerRequestInterface $request) {\n    return new React\\Http\\Message\\Response(\n        React\\Http\\Message\\Response::STATUS_OK,\n        [\n            'Server' =\u003e ''\n        ]\n    );\n});\n```\n\nA `Date` response header will be added automatically with the current system\ndate and time if none is given. You can add a custom `Date` response header\nlike this:\n\n```php\n$http = new React\\Http\\HttpServer(function (ServerRequestInterface $request) {\n    return new React\\Http\\Message\\Response(\n        React\\Http\\Message\\Response::STATUS_OK,\n        [\n            'Date' =\u003e gmdate('D, d M Y H:i:s \\G\\M\\T')\n        ]\n    );\n});\n```\n\nIf you do not want to send this `Date` response header at all (such as when you\ndon't have an appropriate clock to rely on), you can use an empty string value\nlike this:\n\n```php\n$http = new React\\Http\\HttpServer(function (ServerRequestInterface $request) {\n    return new React\\Http\\Message\\Response(\n        React\\Http\\Message\\Response::STATUS_OK,\n        [\n            'Date' =\u003e ''\n        ]\n    );\n});\n```\n\nThe `HttpServer` class will automatically add the protocol version of the request,\nso you don't have to. For instance, if the client sends the request using the\nHTTP/1.1 protocol version, the response message will also use the same protocol\nversion, no matter what version is returned from the request handler function.\n\nThe server supports persistent connections. An appropriate `Connection: keep-alive`\nor `Connection: close` response header will be added automatically, respecting the\nmatching request header value and HTTP default header values. The server is\nresponsible for handling the `Connection` response header, so you SHOULD NOT pass\nthis response header yourself, unless you explicitly want to override the user's\nchoice with a `Connection: close` response header.\n\n### Middleware\n\nAs documented above, the [`HttpServer`](#httpserver) accepts a single request handler\nargument that is responsible for processing an incoming HTTP request and then\ncreating and returning an outgoing HTTP response.\n\nMany common use cases involve validating, processing, manipulating the incoming\nHTTP request before passing it to the final business logic request handler.\nAs such, this project supports the concept of middleware request handlers.\n\n#### Custom middleware\n\nA middleware request handler is expected to adhere the following rules:\n\n* It is a valid `callable`.\n* It accepts an instance implementing\n  [PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface)\n  as first argument and an optional `callable` as second argument.\n* It returns either:\n  * An instance implementing\n    [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface)\n    for direct consumption.\n  * Any promise which can be consumed by\n    [`Promise\\resolve()`](https://reactphp.org/promise/#resolve) resolving to a\n    [PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface)\n    for deferred consumption.\n  * It MAY throw an `Exception` (or return a rejected promise) in order to\n    signal an error condition and abort the chain.\n* It calls `$next($request)` to continue processing the next middleware\n  request handler or returns explicitly without calling `$next` to\n  abort the chain.\n  * The `$next` request handler (recursively) invokes the next request\n    handler from the chain with the same logic as above and returns (or throws)\n    as above.\n  * The `$request` may be modified prior to calling `$next($request)` to\n    change the incoming request the next middleware operates on.\n  * The `$next` return value may be consumed to modify the outgoing response.\n  * The `$next` request handler MAY be called more than once if you want to\n    implement custom \"retry\" logic etc.\n\nNote that this very simple definition allows you to use either anonymous\nfunctions or any classes that use the magic `__invoke()` method.\nThis allows you to easily create custom middleware request handlers on the fly\nor use a class based approach to ease using existing middleware implementations.\n\nWhile this project does provide the means to *use* middleware implementations,\nit does not aim to *define* how middleware implementations should look like.\nWe realize that there's a vivid ecosystem of middleware implementations and\nongoing effort to standardize interfaces between these with\n[PSR-15](https://www.php-fig.org/psr/psr-15/) (HTTP Server Request Handlers)\nand support this goal.\nAs such, this project only bundles a few middleware implementations that are\nrequired to match PHP's request behavior (see below) and otherwise actively\nencourages [Third-Party Middleware](#third-party-middleware) implementations.\n\nIn order to use middleware request handlers, simply pass a list of all\ncallables as defined above to the [`HttpServer`](#httpserver).\nThe following example adds a middleware request handler that adds the current time to the request as a \nheader (`Request-Time`) and a final request handler that always returns a `200 OK` status code without a body: \n\n```php\n$http = new React\\Http\\HttpServer(\n    function (Psr\\Http\\Message\\ServerRequestInterface $request, callable $next) {\n        $request = $request-\u003ewithHeader('Request-Time', time());\n        return $next($request);\n    },\n    function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n        return new React\\Http\\Message\\Response(React\\Http\\Message\\Response::STATUS_OK);\n    }\n);\n```\n\n\u003e Note how the middleware request handler and the final request handler have a\n  very simple (and similar) interface. The only difference is that the final\n  request handler does not receive a `$next` handler.\n\nSimilarly, you can use the result of the `$next` middleware request handler\nfunction to modify the outgoing response.\nNote that as per the above documentation, the `$next` middleware request handler may return a\n[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface)\ndirectly or one wrapped in a promise for deferred resolution.\nIn order to simplify handling both paths, you can simply wrap this in a\n[`Promise\\resolve()`](https://reactphp.org/promise/#resolve) call like this:\n\n```php\n$http = new React\\Http\\HttpServer(\n    function (Psr\\Http\\Message\\ServerRequestInterface $request, callable $next) {\n        $promise = React\\Promise\\resolve($next($request));\n        return $promise-\u003ethen(function (ResponseInterface $response) {\n            return $response-\u003ewithHeader('Content-Type', 'text/html');\n        });\n    },\n    function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n        return new React\\Http\\Message\\Response(React\\Http\\Message\\Response::STATUS_OK);\n    }\n);\n```\n\nNote that the `$next` middleware request handler may also throw an\n`Exception` (or return a rejected promise) as described above.\nThe previous example does not catch any exceptions and would thus signal an\nerror condition to the `HttpServer`.\nAlternatively, you can also catch any `Exception` to implement custom error\nhandling logic (or logging etc.) by wrapping this in a\n[`Promise`](https://reactphp.org/promise/#promise) like this:\n\n```php\n$http = new React\\Http\\HttpServer(\n    function (Psr\\Http\\Message\\ServerRequestInterface $request, callable $next) {\n        $promise = new React\\Promise\\Promise(function ($resolve) use ($next, $request) {\n            $resolve($next($request));\n        });\n        return $promise-\u003ethen(null, function (Exception $e) {\n            return React\\Http\\Message\\Response::plaintext(\n                'Internal error: ' . $e-\u003egetMessage() . \"\\n\"\n            )-\u003ewithStatus(React\\Http\\Message\\Response::STATUS_INTERNAL_SERVER_ERROR);\n        });\n    },\n    function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n        if (mt_rand(0, 1) === 1) {\n            throw new RuntimeException('Database error');\n        }\n        return new React\\Http\\Message\\Response(React\\Http\\Message\\Response::STATUS_OK);\n    }\n);\n```\n\n#### Third-Party Middleware\n\nWhile this project does provide the means to *use* middleware implementations\n(see above), it does not aim to *define* how middleware implementations should\nlook like. We realize that there's a vivid ecosystem of middleware\nimplementations and ongoing effort to standardize interfaces between these with\n[PSR-15](https://www.php-fig.org/psr/psr-15/) (HTTP Server Request Handlers)\nand support this goal.\nAs such, this project only bundles a few middleware implementations that are\nrequired to match PHP's request behavior (see\n[middleware implementations](#reacthttpmiddleware)) and otherwise actively\nencourages third-party middleware implementations.\n\nWhile we would love to support PSR-15 directly in `react/http`, we understand\nthat this interface does not specifically target async APIs and as such does\nnot take advantage of promises for [deferred responses](#deferred-response).\nThe gist of this is that where PSR-15 enforces a\n[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface)\nreturn value, we also accept a `PromiseInterface\u003cResponseInterface\u003e`.\nAs such, we suggest using the external\n[PSR-15 middleware adapter](https://github.com/friends-of-reactphp/http-middleware-psr15-adapter)\nthat uses on the fly monkey patching of these return values which makes using\nmost PSR-15 middleware possible with this package without any changes required.\n\nOther than that, you can also use the above [middleware definition](#middleware)\nto create custom middleware. A non-exhaustive list of third-party middleware can\nbe found at the [middleware wiki](https://github.com/reactphp/reactphp/wiki/Users#http-middleware).\nIf you build or know a custom middleware, make sure to let the world know and\nfeel free to add it to this list.\n\n## API\n\n### Browser\n\nThe `React\\Http\\Browser` is responsible for sending HTTP requests to your HTTP server\nand keeps track of pending incoming HTTP responses.\n\n```php\n$browser = new React\\Http\\Browser();\n```\n\nThis class takes two optional arguments for more advanced usage:\n\n```php\n$browser = new React\\Http\\Browser(?ConnectorInterface $connector = null, ?LoopInterface $loop = null);\n```\n\nIf you need custom connector settings (DNS resolution, TLS parameters, timeouts,\nproxy servers etc.), you can explicitly pass a custom instance of the\n[`ConnectorInterface`](https://github.com/reactphp/socket#connectorinterface):\n\n```php\n$connector = new React\\Socket\\Connector([\n    'dns' =\u003e '127.0.0.1',\n    'tcp' =\u003e [\n        'bindto' =\u003e '192.168.10.1:0'\n    ],\n    'tls' =\u003e [\n        'verify_peer' =\u003e false,\n        'verify_peer_name' =\u003e false\n    ]\n]);\n\n$browser = new React\\Http\\Browser($connector);\n```\n\nThis class takes an optional `LoopInterface|null $loop` parameter that can be used to\npass the event loop instance to use for this object. You can use a `null` value\nhere in order to use the [default loop](https://github.com/reactphp/event-loop#loop).\nThis value SHOULD NOT be given unless you're sure you want to explicitly use a\ngiven event loop instance.\n\n\u003e Note that the browser class is final and shouldn't be extended, it is likely to be marked final in a future release.\n\n#### get()\n\nThe `get(string $url, array $headers = []): PromiseInterface\u003cResponseInterface\u003e` method can be used to\nsend an HTTP GET request.\n\n```php\n$browser-\u003eget($url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    var_dump((string)$response-\u003egetBody());\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nSee also [GET request client example](examples/01-client-get-request.php).\n\n#### post()\n\nThe `post(string $url, array $headers = [], string|ReadableStreamInterface $body = ''): PromiseInterface\u003cResponseInterface\u003e` method can be used to\nsend an HTTP POST request.\n\n```php\n$browser-\u003epost(\n    $url,\n    [\n        'Content-Type' =\u003e 'application/json'\n    ],\n    json_encode($data)\n)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    var_dump(json_decode((string)$response-\u003egetBody()));\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nSee also [POST JSON client example](examples/04-client-post-json.php).\n\nThis method is also commonly used to submit HTML form data:\n\n```php\n$data = [\n    'user' =\u003e 'Alice',\n    'password' =\u003e 'secret'\n];\n\n$browser-\u003epost(\n    $url,\n    [\n        'Content-Type' =\u003e 'application/x-www-form-urlencoded'\n    ],\n    http_build_query($data)\n);\n```\n\nThis method will automatically add a matching `Content-Length` request\nheader if the outgoing request body is a `string`. If you're using a\nstreaming request body (`ReadableStreamInterface`), it will default to\nusing `Transfer-Encoding: chunked` or you have to explicitly pass in a\nmatching `Content-Length` request header like so:\n\n```php\n$body = new React\\Stream\\ThroughStream();\nLoop::addTimer(1.0, function () use ($body) {\n    $body-\u003eend(\"hello world\");\n});\n\n$browser-\u003epost($url, ['Content-Length' =\u003e '11'), $body);\n```\n\n#### head()\n\nThe `head(string $url, array $headers = []): PromiseInterface\u003cResponseInterface\u003e` method can be used to\nsend an HTTP HEAD request.\n\n```php\n$browser-\u003ehead($url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    var_dump($response-\u003egetHeaders());\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\n#### patch()\n\nThe `patch(string $url, array $headers = [], string|ReadableStreamInterface $body = ''): PromiseInterface\u003cResponseInterface\u003e` method can be used to\nsend an HTTP PATCH request.\n\n```php\n$browser-\u003epatch(\n    $url,\n    [\n        'Content-Type' =\u003e 'application/json'\n    ],\n    json_encode($data)\n)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    var_dump(json_decode((string)$response-\u003egetBody()));\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nThis method will automatically add a matching `Content-Length` request\nheader if the outgoing request body is a `string`. If you're using a\nstreaming request body (`ReadableStreamInterface`), it will default to\nusing `Transfer-Encoding: chunked` or you have to explicitly pass in a\nmatching `Content-Length` request header like so:\n\n```php\n$body = new React\\Stream\\ThroughStream();\nLoop::addTimer(1.0, function () use ($body) {\n    $body-\u003eend(\"hello world\");\n});\n\n$browser-\u003epatch($url, ['Content-Length' =\u003e '11'], $body);\n```\n\n#### put()\n\nThe `put(string $url, array $headers = [], string|ReadableStreamInterface $body = ''): PromiseInterface\u003cResponseInterface\u003e` method can be used to\nsend an HTTP PUT request.\n\n```php\n$browser-\u003eput(\n    $url,\n    [\n        'Content-Type' =\u003e 'text/xml'\n    ],\n    $xml-\u003easXML()\n)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    var_dump((string)$response-\u003egetBody());\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nSee also [PUT XML client example](examples/05-client-put-xml.php).\n\nThis method will automatically add a matching `Content-Length` request\nheader if the outgoing request body is a `string`. If you're using a\nstreaming request body (`ReadableStreamInterface`), it will default to\nusing `Transfer-Encoding: chunked` or you have to explicitly pass in a\nmatching `Content-Length` request header like so:\n\n```php\n$body = new React\\Stream\\ThroughStream();\nLoop::addTimer(1.0, function () use ($body) {\n    $body-\u003eend(\"hello world\");\n});\n\n$browser-\u003eput($url, ['Content-Length' =\u003e '11'], $body);\n```\n\n#### delete()\n\nThe `delete(string $url, array $headers = [], string|ReadableStreamInterface $body = ''): PromiseInterface\u003cResponseInterface\u003e` method can be used to\nsend an HTTP DELETE request.\n\n```php\n$browser-\u003edelete($url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    var_dump((string)$response-\u003egetBody());\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\n#### request()\n\nThe `request(string $method, string $url, array $headers = [], string|ReadableStreamInterface $body = ''): PromiseInterface\u003cResponseInterface\u003e` method can be used to\nsend an arbitrary HTTP request.\n\nThe preferred way to send an HTTP request is by using the above\n[request methods](#request-methods), for example the [`get()`](#get)\nmethod to send an HTTP `GET` request.\n\nAs an alternative, if you want to use a custom HTTP request method, you\ncan use this method:\n\n```php\n$browser-\u003erequest('OPTIONS', $url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    var_dump((string)$response-\u003egetBody());\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nThis method will automatically add a matching `Content-Length` request\nheader if the size of the outgoing request body is known and non-empty.\nFor an empty request body, if will only include a `Content-Length: 0`\nrequest header if the request method usually expects a request body (only\napplies to `POST`, `PUT` and `PATCH`).\n\nIf you're using a streaming request body (`ReadableStreamInterface`), it\nwill default to using `Transfer-Encoding: chunked` or you have to\nexplicitly pass in a matching `Content-Length` request header like so:\n\n```php\n$body = new React\\Stream\\ThroughStream();\nLoop::addTimer(1.0, function () use ($body) {\n    $body-\u003eend(\"hello world\");\n});\n\n$browser-\u003erequest('POST', $url, ['Content-Length' =\u003e '11'], $body);\n```\n\n#### requestStreaming()\n\nThe `requestStreaming(string $method, string $url, array $headers = [], string|ReadableStreamInterface $body = ''): PromiseInterface\u003cResponseInterface\u003e` method can be used to\nsend an arbitrary HTTP request and receive a streaming response without buffering the response body.\n\nThe preferred way to send an HTTP request is by using the above\n[request methods](#request-methods), for example the [`get()`](#get)\nmethod to send an HTTP `GET` request. Each of these methods will buffer\nthe whole response body in memory by default. This is easy to get started\nand works reasonably well for smaller responses.\n\nIn some situations, it's a better idea to use a streaming approach, where\nonly small chunks have to be kept in memory. You can use this method to\nsend an arbitrary HTTP request and receive a streaming response. It uses\nthe same HTTP message API, but does not buffer the response body in\nmemory. It only processes the response body in small chunks as data is\nreceived and forwards this data through [ReactPHP's Stream API](https://github.com/reactphp/stream).\nThis works for (any number of) responses of arbitrary sizes.\n\n```php\n$browser-\u003erequestStreaming('GET', $url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    $body = $response-\u003egetBody();\n    assert($body instanceof Psr\\Http\\Message\\StreamInterface);\n    assert($body instanceof React\\Stream\\ReadableStreamInterface);\n\n    $body-\u003eon('data', function ($chunk) {\n        echo $chunk;\n    });\n\n    $body-\u003eon('error', function (Exception $e) {\n        echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n    });\n\n    $body-\u003eon('close', function () {\n        echo '[DONE]' . PHP_EOL;\n    });\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nSee also [ReactPHP's `ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface)\nand the [streaming response](#streaming-response) for more details,\nexamples and possible use-cases.\n\nThis method will automatically add a matching `Content-Length` request\nheader if the size of the outgoing request body is known and non-empty.\nFor an empty request body, if will only include a `Content-Length: 0`\nrequest header if the request method usually expects a request body (only\napplies to `POST`, `PUT` and `PATCH`).\n\nIf you're using a streaming request body (`ReadableStreamInterface`), it\nwill default to using `Transfer-Encoding: chunked` or you have to\nexplicitly pass in a matching `Content-Length` request header like so:\n\n```php\n$body = new React\\Stream\\ThroughStream();\nLoop::addTimer(1.0, function () use ($body) {\n    $body-\u003eend(\"hello world\");\n});\n\n$browser-\u003erequestStreaming('POST', $url, ['Content-Length' =\u003e '11'], $body);\n```\n\n#### withTimeout()\n\nThe `withTimeout(bool|number $timeout): Browser` method can be used to\nchange the maximum timeout used for waiting for pending requests.\n\nYou can pass in the number of seconds to use as a new timeout value:\n\n```php\n$browser = $browser-\u003ewithTimeout(10.0);\n```\n\nYou can pass in a bool `false` to disable any timeouts. In this case,\nrequests can stay pending forever:\n\n```php\n$browser = $browser-\u003ewithTimeout(false);\n```\n\nYou can pass in a bool `true` to re-enable default timeout handling. This\nwill respects PHP's `default_socket_timeout` setting (default 60s):\n\n```php\n$browser = $browser-\u003ewithTimeout(true);\n```\n\nSee also [timeouts](#timeouts) for more details about timeout handling.\n\nNotice that the [`Browser`](#browser) is an immutable object, i.e. this\nmethod actually returns a *new* [`Browser`](#browser) instance with the\ngiven timeout value applied.\n\n#### withFollowRedirects()\n\nThe `withFollowRedirects(bool|int $followRedirects): Browser` method can be used to\nchange how HTTP redirects will be followed.\n\nYou can pass in the maximum number of redirects to follow:\n\n```php\n$browser = $browser-\u003ewithFollowRedirects(5);\n```\n\nThe request will automatically be rejected when the number of redirects\nis exceeded. You can pass in a `0` to reject the request for any\nredirects encountered:\n\n```php\n$browser = $browser-\u003ewithFollowRedirects(0);\n\n$browser-\u003eget($url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    // only non-redirected responses will now end up here\n    var_dump($response-\u003egetHeaders());\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nYou can pass in a bool `false` to disable following any redirects. In\nthis case, requests will resolve with the redirection response instead\nof following the `Location` response header:\n\n```php\n$browser = $browser-\u003ewithFollowRedirects(false);\n\n$browser-\u003eget($url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    // any redirects will now end up here\n    var_dump($response-\u003egetHeaderLine('Location'));\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nYou can pass in a bool `true` to re-enable default redirect handling.\nThis defaults to following a maximum of 10 redirects:\n\n```php\n$browser = $browser-\u003ewithFollowRedirects(true);\n```\n\nSee also [redirects](#redirects) for more details about redirect handling.\n\nNotice that the [`Browser`](#browser) is an immutable object, i.e. this\nmethod actually returns a *new* [`Browser`](#browser) instance with the\ngiven redirect setting applied.\n\n#### withRejectErrorResponse()\n\nThe `withRejectErrorResponse(bool $obeySuccessCode): Browser` method can be used to\nchange whether non-successful HTTP response status codes (4xx and 5xx) will be rejected.\n\nYou can pass in a bool `false` to disable rejecting incoming responses\nthat use a 4xx or 5xx response status code. In this case, requests will\nresolve with the response message indicating an error condition:\n\n```php\n$browser = $browser-\u003ewithRejectErrorResponse(false);\n\n$browser-\u003eget($url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    // any HTTP response will now end up here\n    var_dump($response-\u003egetStatusCode(), $response-\u003egetReasonPhrase());\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nYou can pass in a bool `true` to re-enable default status code handling.\nThis defaults to rejecting any response status codes in the 4xx or 5xx\nrange with a [`ResponseException`](#responseexception):\n\n```php\n$browser = $browser-\u003ewithRejectErrorResponse(true);\n\n$browser-\u003eget($url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    // any successful HTTP response will now end up here\n    var_dump($response-\u003egetStatusCode(), $response-\u003egetReasonPhrase());\n}, function (Exception $e) {\n    if ($e instanceof React\\Http\\Message\\ResponseException) {\n        // any HTTP response error message will now end up here\n        $response = $e-\u003egetResponse();\n        var_dump($response-\u003egetStatusCode(), $response-\u003egetReasonPhrase());\n    } else {\n        echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n    }\n});\n```\n\nNotice that the [`Browser`](#browser) is an immutable object, i.e. this\nmethod actually returns a *new* [`Browser`](#browser) instance with the\ngiven setting applied.\n\n#### withBase()\n\nThe `withBase(string|null $baseUrl): Browser` method can be used to\nchange the base URL used to resolve relative URLs to.\n\nIf you configure a base URL, any requests to relative URLs will be\nprocessed by first resolving this relative to the given absolute base\nURL. This supports resolving relative path references (like `../` etc.).\nThis is particularly useful for (RESTful) API calls where all endpoints\n(URLs) are located under a common base URL.\n\n```php\n$browser = $browser-\u003ewithBase('http://api.example.com/v3/');\n\n// will request http://api.example.com/v3/users\n$browser-\u003eget('users')-\u003ethen(…);\n```\n\nYou can pass in a `null` base URL to return a new instance that does not\nuse a base URL:\n\n```php\n$browser = $browser-\u003ewithBase(null);\n```\n\nAccordingly, any requests using relative URLs to a browser that does not\nuse a base URL can not be completed and will be rejected without sending\na request.\n\nThis method will throw an `InvalidArgumentException` if the given\n`$baseUrl` argument is not a valid URL.\n\nNotice that the [`Browser`](#browser) is an immutable object, i.e. the `withBase()` method\nactually returns a *new* [`Browser`](#browser) instance with the given base URL applied.\n\n#### withProtocolVersion()\n\nThe `withProtocolVersion(string $protocolVersion): Browser` method can be used to\nchange the HTTP protocol version that will be used for all subsequent requests.\n\nAll the above [request methods](#request-methods) default to sending\nrequests as HTTP/1.1. This is the preferred HTTP protocol version which\nalso provides decent backwards-compatibility with legacy HTTP/1.0\nservers. As such, there should rarely be a need to explicitly change this\nprotocol version.\n\nIf you want to explicitly use the legacy HTTP/1.0 protocol version, you\ncan use this method:\n\n```php\n$browser = $browser-\u003ewithProtocolVersion('1.0');\n\n$browser-\u003eget($url)-\u003ethen(…);\n```\n\nNotice that the [`Browser`](#browser) is an immutable object, i.e. this\nmethod actually returns a *new* [`Browser`](#browser) instance with the\nnew protocol version applied.\n\n#### withResponseBuffer()\n\nThe `withResponseBuffer(int $maximumSize): Browser` method can be used to\nchange the maximum size for buffering a response body.\n\nThe preferred way to send an HTTP request is by using the above\n[request methods](#request-methods), for example the [`get()`](#get)\nmethod to send an HTTP `GET` request. Each of these methods will buffer\nthe whole response body in memory by default. This is easy to get started\nand works reasonably well for smaller responses.\n\nBy default, the response body buffer will be limited to 16 MiB. If the\nresponse body exceeds this maximum size, the request will be rejected.\n\nYou can pass in the maximum number of bytes to buffer:\n\n```php\n$browser = $browser-\u003ewithResponseBuffer(1024 * 1024);\n\n$browser-\u003eget($url)-\u003ethen(function (Psr\\Http\\Message\\ResponseInterface $response) {\n    // response body will not exceed 1 MiB\n    var_dump($response-\u003egetHeaders(), (string) $response-\u003egetBody());\n}, function (Exception $e) {\n    echo 'Error: ' . $e-\u003egetMessage() . PHP_EOL;\n});\n```\n\nNote that the response body buffer has to be kept in memory for each\npending request until its transfer is completed and it will only be freed\nafter a pending request is fulfilled. As such, increasing this maximum\nbuffer size to allow larger response bodies is usually not recommended.\nInstead, you can use the [`requestStreaming()` method](#requeststreaming)\nto receive responses with arbitrary sizes without buffering. Accordingly,\nthis maximum buffer size setting has no effect on streaming responses.\n\nNotice that the [`Browser`](#browser) is an immutable object, i.e. this\nmethod actually returns a *new* [`Browser`](#browser) instance with the\ngiven setting applied.\n\n#### withHeader()\n\nThe `withHeader(string $header, string $value): Browser` method can be used to\nadd a request header for all following requests.\n\n```php\n$browser = $browser-\u003ewithHeader('User-Agent', 'ACME');\n\n$browser-\u003eget($url)-\u003ethen(…);\n```\n\nNote that the new header will overwrite any headers previously set with\nthe same name (case-insensitive). Following requests will use these headers\nby default unless they are explicitly set for any requests.\n\n#### withoutHeader()\n\nThe `withoutHeader(string $header): Browser` method can be used to\nremove any default request headers previously set via\nthe [`withHeader()` method](#withheader).\n\n```php\n$browser = $browser-\u003ewithoutHeader('User-Agent');\n\n$browser-\u003eget($url)-\u003ethen(…);\n```\n\nNote that this method only affects the headers which were set with the\nmethod `withHeader(string $header, string $value): Browser`\n\n### React\\Http\\Message\n\n#### Response\n\nThe `React\\Http\\Message\\Response` class can be used to\nrepresent an outgoing server response message.\n\n```php\n$response = new React\\Http\\Message\\Response(\n    React\\Http\\Message\\Response::STATUS_OK,\n    [\n        'Content-Type' =\u003e 'text/html'\n    ],\n    \"\u003chtml\u003eHello world!\u003c/html\u003e\\n\"\n);\n```\n\nThis class implements the\n[PSR-7 `ResponseInterface`](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface)\nwhich in turn extends the\n[PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface).\n\nOn top of this, this class implements the\n[PSR-7 Message Util `StatusCodeInterface`](https://github.com/php-fig/http-message-util/blob/master/src/StatusCodeInterface.php)\nwhich means that most common HTTP status codes are available as class\nconstants with the `STATUS_*` prefix. For instance, the `200 OK` and\n`404 Not Found` status codes can used as `Response::STATUS_OK` and\n`Response::STATUS_NOT_FOUND` respectively.\n\n\u003e Internally, this implementation builds on top of a base class which is\n  considered an implementation detail that may change in the future.\n\n##### html()\n\nThe static `html(string $html): Response` method can be used to\ncreate an HTML response.\n\n```php\n$html = \u003c\u003c\u003cHTML\n\u003c!doctype html\u003e\n\u003chtml\u003e\n\u003cbody\u003eHello wörld!\u003c/body\u003e\n\u003c/html\u003e\n\nHTML;\n\n$response = React\\Http\\Message\\Response::html($html);\n```\n\nThis is a convenient shortcut method that returns the equivalent of this:\n\n```\n$response = new React\\Http\\Message\\Response(\n    React\\Http\\Message\\Response::STATUS_OK,\n    [\n        'Content-Type' =\u003e 'text/html; charset=utf-8'\n    ],\n    $html\n);\n```\n\nThis method always returns a response with a `200 OK` status code and\nthe appropriate `Content-Type` response header for the given HTTP source\nstring encoded in UTF-8 (Unicode). It's generally recommended to end the\ngiven plaintext string with a trailing newline.\n\nIf you want to use a different status code or custom HTTP response\nheaders, you can manipulate the returned response object using the\nprovided PSR-7 methods or directly instantiate a custom HTTP response\nobject using the `Response` constructor:\n\n```php\n$response = React\\Http\\Message\\Response::html(\n    \"\u003ch1\u003eError\u003c/h1\u003e\\n\u003cp\u003eInvalid user name given.\u003c/p\u003e\\n\"\n)-\u003ewithStatus(React\\Http\\Message\\Response::STATUS_BAD_REQUEST);\n```\n\n##### json()\n\nThe static `json(mixed $data): Response` method can be used to\ncreate a JSON response.\n\n```php\n$response = React\\Http\\Message\\Response::json(['name' =\u003e 'Alice']);\n```\n\nThis is a convenient shortcut method that returns the equivalent of this:\n\n```\n$response = new React\\Http\\Message\\Response(\n    React\\Http\\Message\\Response::STATUS_OK,\n    [\n        'Content-Type' =\u003e 'application/json'\n    ],\n    json_encode(\n        ['name' =\u003e 'Alice'],\n        JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION\n    ) . \"\\n\"\n);\n```\n\nThis method always returns a response with a `200 OK` status code and\nthe appropriate `Content-Type` response header for the given structured\ndata encoded as a JSON text.\n\nThe given structured data will be encoded as a JSON text. Any `string`\nvalues in the data must be encoded in UTF-8 (Unicode). If the encoding\nfails, this method will throw an `InvalidArgumentException`.\n\nBy default, the given structured data will be encoded with the flags as\nshown above. This includes pretty printing and preserving zero fractions\nfor `float` values to ease debugging. It is assumed any additional data\noverhead is usually compensated by using HTTP response compression.\n\nIf you want to use a different status code or custom HTTP response\nheaders, you can manipulate the returned response object using the\nprovided PSR-7 methods or directly instantiate a custom HTTP response\nobject using the `Response` constructor:\n\n```php\n$response = React\\Http\\Message\\Response::json(\n    ['error' =\u003e 'Invalid user name given']\n)-\u003ewithStatus(React\\Http\\Message\\Response::STATUS_BAD_REQUEST);\n```\n\n##### plaintext()\n\nThe static `plaintext(string $text): Response` method can be used to\ncreate a plaintext response.\n\n```php\n$response = React\\Http\\Message\\Response::plaintext(\"Hello wörld!\\n\");\n```\n\nThis is a convenient shortcut method that returns the equivalent of this:\n\n```\n$response = new React\\Http\\Message\\Response(\n    React\\Http\\Message\\Response::STATUS_OK,\n    [\n        'Content-Type' =\u003e 'text/plain; charset=utf-8'\n    ],\n    \"Hello wörld!\\n\"\n);\n```\n\nThis method always returns a response with a `200 OK` status code and\nthe appropriate `Content-Type` response header for the given plaintext\nstring encoded in UTF-8 (Unicode). It's generally recommended to end the\ngiven plaintext string with a trailing newline.\n\nIf you want to use a different status code or custom HTTP response\nheaders, you can manipulate the returned response object using the\nprovided PSR-7 methods or directly instantiate a custom HTTP response\nobject using the `Response` constructor:\n\n```php\n$response = React\\Http\\Message\\Response::plaintext(\n    \"Error: Invalid user name given.\\n\"\n)-\u003ewithStatus(React\\Http\\Message\\Response::STATUS_BAD_REQUEST);\n```\n\n##### xml()\n\nThe static `xml(string $xml): Response` method can be used to\ncreate an XML response.\n\n```php\n$xml = \u003c\u003c\u003cXML\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cbody\u003e\n    \u003cgreeting\u003eHello wörld!\u003c/greeting\u003e\n\u003c/body\u003e\n\nXML;\n\n$response = React\\Http\\Message\\Response::xml($xml);\n```\n\nThis is a convenient shortcut method that returns the equivalent of this:\n\n```\n$response = new React\\Http\\Message\\Response(\n    React\\Http\\Message\\Response::STATUS_OK,\n    [\n        'Content-Type' =\u003e 'application/xml'\n    ],\n    $xml\n);\n```\n\nThis method always returns a response with a `200 OK` status code and\nthe appropriate `Content-Type` response header for the given XML source\nstring. It's generally recommended to use UTF-8 (Unicode) and specify\nthis as part of the leading XML declaration and to end the given XML\nsource string with a trailing newline.\n\nIf you want to use a different status code or custom HTTP response\nheaders, you can manipulate the returned response object using the\nprovided PSR-7 methods or directly instantiate a custom HTTP response\nobject using the `Response` constructor:\n\n```php\n$response = React\\Http\\Message\\Response::xml(\n    \"\u003cerror\u003e\u003cmessage\u003eInvalid user name given.\u003c/message\u003e\u003c/error\u003e\\n\"\n)-\u003ewithStatus(React\\Http\\Message\\Response::STATUS_BAD_REQUEST);\n```\n\n#### Request\n\nThe `React\\Http\\Message\\Request` class can be used to\nrespresent an outgoing HTTP request message.\n\nThis class implements the\n[PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface)\nwhich extends the\n[PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface).\n\nThis is mostly used internally to represent each outgoing HTTP request\nmessage for the HTTP client implementation. Likewise, you can also use this\nclass with other HTTP client implementations and for tests.\n\n\u003e Internally, this implementation builds on top of a base class which is\n  considered an implementation detail that may change in the future.\n\n#### ServerRequest\n\nThe `React\\Http\\Message\\ServerRequest` class can be used to\nrespresent an incoming server request message.\n\nThis class implements the\n[PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface)\nwhich extends the\n[PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface)\nwhich in turn extends the\n[PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface).\n\nThis is mostly used internally to represent each incoming request message.\nLikewise, you can also use this class in test cases to test how your web\napplication reacts to certain HTTP requests.\n\n\u003e Internally, this implementation builds on top of a base class which is\n  considered an implementation detail that may change in the future.\n\n#### Uri\n\nThe `React\\Http\\Message\\Uri` class can be used to\nrespresent a URI (or URL).\n\nThis class implements the\n[PSR-7 `UriInterface`](https://www.php-fig.org/psr/psr-7/#35-psrhttpmessageuriinterface).\n\nThis is mostly used internally to represent the URI of each HTTP request\nmessage for our HTTP client and server implementations. Likewise, you may\nalso use this class with other HTTP implementations and for tests.\n\n#### ResponseException\n\nThe `React\\Http\\Message\\ResponseException` is an `Exception` sub-class that will be used to reject\na request promise if the remote server returns a non-success status code\n(anything but 2xx or 3xx).\nYou can control this behavior via the [`withRejectErrorResponse()` method](#withrejecterrorresponse).\n\nThe `getCode(): int` method can be used to\nreturn the HTTP response status code.\n\nThe `getResponse(): ResponseInterface` method can be used to\naccess its underlying response object.\n\n### React\\Http\\Middleware\n\n#### StreamingRequestMiddleware\n\nThe `React\\Http\\Middleware\\StreamingRequestMiddleware` can be used to\nprocess incoming requests with a streaming request body (without buffering).\n\nThis allows you to process requests of any size without buffering the request\nbody in memory. Instead, it will represent the request body as a\n[`ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface)\nthat emit chunks of incoming data as it is received:\n\n```php\n$http = new React\\Http\\HttpServer(\n    new React\\Http\\Middleware\\StreamingRequestMiddleware(),\n    function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n        $body = $request-\u003egetBody();\n        assert($body instanceof Psr\\Http\\Message\\StreamInterface);\n        assert($body instanceof React\\Stream\\ReadableStreamInterface);\n\n        return new React\\Promise\\Promise(function ($resolve) use ($body) {\n            $bytes = 0;\n            $body-\u003eon('data', function ($chunk) use (\u0026$bytes) {\n                $bytes += \\count($chunk);\n            });\n            $body-\u003eon('close', function () use (\u0026$bytes, $resolve) {\n                $resolve(new React\\Http\\Message\\Response(\n                    React\\Http\\Message\\Response::STATUS_OK,\n                    [],\n                    \"Received $bytes bytes\\n\"\n                ));\n            });\n        });\n    }\n);\n```\n\nSee also [streaming incoming request](#streaming-incoming-request)\nfor more details.\n\nAdditionally, this middleware can be used in combination with the\n[`LimitConcurrentRequestsMiddleware`](#limitconcurrentrequestsmiddleware) and\n[`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) (see below)\nto explicitly configure the total number of requests that can be handled at\nonce:\n\n```php\n$http = new React\\Http\\HttpServer(\n    new React\\Http\\Middleware\\StreamingRequestMiddleware(),\n    new React\\Http\\Middleware\\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers\n    new React\\Http\\Middleware\\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request\n    new React\\Http\\Middleware\\RequestBodyParserMiddleware(),\n    $handler\n);\n```\n\n\u003e Internally, this class is used as a \"marker\" to not trigger the default\n  request buffering behavior in the `HttpServer`. It does not implement any logic\n  on its own.\n\n#### LimitConcurrentRequestsMiddleware\n\nThe `React\\Http\\Middleware\\LimitConcurrentRequestsMiddleware` can be used to\nlimit how many next handlers can be executed concurrently.\n\nIf this middleware is invoked, it will check if the number of pending\nhandlers is below the allowed limit and then simply invoke the next handler\nand it will return whatever the next handler returns (or throws).\n\nIf the number of pending handlers exceeds the allowed limit, the request will\nbe queued (and its streaming body will be paused) and it will return a pending\npromise.\nOnce a pending handler returns (or throws), it will pick the oldest request\nfrom this queue and invokes the next handler (and its streaming body will be\nresumed).\n\nThe following example shows how this middleware can be used to ensure no more\nthan 10 handlers will be invoked at once:\n\n```php\n$http = new React\\Http\\HttpServer(\n    new React\\Http\\Middleware\\LimitConcurrentRequestsMiddleware(10),\n    $handler\n);\n```\n\nSimilarly, this middleware is often used in combination with the\n[`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) (see below)\nto limit the total number of requests that can be buffered at once:\n\n```php\n$http = new React\\Http\\HttpServer(\n    new React\\Http\\Middleware\\StreamingRequestMiddleware(),\n    new React\\Http\\Middleware\\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers\n    new React\\Http\\Middleware\\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request\n    new React\\Http\\Middleware\\RequestBodyParserMiddleware(),\n    $handler\n);\n```\n\nMore sophisticated examples include limiting the total number of requests\nthat can be buffered at once and then ensure the actual request handler only\nprocesses one request after another without any concurrency:\n\n```php\n$http = new React\\Http\\HttpServer(\n    new React\\Http\\Middleware\\StreamingRequestMiddleware(),\n    new React\\Http\\Middleware\\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers\n    new React\\Http\\Middleware\\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request\n    new React\\Http\\Middleware\\RequestBodyParserMiddleware(),\n    new React\\Http\\Middleware\\LimitConcurrentRequestsMiddleware(1), // only execute 1 handler (no concurrency)\n    $handler\n);\n```\n\n#### RequestBodyBufferMiddleware\n\nOne of the built-in middleware is the `React\\Http\\Middleware\\RequestBodyBufferMiddleware` which\ncan be used to buffer the whole incoming request body in memory.\nThis can be useful if full PSR-7 compatibility is needed for the request handler\nand the default streaming request body handling is not needed.\nThe constructor accepts one optional argument, the maximum request body size.\nWhen one isn't provided it will use `post_max_size` (default 8 MiB) from PHP's\nconfiguration.\n(Note that the value from your matching SAPI will be used, which is the CLI\nconfiguration in most cases.)\n\nAny incoming request that has a request body that exceeds this limit will be\naccepted, but its request body will be discarded (empty request body).\nThis is done in order to avoid having to keep an incoming request with an\nexcessive size (for example, think of a 2 GB file upload) in memory.\nThis allows the next middleware handler to still handle this request, but it\nwill see an empty request body.\nThis is similar to PHP's default behavior, where the body will not be parsed\nif this limit is exceeded. However, unlike PHP's default behavior, the raw\nrequest body is not available via `php://input`.\n\nThe `RequestBodyBufferMiddleware` will buffer requests with bodies of known size \n(i.e. with `Content-Length` header specified) as well as requests with bodies of \nunknown size (i.e. with `Transfer-Encoding: chunked` header).\n\nAll requests will be buffered in memory until the request body end has\nbeen reached and then call the next middleware handler with the complete,\nbuffered request.\nSimilarly, this will immediately invoke the next middleware handler for requests\nthat have an empty request body (such as a simple `GET` request) and requests\nthat are already buffered (such as due to another middleware).\n\nNote that the given buffer size limit is applied to each request individually.\nThis means that if you allow a 2 MiB limit and then receive 1000 concurrent\nrequests, up to 2000 MiB may be allocated for these buffers alone.\nAs such, it's highly recommended to use this along with the\n[`LimitConcurrentRequestsMiddleware`](#limitconcurrentrequestsmiddleware) (see above) to limit\nthe total number of concurrent requests.\n\nUsage:\n\n```php\n$http = new React\\Http\\HttpServer(\n    new React\\Http\\Middleware\\StreamingRequestMiddleware(),\n    new React\\Http\\Middleware\\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers\n    new React\\Http\\Middleware\\RequestBodyBufferMiddleware(16 * 1024 * 1024), // 16 MiB\n    function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n        // The body from $request-\u003egetBody() is now fully available without the need to stream it \n        return new React\\Http\\Message\\Response(React\\Http\\Message\\Response::STATUS_OK);\n    },\n);\n```\n\n#### RequestBodyParserMiddleware\n\nThe `React\\Http\\Middleware\\RequestBodyParserMiddleware` takes a fully buffered request body\n(generally from [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware)), \nand parses the form values and file uploads from the incoming HTTP request body.\n\nThis middleware handler takes care of applying values from HTTP\nrequests that use `Content-Type: application/x-www-form-urlencoded` or\n`Content-Type: multipart/form-data` to resemble PHP's default superglobals\n`$_POST` and `$_FILES`.\nInstead of relying on these superglobals, you can use the\n`$request-\u003egetParsedBody()` and `$request-\u003egetUploadedFiles()` methods\nas defined by PSR-7.\n\nAccordingly, each file upload will be represented as instance implementing the\n[PSR-7 `UploadedFileInterface`](https://www.php-fig.org/psr/psr-7/#36-psrhttpmessageuploadedfileinterface).\nDue to its blocking nature, the `moveTo()` method is not available and throws\na `RuntimeException` instead.\nYou can use `$contents = (string)$file-\u003egetStream();` to access the file\ncontents and persist this to your favorite data store.\n\n```php\n$handler = function (Psr\\Http\\Message\\ServerRequestInterface $request) {\n    // If any, parsed form fields are now available from $request-\u003egetParsedBody()\n    $body = $request-\u003egetParsedBody();\n    $name = isset($body['name']) ? $body['name'] : 'unnamed';\n\n    $files = $request-\u003egetUploadedFiles();\n    $avatar = isset($files['avatar']) ? $files['avatar'] : null;\n    if ($avatar instanceof Psr\\Http\\Message\\UploadedFileInterface) {\n        if ($avatar-\u003egetError() === UPLOAD_ERR_OK) {\n            $uploaded = $avatar-\u003egetSize() . ' bytes';\n        } elseif ($avatar-\u003egetError() === UPLOAD_ERR_INI_SIZE) {\n            $uploaded = 'file too large';\n        } else {\n            $uploaded = 'with error';\n        }\n    } else {\n        $uploaded = 'nothing';\n    }\n\n    return new React\\Http\\Message\\Response(\n        React\\Http\\Message\\Response::STATUS_OK,\n        [\n            'Content-Type' =\u003e 'text/plain'\n        ],\n        $name . ' uploaded ' . $uploaded\n    );\n};\n\n$http = new React\\Http\\HttpServer(\n    new React\\Http\\Middleware\\StreamingRequestMiddleware(),\n    new React\\Http\\Middleware\\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers\n    new React\\Http\\Middleware\\RequestBodyBufferMiddleware(16 * 1024 * 1024), // 16 MiB\n    new React\\Http\\Middleware\\RequestBodyParserMiddleware(),\n    $handler\n);\n```\n\nSee also [form upload server example](examples/62-server-form-upload.php) for more details.\n\nBy default, this middleware respects the\n[`upload_max_filesize`](https://www.php.net/manual/en/ini.core.php#ini.upload-max-filesize)\n(default `2M`) ini setting.\nFiles that exceed this limit will be rejected with an `UPLOAD_ERR_INI_SIZE` error.\nYou can control the maximum filesize for each individual file upload by\nexplicitly passing the maximum filesize in bytes as the first parameter to the\nconstructor like this:\n\n```php\nnew React\\Http\\Middleware\\RequestBodyParserMiddleware(8 * 1024 * 1024); // 8 MiB limit per file\n```\n\nBy default, this middleware respects the\n[`file_uploads`](https://www.php.net/manual/en/ini.core.php#ini.file-uploads)\n(default `1`) and\n[`max_file_uploads`](https://www.php.net/manual/en/ini.core.php#ini.max-file-uploads)\n(default `20`) ini settings.\nThese settings control if any and how many files can be uploaded in a single request.\nIf you upload more files in a single request, additional files will be ignored\nand the `getUploadedFiles()` method returns a truncated array.\nNote that upload fields left blank on submission do not count towards this limit.\nYou can control the maximum number of file uploads per request by explicitly\npassing the second parameter to the constructor like this:\n\n```php\nnew React\\Http\\Middleware\\RequestBodyParserMiddleware(10 * 1024, 100); // 100 files with 10 KiB each\n```\n\n\u003e Note that this middleware handler simply parses everything that is already\n  buffered in the request body.\n  It is imperative that the request body is buffered by a prior middleware\n  handler as given in the example above.\n  This previous middleware handler is also responsible for rejecting incoming\n  requests that exceed allowed message sizes (such as big file uploads).\n  The [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) used above\n  simply discards excessive request bodies, resulting in an empty body.\n  If you use this middleware without buffering first, it will try to parse an\n  empty (streaming) body and may thus assume an empty data structure.\n  See also [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) for\n  more details.\n  \n\u003e PHP's `MAX_FILE_SIZE` hidden field is respected by this middleware.\n  Files that exceed this limit will be rejected with an `UPLOAD_ERR_FORM_SIZE` error.\n\n\u003e This middleware respects the\n  [`max_input_vars`](https://www.php.net/manual/en/info.configuration.php#ini.max-input-vars)\n  (default `1000`) and\n  [`max_input_nesting_level`](https://www.php.net/manual/en/info.configuration.php#ini.max-input-nesting-level)\n  (default `64`) ini settings.\n\n\u003e Note that this middleware ignores the\n  [`enable_post_data_reading`](https://www.php.net/manual/en/ini.core.php#ini.enable-post-data-reading)\n  (default `1`) ini setting because it makes little sense to respect here and\n  is left up to higher-level implementations.\n  If you want to respect this setting, you have to check its value and\n  effectively avoid using this middleware entirely.\n\n## Install\n\nThe recommended way to install this library is [through Composer](https://getcomposer.org/).\n[New to Composer?](https://getcomposer.org/doc/00-intro.md)\n\nOnce released, this project will follow [SemVer](https://semver.org/).\nAt the moment, this will install the latest development version:\n\n```bash\ncomposer require react/http:^3@dev\n```\n\nSee also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.\n\nThis project aims to run on any platform and thus does not require any PHP\nextensions and supports running on PHP 7.1 through current PHP 8+.\nIt's *highly recommended to use the latest supported PHP version* for this project.\n\n## Tests\n\nTo run the test suite, you first need to clone this repo and then install all\ndependencies [through Composer](https://getcomposer.org/):\n\n```bash\ncomposer install\n```\n\nTo run the test suite, go to the project root and run:\n\n```bash\nvendor/bin/phpunit\n```\n\nThe test suite also contains a number of functional integration tests that rely\non a stable internet connection.\nIf you do not want to run these, they can simply be skipped like this:\n\n```bash\nvendor/bin/phpunit --exclude-group internet\n```\n\n## License\n\nMIT, see [LICENSE file](LICENSE).\n","funding_links":["https://github.com/sponsors/reactphp","https://github.com/sponsors/clue","https://github.com/sponsors/WyriHaximus","https://opencollective.com/reactphp"],"categories":["PHP"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactphp%2Fhttp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freactphp%2Fhttp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactphp%2Fhttp/lists"}