An advanced async HTTP server library for PHP, perfect for real-time apps and APIs with high concurrency demands.
CompressionMiddleware
added in the last release not actually being set (#339)Http2Driver::shutdown()
was called while there were pending streamsLink
headers being overwritten by HTTP/1.x driver.DefaultHttpDriverFactory
, Http1Driver
, and Http2Driver
constructors. Data read from body streams is now immediately pushed to the client. Use a custom stream implementation for the body if buffering is desired.DefaultHttpDriverFactory
constructor.getLogger()
, getRequestHandler()
, and getErrorHandler()
from HttpServer
to avoid the interface being used as a service-locator.ErrorHandler
is now required for SocketHttpServer::start()
instead of being optional.Initial release compatible with AMPHP v3.
As with other libraries compatible with AMPHP v3, most cases of parameters or returns of Promise<ResolutionType>
have been replaced with ResolutionType
.
Happily, the RequestHandler
and Middleware
interfaces along with the Request
and Response
objects are largely unchanged with the exception of replacing Promise
objects with the resolution type.
RequestHandler::handleRequest()
and Middleware::handleRequest()
has changed from Promise<Response>
to Response
.ReadableStream
or a string (note the interface name change in amphp/byte-stream
). null
will no longer be cast to an empty body.Initializing a server has changed significantly.
The Options
object has been removed, replaced by constructor parameters on various components. PHP 8.0's named parameters allows only defining the parameters you wish to override without the need to define those you do not wish to change.
HttpServer
is now an interface. ServerObserver
has been removed and replaced with onStart()
and onStop()
methods on the HttpServer
interface. SocketHttpServer
is the provided default implementation of HttpServer
.
Listening interfaces are provided to SocketHttpServer
using the expose()
. The RequestHandler
and ErrorHandler
instances are not provided to the constructor, instead being provided to the SocketHttpServer::start()
method. As these objects are provided after constructing the HttpServer
instance, RequestHandlers
may now require an instance of HttpServer
in their constructors to attach start and stop handlers.
SocketServer
instances are then created by SocketHttpServer
using an instance of SocketServerFactory
passed to the constructor. This allows server bind contexts to be initialized based on the provided (or default) HttpDriverFactory
.
Below is the "Hello, World!" example from examples/hello-world.php as an example of initializing a SocketHttpServer
instance.
<?php
require dirname(__DIR__) . "/vendor/autoload.php";
use Amp\ByteStream;
use Amp\Http\Server\Request;
use Amp\Http\Server\RequestHandler\ClosureRequestHandler;
use Amp\Http\Server\Response;
use Amp\Http\Server\SocketHttpServer;
use Amp\Http\Status;
use Amp\Log\ConsoleFormatter;
use Amp\Log\StreamHandler;
use Amp\Socket;
use Monolog\Logger;
use Monolog\Processor\PsrLogMessageProcessor;
use function Amp\trapSignal;
// Run this script, then visit http://localhost:1337/ or https://localhost:1338/ in your browser.
$cert = new Socket\Certificate(__DIR__ . '/../test/server.pem');
$context = (new Socket\BindContext)
->withTlsContext((new Socket\ServerTlsContext)
->withDefaultCertificate($cert));
$logHandler = new StreamHandler(ByteStream\getStdout());
$logHandler->pushProcessor(new PsrLogMessageProcessor());
$logHandler->setFormatter(new ConsoleFormatter);
$logger = new Logger('server');
$logger->pushHandler($logHandler);
$server = new SocketHttpServer($logger);
$server->expose(new Socket\InternetAddress("0.0.0.0", 1337));
$server->expose(new Socket\InternetAddress("[::]", 1337));
$server->expose(new Socket\InternetAddress("0.0.0.0", 1338), $context);
$server->expose(new Socket\InternetAddress("[::]", 1338), $context);
$server->start(new ClosureRequestHandler(static function (Request $request): Response {
return new Response(Status::OK, [
"content-type" => "text/plain; charset=utf-8",
], "Hello, World!");
}));
// Await SIGINT or SIGTERM to be received.
$signal = trapSignal([\SIGINT, \SIGTERM]);
$logger->info(sprintf("Received signal %d, stopping HTTP server", $signal));
$server->stop();
Generally consumers of this library need not worry about these changes unless they implemented their own HTTP driver or interacted with the Client
interface beyond grabbing client metadata.
Client
is a significantly thinner interface, consisting of only metadata about the client connection.HttpDriver
instances now handle responding to requests instead of the Client
object.HttpDriver::setup()
has been replaced with HttpDriver::handleClient
. Rather than returning a Generator parser which is fed data read from the client, this method is instead expected to read/write data from the provided streams itself.HttpDriver::write()
has been removed, as writing to the client should be handled internally within the driver.src/Server.php
with --classmap-authoritative