説明

workermanは4.xバージョンからHTTPサービスのサポートを強化しました。リクエストクラス、レスポンスクラス、セッションクラス、そしてSSEが導入されました。workermanのHTTPサービスを使用したい場合は、workerman4.xまたはそれ以降のバージョンを使用することを強くお勧めします。

注意:以下はすべてworkerman4.xバージョンの使用方法であり、workerman3.xとは互換性がありません。

注意

  • チャンクまたはSSEレスポンスを送信する場合を除き、1つのリクエスト内で複数回レスポンスを送信することはできません。つまり、1つのリクエスト内で$connection->send()を複数回呼び出すことは許可されていません。
  • 各リクエストは最終的に1回$connection->send()を呼び出してレスポンスを送信する必要があります。そうしないと、クライアントはずっと待機します。

快適なレスポンス

HTTPステータスコード(デフォルトは200)やカスタムヘッダー、クッキーを変更する必要がない場合、クライアントに文字列を直接送信してレスポンスを完了できます。

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)
{
    // 直接"this is body"をクライアントに送信
    $connection->send("this is body");
};

// workerを実行
Worker::runAll();

ステータスコードの変更

カスタムステータスコード、ヘッダー、クッキーを設定する必要がある場合、Workerman\Protocols\Http\Responseレスポンスクラスを使用する必要があります。以下の例では、パス/404にアクセスしたときに404のステータスコードを返し、ボディの内容は<h1>申し訳ありません、ファイルが存在しません</h1>です。

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>申し訳ありません、ファイルが存在しません</h1>'));
    } else {
        $connection->send('this is body');
    }
};

// workerを実行
Worker::runAll();

Responseクラスが初期化された後、ステータスコードを変更するには次の方法を使用します。

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

ヘッダーの送信

同様に、ヘッダーを送信するためにはWorkerman\Protocols\Http\Responseレスポンスクラスを使用する必要があります。

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);
};

// workerを実行
Worker::runAll();

Responseクラスが初期化された後、ヘッダーを追加または変更するには次の方法を使用します。

$response = new Response(200);
// ヘッダーを1つ追加または変更
$response->header('Content-Type', 'text/html');
// 複数のヘッダーを追加または変更
$response->withHeaders([
    'Content-Type' => 'application/ json',
    'X-Header-One' => 'Header Value'
]);
$connection->send($response);

リダイレクト

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();

クッキーの送信

同様に、クッキーを送信するためにはWorkerman\Protocols\Http\Responseレスポンスクラスを使用する必要があります。

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);
};

// workerを実行
Worker::runAll();

ファイルの送信

同様に、ファイルを送信するためにはWorkerman\Protocols\Http\Responseレスポンスクラスを使用する必要があります。

ファイルを送信する場合は、次の方法を使用します。

$response = (new Response())->withFile($file);
$connection->send($response);
  • workermanは超大容量ファイルの送信をサポートします。
  • 大きなファイル(2Mを超える)について、workermanは全体を一度にメモリに読み込まず、適切なタイミングでファイルを部分的に読み込み送信します。
  • workermanはクライアントの受信速度に基づいてファイルの読み込みと送信速度を最適化し、最も迅速にファイルを送信しつつ、メモリ使用量を最小限に抑えます。
  • データの送信は非ブロッキングであり、他のリクエストの処理に影響を与えません。
  • ファイルを送信するときは、自動的にLast-Modifiedヘッダーが追加され、次回のリクエスト時にサーバーが304レスポンスを送信してファイル転送を節約し、パフォーマンスを向上させます。
  • 送信されるファイルは自動的に適切なContent-Typeヘッダーを使ってブラウザに送信されます。
  • ファイルが存在しない場合は、自動的に404レスポンスに変換されます。

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';
    // if-modified-sinceヘッダーでファイルが変更されているか確認する
    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();
        // ファイルが変更されていなければ304を返す
        if ($modified_time === $if_modified_since) {
            $connection->send(new Response(304));
            return;
        }
    }
    // ファイルが変更されているかif-modified-sinceヘッダーがない場合はファイルを送信
    $response = (new Response())->withFile($file);
    $connection->send($response);
};

// workerを実行
Worker::runAll();

HTTPチャンクデータの送信

  • 最初にTransfer-Encoding: chunkedヘッダーを含むResponseレスポンスをクライアントに送信する必要があります。
  • 続くチャンクデータはWorkerman\Protocols\Http\Chunkクラスを使用して送信します。
  • 最後には空のチャンクを送信してレスポンスを終了する必要があります。

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)
{
    // 最初にTransfer-Encoding: chunkedヘッダーを含むResponseレスポンスを送信
    $connection->send(new Response(200, array('Transfer-Encoding' => 'chunked'), 'hello'));
    // 続くチャンクデータはWorkerman\Protocols\Http\Chunkクラスを使用して送信
    $connection->send(new Chunk('第一段データ'));
    $connection->send(new Chunk('第二段データ'));
    $connection->send(new Chunk('第三段データ'));
   // 最後には空のチャンクを送信してレスポンスを終了
    $connection->send(new Chunk(''));
};

// workerを実行
Worker::runAll();