reactphp/http gives a PHP process a non-blocking HTTP client and a streaming server
Event-driven, streaming HTTP client and server implementation for ReactPHP.
At a glance
- What is it?
- reactphp/http provides reusable HTTP client and server implementations built on ReactPHP's Socket and EventLoop components, so one PHP process can hold many requests open at once without blocking. The stable line is 1.x, with a v3 line under development on the 3.x branch.
- Who is it for?
- reactphp/http fits PHP services that need to fan out many upstream HTTP calls without threads, that want to stream large uploads or downloads instead of buffering them, and that already run on ReactPHP's event loop. It is the wrong choice for a request-response web framework, where a conventional PHP server handles concurrency for you, and it is the wrong choice for a team that cannot accept a package that is mid-way between stable and next major.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 44 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One event loop, many HTTP requests at the same time
reactphp/http is described as an event-driven, streaming HTTP client and server implementation for ReactPHP. The README explains what sits underneath: the library provides reusable implementations for an HTTP client and server based on ReactPHP's Socket and EventLoop components.
That is the whole architectural idea. Rather than a request/response library that blocks, the client component lets you send any number of async HTTP or HTTPS requests concurrently, and the server component builds plaintext HTTP and secure HTTPS servers that accept incoming requests from clients such as web browsers. The README is explicit that the library provides async, streaming means for all of this, so you can handle multiple concurrent HTTP requests without blocking.
The audience is therefore PHP developers writing long-running processes: a bot, a proxy, a webhook relay, a worker that calls many APIs at once, or a service that streams data. A traditional PHP page request, where one script does one thing and exits, gains nothing from this design.
The object model is PSR shaped. The quickstart returns a Psr\Http\Message\ResponseInterface and the server handler receives a Psr\Http\Message\ServerRequestInterface, so message handling follows the PSR message interfaces rather than inventing its own request and response types.
The Browser object returns promises you can cancel
The client entry point is React\Http\Browser, and the README says it offers several methods that resemble the HTTP protocol methods:
$browser->get($url, array $headers = []);
$browser->head($url, array $headers = []);
$browser->post($url, array $headers = [], string|ReadableStreamInterface $body = '');
$browser->delete($url, array $headers = [], string|ReadableStreamInterface $body = '');
$browser->put($url, array $headers = [], string|ReadableStreamInterface $body = '');
$browser->patch($url, array $headers = [], string|ReadableStreamInterface $body = '');Each method takes a URL and optional headers, and a body for the methods that usually carry one. The library adds a matching Content-Length header when the body size is known and non-empty, and for an empty body it only sends Content-Length: 0 for POST, PUT and PATCH, which is the method set that usually expects a body.
The quickstart shows the promise shape:
$client = new React\Http\Browser();
$client->get('http://www.google.com/')->then(function (Psr\Http\Message\ResponseInterface $response) {
var_dump($response->getHeaders(), (string)$response->getBody());
}, function (Exception $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
});The table of contents also lists request options for cancellation, timeouts, authentication, redirects and a blocking mode, plus wrapper methods that return a modified Browser, such as withTimeout(), withFollowRedirects(), withRejectErrorResponse(), withBase(), withProtocolVersion(), withResponseBuffer(), withHeader() and withoutHeader(). That last group is a useful pattern: the browser is immutable in the sense that each wrapper returns a configured instance, so a service can keep one base client and derive a client with a timeout for a specific call.
Streaming bodies both ways, with chunked transfer by default
Streaming is the part of the library that a blocking client cannot easily copy. On the request side, the README says that if you use a streaming request body it will default to using Transfer-Encoding: chunked unless you explicitly pass in a matching Content-Length request header.
That default has a practical consequence for API servers on the other end. Many endpoints reject chunked request bodies or parse them differently, so a request whose body you stream will not be interchangeable with one whose body is a string. If the API you call requires a known length, you either buffer the body or send the header yourself.
On the response side, the streaming API lets you consume a body as it arrives rather than waiting for the whole payload. The example gallery makes that concrete with examples/21-client-request-streaming-to-stdout.php and examples/22-client-stream-upload-from-stdin.php, which pipe data in and out rather than holding it in memory.
This is the capability that makes the library attractive for large file transfer, proxying and monitoring, where a buffered client would either run out of memory or wait for a body that is never going to finish quickly. The trade-off is that error handling moves: with a streaming body, a mid-transfer failure arrives after the status line has already been delivered, so you cannot turn a broken download into a non-200 response at that point.
The server side hands you a PSR server request and lets you answer later
The server is React\Http\HttpServer, and the quickstart is short enough to read in one go:
$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) {
return React\Http\Message\Response::plaintext(
"Hello World!\n"
);
});
$socket = new React\Socket\SocketServer('127.0.0.1:8080');
$http->listen($socket);Three things stand out. The handler receives a PSR server request and returns a response object, so it looks like any PSR-15 middleware. The response is built with a static helper on React\Http\Message\Response, in this case plaintext. And the server listens on a socket from the Socket component, which is what lets you serve HTTPS by giving listen() a TLS socket instead.
The README's table of contents lists the server features in detail: request parameters, query parameters, request body, streaming incoming request, request method, cookie parameters, and invalid request handling, and on the response side deferred responses, streaming outgoing response, response length, invalid response and default response headers.
Deferred responses are the mechanism worth understanding. Because the handler can return a promise, a handler can wait on a database or another service and answer later, which keeps the connection open and the process from blocking. The example gallery includes examples/52-server-count-visitors.php and examples/56-server-sleep.php, which are the two cases that make the point: a slow handler that holds the request, and shared state that the server keeps between requests.
Middleware for concurrency limits, body parsing and streaming requests
React\Http\Middleware is where the parts you would otherwise write yourself live. The README's table of contents names four of them: StreamingRequestMiddleware, LimitConcurrentRequestsMiddleware, RequestBodyBufferMiddleware and RequestBodyParserMiddleware, and the middleware chapter covers custom middleware and third party middleware.
LimitConcurrentRequestsMiddleware addresses a problem specific to event-driven servers. A blocking server can only have as many concurrent requests as it has workers, so a slow handler throttles the whole process. With non-blocking handlers the limit is the memory and CPU of your process, and a flood of slow requests can still exhaust it. A concurrency limit middleware is the equivalent of a worker pool, expressed as a middleware.
RequestBodyBufferMiddleware and RequestBodyParserMiddleware are the counterpart to streaming. Buffering collects the incoming body so a handler can read it as a string, and parsing turns a form or JSON body into parsed parameters, which is what a simple JSON API example such as examples/59-server-json-api.php needs.
StreamingRequestMiddleware is the counterpart again: it turns the incoming request body into a readable stream so the handler can process it incrementally, which pairs with examples/63-server-streaming-request.php and examples/62-server-form-upload.php.
The takeaway is that the library separates transport from parsing, so a service can choose per route whether a body is read as a whole or consumed as a stream.
Proxies, Unix sockets and the example gallery as documentation
The client has a long list of transport options, and the example files show each one as a runnable program: examples/11-client-http-proxy.php, examples/12-client-socks-proxy.php, examples/13-client-ssh-proxy.php and examples/14-client-unix-domain-sockets.php on the client side, and examples/71-server-http-proxy.php and examples/72-server-http-connect-proxy.php for turning the server into a proxy.
That last pair is worth pausing on. A ReactPHP server that speaks HTTP proxying is the shortest path to a forwarding service: no Apache or nginx in front, no process per connection, and the same streaming machinery on both sides. The cost is that the proxying logic in the example is example code, and the README does not describe it as a production grade proxy implementation.
The example gallery also covers the ordinary cases: 01-client-get-request.php, 02-client-concurrent-requests.php, 03-client-request-any.php, 04-client-post-json.php, 05-client-put-xml.php, 51-server-hello-world.php, 53-server-whatsmyip.php, 54-server-query-parameter.php, 55-server-cookie-handling.php, 57-server-error-handling.php, 58-server-stream-response.php and 61-server-hello-world-https.php.
Two details from the naming are easy to miss. 03-client-request-any.php suggests a method for arbitrary HTTP verbs beyond the named ones, and the HTTPS example is a server example, so serving TLS is a matter of handing listen() a TLS socket rather than a flag on HttpServer.
A v1 stable line and a v3 branch under development
The repository has two lines in play, and the README puts a notice about it at the top. The default branch is 3.x, and the notice says that branch contains the code for the upcoming v3 release, while the code of the current stable v1 release lives on the 1.x branch. It also says the upcoming v3 release will be the way forward for this package, and that v1 will still be actively supported for those not yet on the latest version.
The release history matches that picture. v1.11.1 was published on 2026-09-09, while v1.11.0 dates from 2024-11-20 and v1.10.0 from 2024-03-27. The last push to the repository was on 2026-09-09.
So the practical advice for a new project is to decide early which line you start on. Starting on 1.x keeps you on the supported, released code, and moving to 3 later means dealing with a major version change. Starting on 3.x means writing against an API that has not shipped as a stable tag.
The package is published as react/http on Packagist, and the license is MIT with the LICENSE file at the repository root. The repository also carries a CHANGELOG.md, phpunit.xml.dist alongside a legacy phpunit.xml, an examples directory and a tests directory, and the CI badge points at a GitHub Actions workflow.
Editorial conclusion
reactphp/http fits PHP services that need to fan out many upstream HTTP calls without threads, that want to stream large uploads or downloads instead of buffering them, and that already run on ReactPHP's event loop. It is the wrong choice for a request-response web framework, where a conventional PHP server handles concurrency for you, and it is the wrong choice for a team that cannot accept a package that is mid-way between stable and next major. Verify first which branch you are on, since the 3.x branch holds code for an upcoming v3 while v1 is still supported, then check that the client options you need exist in your chosen branch, because the documented surface covers timeouts, cancellation, redirects, authentication, proxies and streaming bodies.
Frequently asked questions
What is reactphp/http used for?
It provides reusable, event-driven HTTP client and server implementations for ReactPHP, built on the Socket and EventLoop components. The client can send any number of async HTTP or HTTPS requests concurrently, and the server accepts incoming HTTP and HTTPS requests without blocking the process.
How do I install and use reactphp/http?
The package is published as react/http on Packagist. The quickstart creates a React\Http\Browser, calls get() on a URL and handles the promise, and for the server side creates a React\Http\HttpServer with a handler, then passes a React\Socket\SocketServer to the listen() method.
Which branch should I use, 3.x or 1.x?
The README states that the 3.x branch contains the code for the upcoming v3 release and that v1 is the current stable release on the 1.x branch, and that v1 will still be actively supported. The latest stable tag is v1.11.1, published on 2026-09-09.
How does streaming request bodies work in reactphp/http?
A streaming request body defaults to Transfer-Encoding: chunked unless you pass a matching Content-Length header yourself. Streaming responses can be consumed as they arrive, and the examples directory includes a client streaming a request to stdout and a client streaming an upload from stdin.
What middleware does reactphp/http provide?
The README lists StreamingRequestMiddleware, LimitConcurrentRequestsMiddleware, RequestBodyBufferMiddleware and RequestBodyParserMiddleware, and it also covers how to write custom middleware and use third party middleware.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/reactphp-http)