Hinweise

Workerman hat mit der Version 4.x die Unterstützung für HTTP-Services verbessert. Es wurden Klassen für Anfragen, Antworten, Sessions sowie SSE eingeführt. Wenn Sie die HTTP-Dienste von Workerman verwenden möchten, wird dringend empfohlen, Workerman 4.x oder eine spätere Version zu verwenden.

Bitte beachten Sie, dass die folgenden Beispiele für die Version Workerman 4.x gelten und nicht mit Workerman 3.x kompatibel sind.

Wichtig

  • Es ist nicht erlaubt, mehrere Antworten innerhalb einer Anfrage zu senden, es sei denn, es handelt sich um chunked oder SSE-Antworten, das heißt, $connection->send() darf nicht mehrmals innerhalb einer Anfrage aufgerufen werden.
  • Jede Anfrage muss letztendlich einmal $connection->send() aufrufen, um eine Antwort zu senden, andernfalls wird der Client weiterhin warten.

Schnelle Antwort

Wenn der HTTP-Statuscode (standardmäßig 200) oder benutzerdefinierte Header und Cookies nicht geändert werden müssen, kann einfach ein String an den Client gesendet werden, um die Antwort abzuschließen.

Beispiel

use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('http://0.0.0.0:8080');

$worker->onMessage = function(TcpConnection $connection, Request $request)
{
    // Direkt "this is body" an den Client senden
    $connection->send("this is body");
};

// Arbeiter starten
Worker::runAll();

Statuscode ändern

Wenn benutzerdefinierte Statuscodes, Header oder Cookies verwendet werden müssen, sollte die Klasse Workerman\Protocols\Http\Response verwendet werden. Im folgenden Beispiel wird bei einem Zugriff auf den Pfad /404 der Statuscode 404 zurückgegeben, und der Body-Inhalt ist <h1>Entschuldigung, Datei nicht gefunden</h1>.

Beispiel

use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('http://0.0.0.0:8080');

$worker->onMessage = function(TcpConnection $connection, Request $request)
{
    if ($request->path() === '/404') {
        $connection->send(new Response(404, [], '<h1>Entschuldigung, Datei nicht gefunden</h1>'));
    } else {
        $connection->send('this is body');
    }
};

// Arbeiter starten
Worker::runAll();

Wenn die Response-Klasse bereits initialisiert wurde, kann der Statuscode wie folgt geändert werden.

$response = new Response(200);
$response->withStatus(404);
$connection->send($response);

Header senden

Um Header zu senden, muss ebenfalls die Klasse Workerman\Protocols\Http\Response verwendet werden.

Beispiel

use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('http://0.0.0.0:8080');

$worker->onMessage = function(TcpConnection $connection, Request $request)
{
    $response = new Response(200, [
        'Content-Type' => 'text/html',
        'X-Header-One' => 'Header-Wert'
    ], 'this is body');
    $connection->send($response);
};

// Arbeiter starten
Worker::runAll();

Wenn die Response-Klasse bereits initialisiert wurde, können Header wie folgt hinzugefügt oder geändert werden.

$response = new Response(200);
// Einen Header hinzufügen oder ändern
$response->header('Content-Type', 'text/html');
// Mehrere Header hinzufügen oder ändern
$response->withHeaders([
    'Content-Type' => 'application/json',
    'X-Header-One' => 'Header-Wert'
]);
$connection->send($response);

Weiterleitung

use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('http://0.0.0.0:8080');

$worker->onMessage = function(TcpConnection $connection, Request $request)
{
    $location = '/test_location';
    $response = new Response(302, ['Location' => $location]);
    $connection->send($response);
};
Worker::runAll();

Cookie senden

Um Cookies zu senden, sollte ebenfalls die Klasse Workerman\Protocols\Http\Response verwendet werden.

Beispiel

use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('http://0.0.0.0:8080');

$worker->onMessage = function(TcpConnection $connection, Request $request)
{
    $response = new Response(200, [], 'this is body');
    $response->cookie('name', 'tom');
    $connection->send($response);
};

// Arbeiter starten
Worker::runAll();

Datei senden

Um Dateien zu senden, muss ebenfalls die Klasse Workerman\Protocols\Http\Response verwendet werden.

Um eine Datei zu senden, verwenden Sie die folgende Methode:

$response = (new Response())->withFile($file);
$connection->send($response);
  • Workerman unterstützt das Senden von sehr großen Dateien.
  • Bei großen Dateien (über 2 MB) wird Workerman die gesamte Datei nicht auf einmal in den Speicher lesen, sondern in geeigneten Zeitfenstern segmentiert lesen und senden.
  • Workerman optimiert die Dateilesegeschwindigkeit basierend auf der Empfangsgeschwindigkeit des Clients, um die Dateien so schnell wie möglich zu senden und gleichzeitig den Speicherbedarf zu minimieren.
  • Der Datentransfer ist nicht blockierend und beeinträchtigt nicht die Verarbeitung anderer Anfragen.
  • Beim Senden von Dateien wird automatisch der Last-Modified-Header hinzugefügt, damit der Server beim nächsten Request entscheiden kann, ob eine 304-Antwort gesendet werden soll, um die Dateitransfergeschwindigkeit zu verbessern.
  • Die gesendete Datei wird automatisch mit dem geeigneten Content-Type-Header an den Browser gesendet.
  • Wenn die Datei nicht existiert, wird automatisch eine 404-Antwort gesendet.

Beispiel

use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('http://0.0.0.0:8080');

$worker->onMessage = function(TcpConnection $connection, Request $request)
{
    $file = '/your/path/of/file';
    // Überprüfen des if-modified-since-Headers, um zu bestimmen, ob die Datei geändert wurde
    if (!empty($if_modified_since = $request->header('if-modified-since'))) {
        $modified_time = date('D, d M Y H:i:s',  filemtime($file)) . ' ' . \date_default_timezone_get();
        // Wenn die Datei nicht geändert wurde, senden Sie 304 zurück
        if ($modified_time === $if_modified_since) {
            $connection->send(new Response(304));
            return;
        }
    }
    // Wenn die Datei geändert wurde oder kein if-modified-since-Header vorhanden ist, senden Sie die Datei
    $response = (new Response())->withFile($file);
    $connection->send($response);
};

// Arbeiter starten
Worker::runAll();

HTTP Chunk-Daten senden

  • Zuerst muss eine Antwort mit dem Header Transfer-Encoding: chunked an den Client gesendet werden.
  • Verwenden Sie für die nachfolgenden Chunk-Daten die Klasse Workerman\Protocols\Http\Chunk.
  • Schließlich muss ein leerer Chunk gesendet werden, um die Antwort zu beenden.

Beispiel

use Workerman\Worker;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;
use Workerman\Protocols\Http\Chunk;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker('http://0.0.0.0:8080');

$worker->onMessage = function(TcpConnection $connection, Request $request)
{
    // Zuerst eine Antwort mit dem Header Transfer-Encoding: chunked senden
    $connection->send(new Response(200, array('Transfer-Encoding' => 'chunked'), 'hello'));
    // Nachfolgende Chunk-Daten verwenden die Klasse Workerman\Protocols\Http\Chunk
    $connection->send(new Chunk('Erster Datenabschnitt'));
    $connection->send(new Chunk('Zweiter Datenabschnitt'));
    $connection->send(new Chunk('Dritter Datenabschnitt'));
   // Schließlich muss ein leerer Chunk gesendet werden, um die Antwort zu beenden
    $connection->send(new Chunk(''));
};

// Arbeiter starten
Worker::runAll();