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-Type appropriata.
  • 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: chunked al 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();