AMPHP ist eine Sammlung ereignisgesteuerter Bibliotheken für PHP, die unter Berücksichtigung von Fibers und Parallelität entwickelt wurden. Dieses Paket stellt einen nicht blockierenden, gleichzeitigen HTTP/1.1- und HTTP/2-Anwendungsserver für PHP basierend auf Revolt bereit. Mehrere Funktionen werden in separaten Paketen bereitgestellt, beispielsweise in der WebSocket-Komponente.
Dieses Paket kann als Composer-Abhängigkeit installiert werden.
composer require amphp/http-server
Darüber hinaus möchten Sie möglicherweise die nghttp2
-Bibliothek installieren, um FFI zu nutzen und die Speichernutzung zu beschleunigen und zu reduzieren.
Diese Bibliothek ermöglicht den Zugriff auf Ihre Anwendung über das HTTP-Protokoll, indem sie Clientanfragen akzeptiert und diese Anfragen an von Ihrer Anwendung definierte Handler weiterleitet, die eine Antwort zurückgeben.
Eingehende Anfragen werden durch Request
-Objekte dargestellt. Eine Anfrage wird an einen Implementierer von RequestHandler
gesendet, der eine handleRequest()
Methode definiert, die eine Instanz von Response
zurückgibt.
public function handleRequest( Request $ request ): Response
Anfragehandler werden im Abschnitt RequestHandler
ausführlicher behandelt.
Dieser HTTP-Server basiert auf der Revolt-Ereignisschleife und dem nicht blockierenden Parallelitäts-Framework Amp. Somit erbt es die volle Unterstützung aller ihrer Grundelemente und es ist möglich, alle nicht blockierenden Bibliotheken zu verwenden, die auf Revolt basieren.
Hinweis Generell sollten Sie sich mit dem
Future
Konzept , mit Coroutinen und den verschiedenen Kombinatorfunktionen vertraut machen, um den HTTP-Server wirklich erfolgreich nutzen zu können.
Nahezu jede integrierte Funktion von PHP blockiert E/A, das heißt, der ausführende Thread (im Fall von PHP größtenteils äquivalent zum Prozess) wird effektiv angehalten, bis die Antwort empfangen wird. Ein paar Beispiele für solche Funktionen: mysqli_query
, file_get_contents
, usleep
und viele mehr.
Eine gute Faustregel lautet: Jede integrierte PHP-Funktion, die E/A ausführt, führt sie auf blockierende Weise aus, es sei denn, Sie wissen genau, dass dies nicht der Fall ist.
Es gibt Bibliotheken, die Implementierungen bereitstellen, die nicht blockierende E/A verwenden. Sie sollten diese anstelle der integrierten Funktionen verwenden.
Wir decken die häufigsten I/O-Anforderungen ab, wie z. B. Netzwerk-Sockets, Dateizugriff, HTTP-Anfragen und Websockets, MySQL- und Postgres-Datenbank-Clients und Redis. Wenn zur Erfüllung einer Anforderung die Verwendung blockierender E/A oder lange Berechnungen erforderlich sind, sollten Sie die Verwendung der Parallelbibliothek in Betracht ziehen, um diesen Code in einem separaten Prozess oder Thread auszuführen.
Warnung: Verwenden Sie keine blockierenden I/O-Funktionen im HTTP-Server.
// Here's a bad example, DO NOT do something like the following!
$ handler = new ClosureRequestHandler ( function () {
sleep ( 5 ); // Equivalent to a blocking I/O function with a 5 second timeout
return new Response ;
});
// Start a server with this handler and hit it twice.
// You'll have to wait until the 5 seconds are over until the second request is handled.
Ihre Anwendung wird von einer Instanz von HttpServer
bedient. Diese Bibliothek stellt SocketHttpServer
bereit, der für die meisten Anwendungen geeignet ist und auf Komponenten basiert, die in dieser Bibliothek und in amphp/socket
enthalten sind.
Um eine Instanz von SocketHttpServer
zu erstellen und auf Anfragen zu warten, sind mindestens vier Dinge erforderlich:
RequestHandler
, um auf eingehende Anfragen zu antworten,ErrorHander
um Antworten auf ungültige Anfragen bereitzustellen,PsrLogLoggerInterface
und <?php
use Amp ByteStream ;
use Amp Http HttpStatus ;
use Amp Http Server DefaultErrorHandler ;
use Amp Http Server Request ;
use Amp Http Server RequestHandler ;
use Amp Http Server Response ;
use Amp Http Server SocketHttpServer ;
use Amp Log ConsoleFormatter ;
use Amp Log StreamHandler ;
use Monolog Logger ;
use Monolog Processor PsrLogMessageProcessor ;
require __DIR__ . ' /vendor/autoload.php ' ;
// Note any PSR-3 logger may be used, Monolog is only an example.
$ logHandler = new StreamHandler ( ByteStream getStdout ());
$ logHandler -> pushProcessor ( new PsrLogMessageProcessor ());
$ logHandler -> setFormatter ( new ConsoleFormatter ());
$ logger = new Logger ( ' server ' );
$ logger -> pushHandler ( $ logHandler );
$ requestHandler = new class () implements RequestHandler {
public function handleRequest ( Request $ request ) : Response
{
return new Response (
status: HttpStatus:: OK ,
headers: [ ' Content-Type ' => ' text/plain ' ],
body: ' Hello, world! ' ,
);
}
};
$ errorHandler = new DefaultErrorHandler ();
$ server = SocketHttpServer:: createForDirectAccess ( $ logger );
$ server -> expose ( ' 127.0.0.1:1337 ' );
$ server -> start ( $ requestHandler , $ errorHandler );
// Serve requests until SIGINT or SIGTERM is received by the process.
Amp trapSignal ([ SIGINT , SIGTERM ]);
$ server -> stop ();
Das obige Beispiel erstellt einen einfachen Server, der auf jede empfangene Anfrage eine Klartext-Antwort sendet.
SocketHttpServer
bietet zusätzlich zum normalen Konstruktor für erweiterte und benutzerdefinierte Anwendungen zwei statische Konstruktoren für allgemeine Anwendungsfälle.
SocketHttpServer::createForDirectAccess()
: Wird im obigen Beispiel verwendet und erstellt einen HTTP-Anwendungsserver, der für den direkten Netzwerkzugriff geeignet ist. Es gelten einstellbare Grenzwerte für Verbindungen pro IP, Gesamtverbindungen und gleichzeitige Anfragen (standardmäßig jeweils 10, 1000 und 1000). Die Antwortkomprimierung kann ein- oder ausgeschaltet werden (standardmäßig aktiviert), und die Anforderungsmethoden sind standardmäßig auf einen bekannten Satz von HTTP-Verben beschränkt.SocketHttpServer::createForBehindProxy()
: Erstellt einen Server, der für die Verwendung hinter einem Proxy-Dienst wie Nginx geeignet ist. Dieser statische Konstruktor erfordert eine Liste vertrauenswürdiger Proxy-IPs (mit optionalen Subnetzmasken) und einen Aufzählungsfall von ForwardedHeaderType
(entweder Forwarded
oder X-Forwarded-For
), um die ursprüngliche Client-IP aus Anforderungsheadern zu analysieren. Für die Anzahl der Verbindungen zum Server gibt es keine Beschränkungen, die Anzahl gleichzeitiger Anfragen ist jedoch begrenzt (standardmäßig 1000, einstellbar oder kann entfernt werden). Die Antwortkomprimierung kann ein- oder ausgeschaltet werden (standardmäßig aktiviert). Anforderungsmethoden sind standardmäßig auf einen bekannten Satz von HTTP-Verben beschränkt. Wenn keine dieser Methoden Ihren Anwendungsanforderungen entspricht, kann der SocketHttpServer
-Konstruktor direkt verwendet werden. Dies bietet ein enormes Maß an Flexibilität bei der Erstellung und Handhabung eingehender Client-Verbindungen, erfordert jedoch mehr Code zum Erstellen. Der Konstruktor erfordert, dass der Benutzer eine Instanz von SocketServerFactory
übergibt, die zum Erstellen von Client- Socket
-Instanzen verwendet wird (beides Komponenten der amphp/socket
-Bibliothek), und eine Instanz von ClientFactory
, die entsprechend Client
Instanzen erstellt, die an jede vom Client gestellte Request
angehängt werden .
RequestHandler
Eingehende Anfragen werden durch Request
-Objekte dargestellt. Eine Anfrage wird an einen Implementierer von RequestHandler
gesendet, der eine handleRequest()
Methode definiert, die eine Instanz von Response
zurückgibt.
public function handleRequest( Request $ request ): Response
Jede Client-Anfrage (d. h. ein Aufruf von RequestHandler::handleRequest()
) wird in einer separaten Coroutine ausgeführt, sodass Anfragen automatisch kooperativ innerhalb des Serverprozesses bearbeitet werden. Wenn ein Anforderungshandler auf nicht blockierende E/A wartet, werden andere Clientanforderungen in gleichzeitigen Coroutinen verarbeitet. Ihr Anfragehandler kann selbst andere Coroutinen erstellen, indem er Ampasync()
verwendet, um mehrere Aufgaben für eine einzelne Anfrage auszuführen.
Normalerweise generiert ein RequestHandler
direkt eine Antwort, er kann aber auch an einen anderen RequestHandler
delegieren. Ein Beispiel für einen solchen delegierenden RequestHandler
ist der Router
.
Die RequestHandler
Schnittstelle soll durch benutzerdefinierte Klassen implementiert werden. Für sehr einfache Anwendungsfälle oder schnelles Verspotten können Sie CallableRequestHandler
verwenden, der jedes callable
umschließen, einen Request
annehmen und einen Response
zurückgeben kann.
Middleware ermöglicht die Vorverarbeitung von Anfragen und die Nachverarbeitung von Antworten. Darüber hinaus kann eine Middleware auch die Anfrageverarbeitung abfangen und eine Antwort zurückgeben, ohne sie an den übergebenen Anfragehandler zu delegieren. Dafür müssen Klassen die Middleware
Schnittstelle implementieren.
Hinweis Middleware folgt im Allgemeinen anderen Wörtern wie „Soft-“ und „Hardware“ im Plural. Allerdings verwenden wir den Begriff Middleware, um sich auf mehrere Objekte zu beziehen, die die
Middleware
Schnittstelle implementieren.
public function handleRequest( Request $ request , RequestHandler $ next ): Response
handleRequest
ist die einzige Methode der Middleware
Schnittstelle. Wenn die Middleware
die Anfrage nicht selbst verarbeitet, sollte sie die Antworterstellung an den empfangenen RequestHandler
delegieren.
function stackMiddleware( RequestHandler $ handler , Middleware ... $ middleware ): RequestHandler
Mehrere Middlewares können gestapelt werden, indem AmpHttpServerMiddlewarestackMiddleware()
verwendet wird, das einen RequestHandler
als erstes Argument und eine variable Anzahl von Middleware
Instanzen akzeptiert. Der zurückgegebene RequestHandler
ruft jede Middleware in der angegebenen Reihenfolge auf.
$ requestHandler = new class implements RequestHandler {
public function handleRequest ( Request $ request ): Response
{
return new Response (
status: HttpStatus:: OK ,
headers: [ " content-type " => " text/plain; charset=utf-8 " ],
body: " Hello, World! " ,
);
}
}
$ middleware = new class implements Middleware {
public function handleRequest ( Request $ request , RequestHandler $ next ): Response
{
$ requestTime = microtime ( true );
$ response = $ next -> handleRequest ( $ request );
$ response -> setHeader ( " x-request-time " , microtime ( true ) - $ requestTime );
return $ response ;
}
};
$ stackedHandler = Middleware stackMiddleware ( $ requestHandler , $ middleware );
$ errorHandler = new DefaultErrorHandler ();
// $logger is a PSR-3 logger instance.
$ server = SocketHttpServer:: createForDirectAccess ( $ logger );
$ server -> expose ( ' 127.0.0.1:1337 ' );
$ server -> start ( $ stackedHandler , $ errorHandler );
ErrorHandler
Ein ErrorHander
wird vom HTTP-Server verwendet, wenn eine fehlerhafte oder anderweitig ungültige Anfrage empfangen wird. Das Request
Objekt wird bereitgestellt, wenn eines aus den eingehenden Daten erstellt wurde, ist jedoch möglicherweise nicht immer festgelegt.
public function handleError(
int $ status ,
? string $ reason = null ,
? Request $ request = null ,
): Response
Diese Bibliothek stellt DefaultErrorHandler
bereit, der eine stilisierte HTML-Seite als Antworttext zurückgibt. Möglicherweise möchten Sie eine andere Implementierung für Ihre Anwendung bereitstellen und möglicherweise mehrere in Verbindung mit einem Router verwenden.
Request
Es kommt selten vor, dass Sie selbst ein Request
-Objekt erstellen müssen, da diese normalerweise vom Server an RequestHandler::handleRequest()
bereitgestellt werden.
/**
* @param string $method The HTTP method verb.
* @param array<string>|array<string, array<string>> $headers An array of strings or an array of string arrays.
*/
public function __construct(
private readonly Client $ client ,
string $ method ,
Psr Http Message UriInterface $ uri ,
array $ headers = [],
Amp ByteStream ReadableStream | string $ body = '' ,
private string $ protocol = ' 1.1 ' ,
? Trailers $ trailers = null ,
)
public function getClient(): Client
Gibt den Сlient
zurück, der die Anfrage sendet
public function getMethod(): string
Gibt die HTTP-Methode zurück, die für diese Anfrage verwendet wurde, z. B. "GET"
.
public function setMethod( string $ method ): void
Legt die HTTP-Anforderungsmethode fest.
public function getUri(): Psr Http Message UriInterface
Gibt den Anforderungs URI
zurück.
public function setUri( Psr Http Message UriInterface $ uri ): void
Legt einen neuen URI
für die Anfrage fest.
public function getProtocolVersion(): string
Gibt die HTTP-Protokollversion als String zurück (z. B. „1.0“, „1.1“, „2“).
public function setProtocolVersion( string $ protocol )
Legt eine neue Protokollversionsnummer für die Anfrage fest.
/** @return array<non-empty-string, list<string>> */
public function getHeaders(): array
Gibt die Header als stringindiziertes Array von String-Arrays oder als leeres Array zurück, wenn keine Header festgelegt wurden.
public function hasHeader( string $ name ): bool
Überprüft, ob der angegebene Header vorhanden ist.
/** @return list<string> */
public function getHeaderArray( string $ name ): array
Gibt das Wertearray für den angegebenen Header oder ein leeres Array zurück, wenn der Header nicht vorhanden ist.
public function getHeader( string $ name ): ? string
Gibt den Wert des angegebenen Headers zurück. Wenn für den benannten Header mehrere Header vorhanden sind, wird nur der erste Header-Wert zurückgegeben. Verwenden Sie getHeaderArray()
um ein Array aller Werte für den jeweiligen Header zurückzugeben. Gibt null
zurück, wenn der Header nicht vorhanden ist.
public function setHeaders( array $ headers ): void
Legt die Header aus dem angegebenen Array fest.
/** @param array<string>|string $value */
public function setHeader( string $ name , array | string $ value ): void
Setzt den Header auf die angegebenen Werte. Alle bisherigen Kopfzeilen mit dem angegebenen Namen werden ersetzt.
/** @param array<string>|string $value */
public function addHeader( string $ name , array | string $ value ): void
Fügt eine zusätzliche Kopfzeile mit dem angegebenen Namen hinzu.
public function removeHeader( string $ name ): void
Entfernt den angegebenen Header, falls vorhanden. Wenn mehrere Kopfzeilen mit demselben Namen vorhanden sind, werden alle entfernt.
public function getBody(): RequestBody
Gibt den Anforderungstext zurück. Der RequestBody
ermöglicht den gestreamten und gepufferten Zugriff auf einen InputStream
.
public function setBody( ReadableStream | string $ body )
Legt den Stream für den Nachrichtentext fest
Hinweis Durch die Verwendung einer Zeichenfolge wird der
Content-Length
-Header automatisch auf die Länge der angegebenen Zeichenfolge festgelegt. Durch das Festlegen einesReadableStream
wird derContent-Length
Header entfernt. Wenn Sie die genaue Inhaltslänge Ihres Streams kennen, können Sie nach dem Aufruf vonsetBody()
einen Headercontent-length
hinzufügen.
/** @return array<non-empty-string, RequestCookie> */
public function getCookies(): array
Gibt alle Cookies in der assoziativen Zuordnung des Cookie-Namens an RequestCookie
zurück.
public function getCookie( string $ name ): ? RequestCookie
Ruft einen Cookie-Wert nach Name oder null
ab.
public function setCookie( RequestCookie $ cookie ): void
Fügt der Anfrage ein Cookie
hinzu.
public function removeCookie( string $ name ): void
Entfernt ein Cookie aus der Anfrage.
public function getAttributes(): array
Gibt ein Array aller Attribute zurück, die im veränderlichen lokalen Speicher der Anforderung gespeichert sind.
public function removeAttributes(): array
Entfernt alle Anforderungsattribute aus dem veränderlichen lokalen Speicher der Anforderung.
public function hasAttribute( string $ name ): bool
Überprüfen Sie, ob ein Attribut mit dem angegebenen Namen im veränderbaren lokalen Speicher der Anforderung vorhanden ist.
public function getAttribute( string $ name ): mixed
Rufen Sie eine Variable aus dem veränderlichen lokalen Speicher der Anforderung ab.
Hinweis Der Name des Attributs sollte wie Klassen einen Namensraum mit einem Hersteller- und Paket-Namensraum haben.
public function setAttribute( string $ name , mixed $ value ): void
Weisen Sie dem veränderlichen lokalen Speicher der Anforderung eine Variable zu.
Hinweis Der Name des Attributs sollte wie Klassen einen Namensraum mit einem Hersteller- und Paket-Namensraum haben.
public function removeAttribute( string $ name ): void
Entfernt eine Variable aus dem veränderlichen lokalen Speicher der Anforderung.
public function getTrailers(): Trailers
Ermöglicht den Zugriff auf die Trailers
einer Anfrage.
public function setTrailers( Trailers $ trailers ): void
Weist das Trailers
-Objekt zu, das in der Anfrage verwendet werden soll.
Clientbezogene Details werden in AmpHttpServerDriverClient
Objekten gebündelt, die von Request::getClient()
zurückgegeben werden. Die Client
Schnittstelle bietet Methoden zum Abrufen der Remote- und lokalen Socket-Adressen und TLS-Informationen (falls zutreffend).
Response
Die Response
Klasse stellt eine HTTP-Antwort dar. Eine Response
wird von Anforderungshandlern und Middleware zurückgegeben.
/**
* @param int $code The HTTP response status code.
* @param array<string>|array<string, array<string>> $headers An array of strings or an array of string arrays.
*/
public function __construct(
int $ code = HttpStatus:: OK ,
array $ headers = [],
Amp ByteStream ReadableStream | string $ body = '' ,
? Trailers $ trailers = null ,
)
Ruft Dispose-Handler auf (d. h. Funktionen, die über die Methode onDispose()
registriert wurden).
Hinweis Nicht abgefangene Ausnahmen von den Dispose-Handlern werden an den Ereignisschleifen-Fehlerhandler weitergeleitet.
public function getBody(): Amp ByteStream ReadableStream
Gibt den Stream für den Nachrichtentext zurück.
public function setBody( Amp ByteStream ReadableStream | string $ body )
Legt den Stream für den Nachrichtentext fest.
Hinweis Durch die Verwendung einer Zeichenfolge wird der
Content-Length
-Header automatisch auf die Länge der angegebenen Zeichenfolge festgelegt. Durch das Festlegen einesReadableStream
wird derContent-Length
Header entfernt. Wenn Sie die genaue Inhaltslänge Ihres Streams kennen, können Sie nach dem Aufruf vonsetBody()
einen Headercontent-length
hinzufügen.
/** @return array<non-empty-string, list<string>> */
public function getHeaders(): array
Gibt die Header als stringindiziertes Array von String-Arrays oder als leeres Array zurück, wenn keine Header festgelegt wurden.
public function hasHeader( string $ name ): bool
Überprüft, ob der angegebene Header vorhanden ist.
/** @return list<string> */
public function getHeaderArray( string $ name ): array
Gibt das Wertearray für den angegebenen Header oder ein leeres Array zurück, wenn der Header nicht vorhanden ist.
public function getHeader( string $ name ): ? string
Gibt den Wert des angegebenen Headers zurück. Wenn für den benannten Header mehrere Header vorhanden sind, wird nur der erste Header-Wert zurückgegeben. Verwenden Sie getHeaderArray()
um ein Array aller Werte für den jeweiligen Header zurückzugeben. Gibt null
zurück, wenn der Header nicht vorhanden ist.
public function setHeaders( array $ headers ): void
Legt die Header aus dem angegebenen Array fest.
/** @param array<string>|string $value */
public function setHeader( string $ name , array | string $ value ): void
Setzt den Header auf die angegebenen Werte. Alle bisherigen Kopfzeilen mit dem angegebenen Namen werden ersetzt.
/** @param array<string>|string $value */
public function addHeader( string $ name , array | string $ value ): void
Fügt eine zusätzliche Kopfzeile mit dem angegebenen Namen hinzu.
public function removeHeader( string $ name ): void
Entfernt den angegebenen Header, falls vorhanden. Wenn mehrere Kopfzeilen mit demselben Namen vorhanden sind, werden alle entfernt.
public function getStatus(): int
Gibt den Antwortstatuscode zurück.
public function getReason(): string
Gibt den Grundsatz zurück, der den Statuscode beschreibt.
public function setStatus( int $ code , string | null $ reason ): void
Legt den numerischen HTTP-Statuscode (zwischen 100 und 599) und den Grundsatz fest. Verwenden Sie null als Begründungsphrase, um die mit dem Statuscode verknüpfte Standardphrase zu verwenden.
/** @return array<non-empty-string, ResponseCookie> */
public function getCookies(): array
Gibt alle Cookies in einer assoziativen Zuordnung des Cookie-Namens an ResponseCookie
zurück.
public function getCookie( string $ name ): ? ResponseCookie
Ruft einen Cookie-Wert nach Namen ab oder null
wenn kein Cookie mit diesem Namen vorhanden ist.
public function setCookie( ResponseCookie $ cookie ): void
Fügt der Antwort ein Cookie hinzu.
public function removeCookie( string $ name ): void
Entfernt ein Cookie aus der Antwort.
/** @return array<string, Push> Map of URL strings to Push objects. */
public function getPushes(): array
Gibt eine Liste von Push-Ressourcen in einer assoziativen Zuordnung von URL-Zeichenfolgen zu Push
-Objekten zurück.
/** @param array<string>|array<string, array<string>> $headers */
public function push( string $ url , array $ headers ): void
Geben Sie Ressourcen an, die ein Client wahrscheinlich abrufen muss. (z. B. Link: preload
oder HTTP/2 Server Push).
public function isUpgraded(): bool
Gibt true
zurück, wenn ein Detach-Callback festgelegt wurde, false
, wenn keiner festgelegt wurde.
/** @param Closure(DriverUpgradedSocket, Request, Response): void $upgrade */
public function upgrade( Closure $ upgrade ): void
Legt einen Rückruf fest, der aufgerufen wird, sobald die Antwort an den Client geschrieben wurde, und ändert den Status der Antwort in 101 Switching Protocols
. Der Rückruf empfängt eine Instanz von DriverUpgradedSocket
, die Request
, die das Upgrade initiiert hat, und diese Response
.
Der Rückruf kann entfernt werden, indem der Status auf einen anderen Wert als 101 geändert wird.
public function getUpgradeCallable(): ? Closure
Gibt die Upgrade-Funktion zurück, falls vorhanden.
/** @param Closure():void $onDispose */
public function onDispose( Closure $ onDispose ): void
Registriert eine Funktion, die aufgerufen wird, wenn die Antwort verworfen wird. Eine Antwort wird entweder verworfen, sobald sie an den Client geschrieben wurde oder wenn sie in einer Middleware-Kette ersetzt wird.
public function getTrailers(): Trailers
Ermöglicht den Zugriff auf die Trailers
einer Antwort.
public function setTrailers( Trailers $ trailers ): void
Weist das Trailers
-Objekt zu, das in der Antwort verwendet werden soll. Trailer werden gesendet, sobald der gesamte Antworttext für den Client festgelegt wurde.
RequestBody
, zurückgegeben von Request::getBody()
, bietet gepufferten und gestreamten Zugriff auf den Anforderungstext. Verwenden Sie den gestreamten Zugriff, um große Nachrichten zu verarbeiten. Dies ist besonders wichtig, wenn Sie über größere Nachrichtengrenzen verfügen (z. B. mehrere zehn Megabyte) und nicht alles im Speicher puffern möchten. Wenn mehrere Personen gleichzeitig große Körper hochladen, kann der Speicher schnell erschöpft sein.
Daher ist die inkrementelle Verarbeitung wichtig und über die read()
-API von AmpByteStreamReadableStream
zugänglich.
Falls ein Client die Verbindung trennt, schlägt read()
mit einer AmpHttpServerClientException
fehl. Diese Ausnahme wird sowohl für die read()
als auch buffer()
API ausgelöst.
Hinweis
ClientException
s müssen nicht abgefangen werden. Sie können sie fangen, wenn Sie fortfahren möchten, müssen es aber nicht. Der Server beendet den Anforderungszyklus stillschweigend und verwirft diese Ausnahme.
Anstatt das generische Body-Limit hoch festzulegen, sollten Sie erwägen, das Body-Limit nur dort zu erhöhen, wo es erforderlich ist. Dies ist mit der Methode increaseSizeLimit()
für RequestBody
dynamisch möglich.
Hinweis:
RequestBody
selbst bietet keine Analyse von Formulardaten. Bei Bedarf können Sieamphp/http-server-form-parser
verwenden.
Wie bei Request
ist es selten erforderlich, eine RequestBody
-Instanz zu erstellen, da eine solche als Teil der Request
bereitgestellt wird.
public function __construct(
ReadableStream | string $ stream ,
? Closure $ upgradeSize = null ,
)
public function increaseSizeLimit( int $ limit ): void
Erhöht die Körpergrößenbeschränkung dynamisch, um es einzelnen Anforderungshandlern zu ermöglichen, größere Anforderungskörper als die Standardeinstellung für den HTTP-Server zu verarbeiten.
Die Trailers
-Klasse ermöglicht den Zugriff auf die Trailer einer HTTP-Anfrage, auf die über Request::getTrailers()
zugegriffen werden kann. null
wird zurückgegeben, wenn bei der Anfrage keine Trailer erwartet werden. Trailers::await()
gibt einen Future
zurück, der mit einem HttpMessage
Objekt aufgelöst wird, das Methoden für den Zugriff auf die Trailer-Header bereitstellt.
$ trailers = $ request -> getTrailers ();
$ message = $ trailers ?->await();
Der HTTP-Server wird nicht der Flaschenhals sein. Fehlkonfiguration, Verwendung blockierender E/A oder ineffiziente Anwendungen sind die Ursache.
Der Server ist gut optimiert und kann auf typischer Hardware Zehntausende von Anfragen pro Sekunde verarbeiten und gleichzeitig ein hohes Maß an Parallelität von Tausenden von Clients aufrechterhalten.
Bei ineffizienten Anwendungen nimmt diese Leistung jedoch drastisch ab. Der Server hat den schönen Vorteil, dass Klassen und Handler immer geladen werden, sodass beim Kompilieren und Initialisieren keine Zeit verloren geht.
Eine häufige Falle besteht darin, große Datenmengen mit einfachen String-Operationen zu bearbeiten, was viele ineffiziente große Kopien erfordert. Stattdessen sollte bei größeren Anfrage- und Antworttexten nach Möglichkeit Streaming verwendet werden.
Das Problem sind wirklich die CPU-Kosten. Ineffizientes I/O-Management (solange es nicht blockierend ist!) verzögert lediglich einzelne Anfragen. Es wird empfohlen, mehrere unabhängige I/O-Anfragen gleichzeitig zu versenden und schließlich über die Kombinatoren von Amp zu bündeln, aber ein langsamer Handler verlangsamt auch jede andere Anfrage. Während ein Handler rechnet, können alle anderen Handler nicht fortfahren. Daher ist es zwingend erforderlich, die Rechenzeiten der Handler auf ein Minimum zu reduzieren.
Mehrere Beispiele finden Sie im Verzeichnis ./examples
des Repositorys. Diese können als normale PHP-Skripte auf der Kommandozeile ausgeführt werden.
php examples/hello-world.php
Anschließend können Sie in Ihrem Browser auf den Beispielserver unter http://localhost:1337/
zugreifen.
Wenn Sie sicherheitsrelevante Probleme entdecken, verwenden Sie bitte den privaten Sicherheitsproblem-Reporter anstelle des öffentlichen Problem-Trackers.
Die MIT-Lizenz (MIT). Weitere Informationen finden Sie unter LIZENZ.