Description
Workerman a renforcé le support des services HTTP à partir de la version 4.x. Des classes comme Request, Response, Session ainsi que SSE ont été introduites. Si vous souhaitez utiliser le service HTTP de Workerman, il est fortement recommandé d'utiliser Workerman 4.x ou une version ultérieure.
Remarque : toutes les utilisations suivantes concernent la version Workerman 4.x, qui n'est pas compatible avec Workerman 3.x.
Remarques
- À moins d'envoyer un chunk ou une réponse SSE, il n'est pas permis d'envoyer plusieurs réponses dans une même requête, c'est-à-dire que
send()ne peut pas être appelé plusieurs fois pour une même connexion. - Chaque requête doit finalement appeler
send()une fois pour envoyer la réponse, sinon le client restera en attente.
Réponse rapide
Lorsque vous n'avez pas besoin de modifier le code d'état HTTP (par défaut 200), ou d'ajouter des en-têtes personnalisés ou des cookies, vous pouvez directement envoyer une chaîne au client pour terminer la réponse.
Exemple
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)
{
// Envoyer directement "this is body" au client
$connection->send("this is body");
};
// Exécuter le worker
Worker::runAll();
Changer le code d'état
Pour personnaliser le code d'état, les en-têtes et les cookies, vous devez utiliser la classe de réponse Workerman\Protocols\Http\Response. Par exemple, le code ci-dessous renvoie un code d'état 404 lorsque le chemin d'accès est /404, avec le contenu <h1>Désolé, le fichier n'existe pas</h1>.
Exemple
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>Désolé, le fichier n'existe pas</h1>'));
} else {
$connection->send('this is body');
}
};
// Exécuter le worker
Worker::runAll();
Lorsque la classe Response est déjà initialisée, pour changer le code d'état utilisez la méthode suivante.
$response = new Response(200);
$response->withStatus(404);
$connection->send($response);
Envoyer des en-têtes
De même, pour envoyer des en-têtes, il faut utiliser la classe de réponse Workerman\Protocols\Http\Response.
Exemple
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 Value'
], 'this is body');
$connection->send($response);
};
// Exécuter le worker
Worker::runAll();
Après l'initialisation de la classe Response, pour ajouter ou modifier un en-tête utilisez la méthode suivante.
$response = new Response(200);
// Ajouter ou modifier un en-tête
$response->header('Content-Type', 'text/html');
// Ajouter ou modifier plusieurs en-têtes
$response->withHeaders([
'Content-Type' => 'application/json',
'X-Header-One' => 'Header Value'
]);
$connection->send($response);
Redirection
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();
Envoyer des cookies
De même, pour envoyer des cookies, il faut utiliser la classe de réponse Workerman\Protocols\Http\Response.
Exemple
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);
};
// Exécuter le worker
Worker::runAll();
Envoyer des fichiers
De même, pour envoyer des fichiers, utilisez la classe de réponse Workerman\Protocols\Http\Response.
Pour envoyer un fichier, utilisez la méthode suivante :
$response = (new Response())->withFile($file);
$connection->send($response);
- Workerman prend en charge l'envoi de très gros fichiers.
- Pour les gros fichiers (plus de 2 Mo), Workerman ne charge pas le fichier entier en mémoire d'un coup, mais le lit en segments et l'envoie au bon moment.
- Workerman optimisera la vitesse de lecture et d'envoi des fichiers en fonction de la vitesse de réception du client, garantissant ainsi un envoi rapide tout en minimisant l'utilisation de la mémoire.
- L'envoi de données est non-bloquant et n'affectera pas le traitement des autres requêtes.
- Lors de l'envoi de fichiers, l'en-tête
Last-Modifiedsera automatiquement ajouté pour permettre au serveur de décider d'envoyer une réponse 304 lors de la prochaine requête, afin d'économiser le transfert de fichiers et d'améliorer les performances. - Les fichiers envoyés auront automatiquement l'en-tête
Content-Typeapproprié envoyé au navigateur. - Si le fichier n'existe pas, il sera automatiquement transformé en réponse 404.
Exemple
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';
// Vérifiez l'en-tête if-modified-since pour déterminer si le fichier a été modifié
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();
// Si le fichier n'a pas été modifié, renvoyez 304
if ($modified_time === $if_modified_since) {
$connection->send(new Response(304));
return;
}
}
// Si le fichier a été modifié ou si l'en-tête if-modified-since n'est pas présent, envoyez le fichier
$response = (new Response())->withFile($file);
$connection->send($response);
};
// Exécuter le worker
Worker::runAll();
Envoyer des données HTTP en chunks
- Vous devez d'abord envoyer une réponse avec l'en-tête
Transfer-Encoding: chunkedau client. - Pour envoyer les données chunk suivantes, utilisez la classe
Workerman\Protocols\Http\Chunk. - Finalement, vous devez envoyer un chunk vide pour terminer la réponse.
Exemple
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)
{
// Envoyez d'abord une réponse avec l'en-tête Transfer-Encoding: chunked
$connection->send(new Response(200, array('Transfer-Encoding' => 'chunked'), 'hello'));
// Les données chunk suivantes sont envoyées avec Workerman\Protocols\Http\Chunk
$connection->send(new Chunk('Première partie des données'));
$connection->send(new Chunk('Deuxième partie des données'));
$connection->send(new Chunk('Troisième partie des données'));
// Finalement, vous devez envoyer un chunk vide pour terminer la réponse
$connection->send(new Chunk(''));
};
// Exécuter le worker
Worker::runAll();