PHPackages                             faj1/http - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. faj1/http

ActiveLibrary[HTTP &amp; Networking](/categories/http)

faj1/http
=========

Event-driven, streaming HTTP client and server implementation for ReactPHP

0371PHP

Since Nov 13Pushed 1y ago1 watchersCompare

[ Source](https://github.com/faj1/http)[ Packagist](https://packagist.org/packages/faj1/http)[ RSS](/packages/faj1-http/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (1)

HTTP
====

[](#http)

[![CI status](https://github.com/reactphp/http/actions/workflows/ci.yml/badge.svg)](https://github.com/reactphp/http/actions)[![installs on Packagist](https://camo.githubusercontent.com/c392ef20c32841314052d5d90e4480def5d3d0ca43ab69be56357732e4961c85/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f72656163742f687474703f636f6c6f723d626c7565266c6162656c3d696e7374616c6c732532306f6e2532305061636b6167697374)](https://packagist.org/packages/react/http)

Event-driven, streaming HTTP client and server implementation for [ReactPHP](https://reactphp.org/).

> **Development version:** This branch contains the code for the upcoming v3 release. For the code of the current stable v1 release, check out the [`1.x` branch](https://github.com/reactphp/http/tree/1.x).
>
> The upcoming v3 release will be the way forward for this package. However, we will still actively support v1 for those not yet on the latest version. See also [installation instructions](#install) for more details.

This HTTP library provides re-usable implementations for an HTTP client and server based on ReactPHP's [`Socket`](https://github.com/reactphp/socket) and [`EventLoop`](https://github.com/reactphp/event-loop) components. Its client component allows you to send any number of async HTTP/HTTPS requests concurrently. Its server component allows you to build plaintext HTTP and secure HTTPS servers that accept incoming HTTP requests from HTTP clients (such as web browsers). This library provides async, streaming means for all of this, so you can handle multiple concurrent HTTP requests without blocking.

**Table of contents**

- [Quickstart example](#quickstart-example)
- [Client Usage](#client-usage)
    - [Request methods](#request-methods)
    - [Promises](#promises)
    - [Cancellation](#cancellation)
    - [Timeouts](#timeouts)
    - [Authentication](#authentication)
    - [Redirects](#redirects)
    - [Blocking](#blocking)
    - [Concurrency](#concurrency)
    - [Streaming response](#streaming-response)
    - [Streaming request](#streaming-request)
    - [HTTP proxy](#http-proxy)
    - [SOCKS proxy](#socks-proxy)
    - [SSH proxy](#ssh-proxy)
    - [Unix domain sockets](#unix-domain-sockets)
- [Server Usage](#server-usage)
    - [HttpServer](#httpserver)
    - [listen()](#listen)
    - [Server Request](#server-request)
        - [Request parameters](#request-parameters)
        - [Query parameters](#query-parameters)
        - [Request body](#request-body)
        - [Streaming incoming request](#streaming-incoming-request)
        - [Request method](#request-method)
        - [Cookie parameters](#cookie-parameters)
        - [Invalid request](#invalid-request)
    - [Server Response](#server-response)
        - [Deferred response](#deferred-response)
        - [Streaming outgoing response](#streaming-outgoing-response)
        - [Response length](#response-length)
        - [Invalid response](#invalid-response)
        - [Default response headers](#default-response-headers)
    - [Middleware](#middleware)
        - [Custom middleware](#custom-middleware)
        - [Third-Party Middleware](#third-party-middleware)
- [API](#api)
    - [Browser](#browser)
        - [get()](#get)
        - [post()](#post)
        - [head()](#head)
        - [patch()](#patch)
        - [put()](#put)
        - [delete()](#delete)
        - [request()](#request)
        - [requestStreaming()](#requeststreaming)
        - [withTimeout()](#withtimeout)
        - [withFollowRedirects()](#withfollowredirects)
        - [withRejectErrorResponse()](#withrejecterrorresponse)
        - [withBase()](#withbase)
        - [withProtocolVersion()](#withprotocolversion)
        - [withResponseBuffer()](#withresponsebuffer)
        - [withHeader()](#withheader)
        - [withoutHeader()](#withoutheader)
    - [React\\Http\\Message](#reacthttpmessage)
        - [Response](#response)
            - [html()](#html)
            - [json()](#json)
            - [plaintext()](#plaintext)
            - [xml()](#xml)
        - [Request](#request-1)
        - [ServerRequest](#serverrequest)
        - [Uri](#uri)
        - [ResponseException](#responseexception)
    - [React\\Http\\Middleware](#reacthttpmiddleware)
        - [StreamingRequestMiddleware](#streamingrequestmiddleware)
        - [LimitConcurrentRequestsMiddleware](#limitconcurrentrequestsmiddleware)
        - [RequestBodyBufferMiddleware](#requestbodybuffermiddleware)
        - [RequestBodyParserMiddleware](#requestbodyparsermiddleware)
- [Install](#install)
- [Tests](#tests)
- [License](#license)

Quickstart example
------------------

[](#quickstart-example)

Once [installed](#install), you can use the following code to access an HTTP web server and send some simple HTTP GET requests:

```

    Hello wörld!

XML;

$response = React\Http\Message\Response::xml($xml);
```

This is a convenient shortcut method that returns the equivalent of this:

```
$response = new React\Http\Message\Response(
    React\Http\Message\Response::STATUS_OK,
    [
        'Content-Type' => 'application/xml'
    ],
    $xml
);

```

This method always returns a response with a `200 OK` status code and the appropriate `Content-Type` response header for the given XML source string. It's generally recommended to use UTF-8 (Unicode) and specify this as part of the leading XML declaration and to end the given XML source string with a trailing newline.

If you want to use a different status code or custom HTTP response headers, you can manipulate the returned response object using the provided PSR-7 methods or directly instantiate a custom HTTP response object using the `Response` constructor:

```
$response = React\Http\Message\Response::xml(
    "Invalid user name given.\n"
)->withStatus(React\Http\Message\Response::STATUS_BAD_REQUEST);
```

#### Request

[](#request-1)

The `React\Http\Message\Request` class can be used to respresent an outgoing HTTP request message.

This class implements the [PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface)which extends the [PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface).

This is mostly used internally to represent each outgoing HTTP request message for the HTTP client implementation. Likewise, you can also use this class with other HTTP client implementations and for tests.

> Internally, this implementation builds on top of a base class which is considered an implementation detail that may change in the future.

#### ServerRequest

[](#serverrequest)

The `React\Http\Message\ServerRequest` class can be used to respresent an incoming server request message.

This class implements the [PSR-7 `ServerRequestInterface`](https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface)which extends the [PSR-7 `RequestInterface`](https://www.php-fig.org/psr/psr-7/#32-psrhttpmessagerequestinterface)which in turn extends the [PSR-7 `MessageInterface`](https://www.php-fig.org/psr/psr-7/#31-psrhttpmessagemessageinterface).

This is mostly used internally to represent each incoming request message. Likewise, you can also use this class in test cases to test how your web application reacts to certain HTTP requests.

> Internally, this implementation builds on top of a base class which is considered an implementation detail that may change in the future.

#### Uri

[](#uri)

The `React\Http\Message\Uri` class can be used to respresent a URI (or URL).

This class implements the [PSR-7 `UriInterface`](https://www.php-fig.org/psr/psr-7/#35-psrhttpmessageuriinterface).

This is mostly used internally to represent the URI of each HTTP request message for our HTTP client and server implementations. Likewise, you may also use this class with other HTTP implementations and for tests.

#### ResponseException

[](#responseexception)

The `React\Http\Message\ResponseException` is an `Exception` sub-class that will be used to reject a request promise if the remote server returns a non-success status code (anything but 2xx or 3xx). You can control this behavior via the [`withRejectErrorResponse()` method](#withrejecterrorresponse).

The `getCode(): int` method can be used to return the HTTP response status code.

The `getResponse(): ResponseInterface` method can be used to access its underlying response object.

### React\\Http\\Middleware

[](#reacthttpmiddleware)

#### StreamingRequestMiddleware

[](#streamingrequestmiddleware)

The `React\Http\Middleware\StreamingRequestMiddleware` can be used to process incoming requests with a streaming request body (without buffering).

This allows you to process requests of any size without buffering the request body in memory. Instead, it will represent the request body as a [`ReadableStreamInterface`](https://github.com/reactphp/stream#readablestreaminterface)that emit chunks of incoming data as it is received:

```
$http = new React\Http\HttpServer(
    new React\Http\Middleware\StreamingRequestMiddleware(),
    function (Psr\Http\Message\ServerRequestInterface $request) {
        $body = $request->getBody();
        assert($body instanceof Psr\Http\Message\StreamInterface);
        assert($body instanceof React\Stream\ReadableStreamInterface);

        return new React\Promise\Promise(function ($resolve) use ($body) {
            $bytes = 0;
            $body->on('data', function ($chunk) use (&$bytes) {
                $bytes += \count($chunk);
            });
            $body->on('close', function () use (&$bytes, $resolve) {
                $resolve(new React\Http\Message\Response(
                    React\Http\Message\Response::STATUS_OK,
                    [],
                    "Received $bytes bytes\n"
                ));
            });
        });
    }
);
```

See also [streaming incoming request](#streaming-incoming-request)for more details.

Additionally, this middleware can be used in combination with the [`LimitConcurrentRequestsMiddleware`](#limitconcurrentrequestsmiddleware) and [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) (see below) to explicitly configure the total number of requests that can be handled at once:

```
$http = new React\Http\HttpServer(
    new React\Http\Middleware\StreamingRequestMiddleware(),
    new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers
    new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request
    new React\Http\Middleware\RequestBodyParserMiddleware(),
    $handler
);
```

> Internally, this class is used as a "marker" to not trigger the default request buffering behavior in the `HttpServer`. It does not implement any logic on its own.

#### LimitConcurrentRequestsMiddleware

[](#limitconcurrentrequestsmiddleware)

The `React\Http\Middleware\LimitConcurrentRequestsMiddleware` can be used to limit how many next handlers can be executed concurrently.

If this middleware is invoked, it will check if the number of pending handlers is below the allowed limit and then simply invoke the next handler and it will return whatever the next handler returns (or throws).

If the number of pending handlers exceeds the allowed limit, the request will be queued (and its streaming body will be paused) and it will return a pending promise. Once a pending handler returns (or throws), it will pick the oldest request from this queue and invokes the next handler (and its streaming body will be resumed).

The following example shows how this middleware can be used to ensure no more than 10 handlers will be invoked at once:

```
$http = new React\Http\HttpServer(
    new React\Http\Middleware\LimitConcurrentRequestsMiddleware(10),
    $handler
);
```

Similarly, this middleware is often used in combination with the [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) (see below) to limit the total number of requests that can be buffered at once:

```
$http = new React\Http\HttpServer(
    new React\Http\Middleware\StreamingRequestMiddleware(),
    new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers
    new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request
    new React\Http\Middleware\RequestBodyParserMiddleware(),
    $handler
);
```

More sophisticated examples include limiting the total number of requests that can be buffered at once and then ensure the actual request handler only processes one request after another without any concurrency:

```
$http = new React\Http\HttpServer(
    new React\Http\Middleware\StreamingRequestMiddleware(),
    new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers
    new React\Http\Middleware\RequestBodyBufferMiddleware(2 * 1024 * 1024), // 2 MiB per request
    new React\Http\Middleware\RequestBodyParserMiddleware(),
    new React\Http\Middleware\LimitConcurrentRequestsMiddleware(1), // only execute 1 handler (no concurrency)
    $handler
);
```

#### RequestBodyBufferMiddleware

[](#requestbodybuffermiddleware)

One of the built-in middleware is the `React\Http\Middleware\RequestBodyBufferMiddleware` which can be used to buffer the whole incoming request body in memory. This can be useful if full PSR-7 compatibility is needed for the request handler and the default streaming request body handling is not needed. The constructor accepts one optional argument, the maximum request body size. When one isn't provided it will use `post_max_size` (default 8 MiB) from PHP's configuration. (Note that the value from your matching SAPI will be used, which is the CLI configuration in most cases.)

Any incoming request that has a request body that exceeds this limit will be accepted, but its request body will be discarded (empty request body). This is done in order to avoid having to keep an incoming request with an excessive size (for example, think of a 2 GB file upload) in memory. This allows the next middleware handler to still handle this request, but it will see an empty request body. This is similar to PHP's default behavior, where the body will not be parsed if this limit is exceeded. However, unlike PHP's default behavior, the raw request body is not available via `php://input`.

The `RequestBodyBufferMiddleware` will buffer requests with bodies of known size (i.e. with `Content-Length` header specified) as well as requests with bodies of unknown size (i.e. with `Transfer-Encoding: chunked` header).

All requests will be buffered in memory until the request body end has been reached and then call the next middleware handler with the complete, buffered request. Similarly, this will immediately invoke the next middleware handler for requests that have an empty request body (such as a simple `GET` request) and requests that are already buffered (such as due to another middleware).

Note that the given buffer size limit is applied to each request individually. This means that if you allow a 2 MiB limit and then receive 1000 concurrent requests, up to 2000 MiB may be allocated for these buffers alone. As such, it's highly recommended to use this along with the [`LimitConcurrentRequestsMiddleware`](#limitconcurrentrequestsmiddleware) (see above) to limit the total number of concurrent requests.

Usage:

```
$http = new React\Http\HttpServer(
    new React\Http\Middleware\StreamingRequestMiddleware(),
    new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers
    new React\Http\Middleware\RequestBodyBufferMiddleware(16 * 1024 * 1024), // 16 MiB
    function (Psr\Http\Message\ServerRequestInterface $request) {
        // The body from $request->getBody() is now fully available without the need to stream it
        return new React\Http\Message\Response(React\Http\Message\Response::STATUS_OK);
    },
);
```

#### RequestBodyParserMiddleware

[](#requestbodyparsermiddleware)

The `React\Http\Middleware\RequestBodyParserMiddleware` takes a fully buffered request body (generally from [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware)), and parses the form values and file uploads from the incoming HTTP request body.

This middleware handler takes care of applying values from HTTP requests that use `Content-Type: application/x-www-form-urlencoded` or `Content-Type: multipart/form-data` to resemble PHP's default superglobals `$_POST` and `$_FILES`. Instead of relying on these superglobals, you can use the `$request->getParsedBody()` and `$request->getUploadedFiles()` methods as defined by PSR-7.

Accordingly, each file upload will be represented as instance implementing the [PSR-7 `UploadedFileInterface`](https://www.php-fig.org/psr/psr-7/#36-psrhttpmessageuploadedfileinterface). Due to its blocking nature, the `moveTo()` method is not available and throws a `RuntimeException` instead. You can use `$contents = (string)$file->getStream();` to access the file contents and persist this to your favorite data store.

```
$handler = function (Psr\Http\Message\ServerRequestInterface $request) {
    // If any, parsed form fields are now available from $request->getParsedBody()
    $body = $request->getParsedBody();
    $name = isset($body['name']) ? $body['name'] : 'unnamed';

    $files = $request->getUploadedFiles();
    $avatar = isset($files['avatar']) ? $files['avatar'] : null;
    if ($avatar instanceof Psr\Http\Message\UploadedFileInterface) {
        if ($avatar->getError() === UPLOAD_ERR_OK) {
            $uploaded = $avatar->getSize() . ' bytes';
        } elseif ($avatar->getError() === UPLOAD_ERR_INI_SIZE) {
            $uploaded = 'file too large';
        } else {
            $uploaded = 'with error';
        }
    } else {
        $uploaded = 'nothing';
    }

    return new React\Http\Message\Response(
        React\Http\Message\Response::STATUS_OK,
        [
            'Content-Type' => 'text/plain'
        ],
        $name . ' uploaded ' . $uploaded
    );
};

$http = new React\Http\HttpServer(
    new React\Http\Middleware\StreamingRequestMiddleware(),
    new React\Http\Middleware\LimitConcurrentRequestsMiddleware(100), // 100 concurrent buffering handlers
    new React\Http\Middleware\RequestBodyBufferMiddleware(16 * 1024 * 1024), // 16 MiB
    new React\Http\Middleware\RequestBodyParserMiddleware(),
    $handler
);
```

See also [form upload server example](examples/62-server-form-upload.php) for more details.

By default, this middleware respects the [`upload_max_filesize`](https://www.php.net/manual/en/ini.core.php#ini.upload-max-filesize)(default `2M`) ini setting. Files that exceed this limit will be rejected with an `UPLOAD_ERR_INI_SIZE` error. You can control the maximum filesize for each individual file upload by explicitly passing the maximum filesize in bytes as the first parameter to the constructor like this:

```
new React\Http\Middleware\RequestBodyParserMiddleware(8 * 1024 * 1024); // 8 MiB limit per file
```

By default, this middleware respects the [`file_uploads`](https://www.php.net/manual/en/ini.core.php#ini.file-uploads)(default `1`) and [`max_file_uploads`](https://www.php.net/manual/en/ini.core.php#ini.max-file-uploads)(default `20`) ini settings. These settings control if any and how many files can be uploaded in a single request. If you upload more files in a single request, additional files will be ignored and the `getUploadedFiles()` method returns a truncated array. Note that upload fields left blank on submission do not count towards this limit. You can control the maximum number of file uploads per request by explicitly passing the second parameter to the constructor like this:

```
new React\Http\Middleware\RequestBodyParserMiddleware(10 * 1024, 100); // 100 files with 10 KiB each
```

> Note that this middleware handler simply parses everything that is already buffered in the request body. It is imperative that the request body is buffered by a prior middleware handler as given in the example above. This previous middleware handler is also responsible for rejecting incoming requests that exceed allowed message sizes (such as big file uploads). The [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) used above simply discards excessive request bodies, resulting in an empty body. If you use this middleware without buffering first, it will try to parse an empty (streaming) body and may thus assume an empty data structure. See also [`RequestBodyBufferMiddleware`](#requestbodybuffermiddleware) for more details.

> PHP's `MAX_FILE_SIZE` hidden field is respected by this middleware. Files that exceed this limit will be rejected with an `UPLOAD_ERR_FORM_SIZE` error.

> This middleware respects the [`max_input_vars`](https://www.php.net/manual/en/info.configuration.php#ini.max-input-vars)(default `1000`) and [`max_input_nesting_level`](https://www.php.net/manual/en/info.configuration.php#ini.max-input-nesting-level)(default `64`) ini settings.

> Note that this middleware ignores the [`enable_post_data_reading`](https://www.php.net/manual/en/ini.core.php#ini.enable-post-data-reading)(default `1`) ini setting because it makes little sense to respect here and is left up to higher-level implementations. If you want to respect this setting, you have to check its value and effectively avoid using this middleware entirely.

Install
-------

[](#install)

The recommended way to install this library is [through Composer](https://getcomposer.org/). [New to Composer?](https://getcomposer.org/doc/00-intro.md)

Once released, this project will follow [SemVer](https://semver.org/). At the moment, this will install the latest development version:

```
composer require react/http:^3@dev
```

See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.

This project aims to run on any platform and thus does not require any PHP extensions and supports running on PHP 7.1 through current PHP 8+. It's *highly recommended to use the latest supported PHP version* for this project.

Tests
-----

[](#tests)

To run the test suite, you first need to clone this repo and then install all dependencies [through Composer](https://getcomposer.org/):

```
composer install
```

To run the test suite, go to the project root and run:

```
vendor/bin/phpunit
```

The test suite also contains a number of functional integration tests that rely on a stable internet connection. If you do not want to run these, they can simply be skipped like this:

```
vendor/bin/phpunit --exclude-group internet
```

License
-------

[](#license)

MIT, see [LICENSE file](LICENSE).

###  Health Score

16

—

LowBetter than 5% of packages

Maintenance30

Infrequent updates — may be unmaintained

Popularity7

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity16

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/a0218fc896fe52e0d04873517c4b208ad1542deeaa0e51f98e3f42c80a83cf29?d=identicon)[faj1](/maintainers/faj1)

---

Top Contributors

[![githabus](https://avatars.githubusercontent.com/u/10916592?v=4)](https://github.com/githabus "githabus (3 commits)")

### Embed Badge

![Health badge](/badges/faj1-http/health.svg)

```
[![Health](https://phpackages.com/badges/faj1-http/health.svg)](https://phpackages.com/packages/faj1-http)
```

###  Alternatives

[friendsofsymfony/rest-bundle

This Bundle provides various tools to rapidly develop RESTful API's with Symfony

2.8k73.3M319](/packages/friendsofsymfony-rest-bundle)[php-http/discovery

Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations

1.3k309.5M1.2k](/packages/php-http-discovery)[nyholm/psr7

A fast PHP7 implementation of PSR-7

1.3k235.4M2.4k](/packages/nyholm-psr7)[pusher/pusher-php-server

Library for interacting with the Pusher REST API

1.5k94.8M293](/packages/pusher-pusher-php-server)[spatie/crawler

Crawl all internal links found on a website

2.8k16.3M52](/packages/spatie-crawler)[react/http

Event-driven, streaming HTTP client and server implementation for ReactPHP

78126.4M414](/packages/react-http)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
