RRelayer
ホーム/ルーティング

ミドルウェアと CORS#

src/Pages/middleware.php(任意)は、全ルートのディスパッチを 1 つのクロージャでラップします。

<?php
use Polidog\Relayer\Http\Request;

return function (Request $request, Closure $next): void {
    if (null === $request->header('x-api-key')) {
        \http_response_code(401);
        echo '{"error":"missing api key"}';

        return; // $next() を呼ばなければショートサーキット
    }

    $next($request);
};
  • クロージャは 1 つだけ。チェーンランナーはなく、複数走らせたいときは

手で合成します(複数のミドルウェアを合成する)。

  • route.php 同様、宣言禁止(return のみ、毎リクエスト評価)。
  • $next($request) を呼ばなければ後段を実行せず終了(401 / 429 など)。
  • フレームワークの defer / プロファイラのエンドポイントは意図的に

このミドルウェアの外で動きます。

CORS#

CORS は手書きせず、組み込みミドルウェアを使います。

<?php
use Polidog\Relayer\Http\Cors;

return Cors::middleware([
    'origins' => ['https://app.example.com'],
    // 'methods', 'headers', 'credentials', 'maxAge' は任意
]);

すべてのオリジンを許可する場合は ['origins' => ['*']]。プリフライト(OPTIONS)への応答も Cors::middleware() が処理します。

複数のミドルウェアを合成する#

middleware.php が返せるクロージャは 1 本だけで、チェーンランナーはありません(設計)。複数の処理を重ねたいときは、外側のクロージャの $next に内側のミドルウェアを噛ませて手で合成します。各ミドルウェアのシグネチャは同じ fn(Request $request, Closure $next) なので、内側を「次へ進む処理」として渡すだけです。

最小形:

<?php
// a が外側、b が内側、その後に実ルート
return fn (Request $r, Closure $next) => $a($r, fn (Request $r) => $b($r, $next));

実用例 — リクエスト ID を付与してから CORS に委譲し、最後にルートへ:

<?php
declare(strict_types=1);

use Polidog\Relayer\Http\Cors;
use Polidog\Relayer\Http\Request;

$cors = Cors::middleware([
    'origins' => ['*'],
    'methods' => ['GET', 'POST', 'OPTIONS'],
]);

return function (Request $request, Closure $next) use ($cors): void {
    if (!\headers_sent()) {
        \header('X-Request-Id: ' . \bin2hex(\random_bytes(8)));
    }

    // $cors が OPTIONS プリフライトには自分で応答し、実リクエストでは
    // ヘッダを付けて $next(実ルート)へ続ける。
    $cors($request, $next);
};

要点:

  • 実行順は外側から内側へ$next($request) を呼ぶ前に書いた処理が

前処理、呼んだ後に書いた処理が後処理(戻りがけ)になります。

  • 短絡はどの層でも可能。ある層が $next を呼ばなければ、それより

内側のミドルウェアもルートも実行されません(認証 401・レート制限 429・メンテナンス・CORS プリフライト等)。

  • $next には別の Request を渡せます。ある層で

$next($request->withPath(...)) のように差し替えると、内側とルートはその差し替え後のリクエストを見ます。

  • 3 本以上も同じ入れ子で合成できます:

fn ($r, $n) => $a($r, fn ($r) => $b($r, fn ($r) => $c($r, $n)))。各 $a/$b/$cfn(Request, Closure) 契約のミドルウェアです。

最終更新: 2026-05-20
変更履歴 (2)
  • 複数ミドルウェアの手組み合成セクションを追加
  • 新規作成