Descrizione
A partire dalla versione 4.x, Workerman ha migliorato il supporto per i servizi HTTP. Sono state introdotte le classi per le richieste, le risposte, le sessioni e SSE. Se desideri utilizzare il servizio HTTP di Workerman, si raccomanda vivamente di usare Workerman 4.x o versioni successive.
Nota: quanto segue si riferisce all'uso della versione 4.x di Workerman, non compatibile con Workerman 3.x.
Avvertenza
- A meno che non si stia inviando una risposta chunk o SSE, non è consentito inviare più risposte in una singola richiesta, ovvero non è permesso chiamare più volte
$connection->send()in una richiesta. - Ogni richiesta deve infine chiamare
$connection->send()per inviare la risposta, altrimenti il client rimarrà in attesa.
Risposta rapida
Quando non è necessario modificare il codice di stato HTTP (il predefinito è 200), o personalizzare header, cookie, è possibile inviare direttamente una stringa al client per completare la risposta.
Esempio
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)
{
// Invia direttamente "this is body" al client
$connection->send("this is body");
};
// Esegui il worker
Worker::runAll();
Modifica del codice di stato
Quando è necessario personalizzare il codice di stato, l'header o i cookie, è necessario utilizzare la classe di risposta Workerman\Protocols\Http\Response. Ad esempio, il seguente esempio restituisce un codice di stato 404 quando si accede al percorso /404, con il contenuto del corpo <h1>Spiacente, file non trovato</h1>.
Esempio
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>Spiacente, file non trovato</h1>'));
} else {
$connection->send('this is body');
}
};
// Esegui il worker
Worker::runAll();
Quando la classe Response è già stata inizializzata e si desidera modificare il codice di stato, utilizzare il seguente metodo:
$response = new Response(200);
$response->withStatus(404);
$connection->send($response);
Inviare header
Allo stesso modo, per inviare header è necessaria la classe Workerman\Protocols\Http\Response.
Esempio
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);
};
// Esegui il worker
Worker::runAll();
Quando la classe Response è già stata inizializzata e si desidera aggiungere o modificare un header, utilizzare il seguente metodo:
$response = new Response(200);
// Aggiungi o modifica un header
$response->header('Content-Type', 'text/html');
// Aggiungi o modifica più header
$response->withHeaders([
'Content-Type' => 'application/json',
'X-Header-One' => 'Header Value'
]);
$connection->send($response);
Reindirizzamento
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);
};
// Esegui il worker
Worker::runAll();
Inviare cookie
Allo stesso modo, per inviare cookie è necessaria la classe Workerman\Protocols\Http\Response.
Esempio
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);
};
// Esegui il worker
Worker::runAll();
Inviare file
Allo stesso modo, per inviare file è necessaria la classe Workerman\Protocols\Http\Response.
Per inviare un file, utilizzare il seguente modo:
$response = (new Response())->withFile($file);
$connection->send($response);
- Workerman supporta l'invio di file molto grandi.
- Per file di grandi dimensioni (superiori a 2M), Workerman non leggerà l'intero file in memoria tutto in una volta, ma leggerà e invierà il file in segmenti al momento opportuno.
- Workerman ottimizzerà la velocità di lettura e invio del file in base alla velocità di ricezione del client, garantendo l'invio del file nel più breve tempo possibile riducendo al minimo l'uso della memoria.
- L'invio dei dati è non bloccante e non influisce sul trattamento delle altre richieste.
- Durante l'invio di un file, verrà automaticamente aggiunto l'intestazione
Last-Modified, in modo che il server possa determinare se inviare una risposta 304 per risparmiare sul trasferimento dei file e migliorare le prestazioni. - I file inviati verranno automaticamente inviati al browser con l'intestazione
Content-Typeappropriata. - Se il file non esiste, verrà automaticamente convertito in una risposta 404.
Esempio
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';
// Controlla l'intestazione if-modified-since per verificare se il file è stato modificato
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();
// Se il file non è stato modificato, restituisci 304
if ($modified_time === $if_modified_since) {
$connection->send(new Response(304));
return;
}
}
// Se il file è stato modificato o non c'è un'intestazione if-modified-since, invia il file
$response = (new Response())->withFile($file);
$connection->send($response);
};
// Esegui il worker
Worker::runAll();
Inviare dati HTTP chunk
- È necessario inviare prima una risposta contenente l'intestazione
Transfer-Encoding: chunkedal client. - I successivi dati di chunk possono essere inviati utilizzando la classe
Workerman\Protocols\Http\Chunk. - Infine, è necessario inviare un chunk vuoto per terminare la risposta.
Esempio
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)
{
// Invia prima una risposta con intestazione Transfer-Encoding: chunked
$connection->send(new Response(200, array('Transfer-Encoding' => 'chunked'), 'hello'));
// I dati chunk successivi vengono inviati utilizzando la classe Workerman\Protocols\Http\Chunk
$connection->send(new Chunk('Primo chunk di dati'));
$connection->send(new Chunk('Secondo chunk di dati'));
$connection->send(new Chunk('Terzo chunk di dati'));
// Infine, invia un chunk vuoto per terminare la risposta
$connection->send(new Chunk(''));
};
// Esegui il worker
Worker::runAll();