Laravelのメンテナンスモードの挙動を確認した際のメモを備忘録として残します。
- メンテナンスモードのコマンド実行
-
storage/framework/down
というJSONファイルが作成される
{
"except": [],
"redirect": null,
"retry": null,
"refresh": null,
"secret": null,
"status": 503,
"template": null
}
フィールド | 意味 |
---|---|
except |
メンテナンスモード中でも通常の処理を許可するルートの URI パターン一覧。 Laravel 標準の down コマンドでは設定できない。PreventRequestsDuringMaintenance ミドルウェアをオーバーライドし、その $except プロパティにパスを追加するとここに反映される。デフォルトは空配列。 |
redirect |
メンテナンス中の全リクエストをリダイレクトする先 URI。php artisan down --redirect=/ のように指定すると、すべてのアクセスが /{} にリダイレクトされる。(artisan.page) |
retry |
HTTP レスポンスヘッダ Retry-After にセットする秒数。〈例:--retry=60 〉。ほとんどのブラウザは無視しますが、API クライアントなどには伝わるらしい。(Laravel) |
refresh |
HTML レスポンスに Refresh ヘッダをセットし、指定秒後に自動リロードを指示。〈例:--refresh=15 〉。(Laravel) |
secret |
メンテバイパス用のトークン文字列。例として --secret="abc123" とすると、https://your-app/abc123 に一度アクセスすることでバイパスクッキーが発行され、以降通常モードで閲覧できる。(Laravel) |
status |
HTTP ステータスコード。デフォルトは 503 ですが、--status=402 のように変更可能(あまり使われないらしい)。(artisan.page) |
template |
プリレンダリング済みビュー名。〈例:--render="errors::503" 〉を指定すると、そのビューを依存ロード前にキャッシュし、極限状態でも直接返す。値はビューの「名前」文字列。(Laravel) |
PreventRequestsDuringMaintenanceの役割
-
アプリ全体のグローバルミドルウェアスタック
-
Laravel9 では
app/Http/Kernel.php
-
Laravel11 以降は
bootstrap/app.php
のwithMiddleware()
に登録 -
vendorの中のグローバルのところにある
vendor/laravel/framework/src/Illuminate/Foundation/Configuration/Middleware.php
public function getGlobalMiddleware()
{
$middleware = $this->global ?: array_values(array_filter([
\Illuminate\Http\Middleware\ValidatePathEncoding::class,
\Illuminate\Foundation\Http\Middleware\InvokeDeferredCallbacks::class,
$this->trustHosts ? \Illuminate\Http\Middleware\TrustHosts::class : null,
\Illuminate\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Http\Middleware\ValidatePostSize::class,
\Illuminate\Foundation\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
]));
(略)
- 中身を見てみるとこんな感じになっているみたい
### PreventRequestsDuringMaintenance クラスの
このミドルウェアは「アプリがメンテモード中か」を判定し、
- 許可パス(`except`)か、
- シークレットトークン/クッキーによるバイパスか
…のいずれにも該当しなければ 503 応答を返す。
主な処理フロー(抜粋)
public function handle($request, Closure $next)
{
// **(1) 除外パスチェック**
if ($this->inExceptArray($request)) {
return $next($request);
}
// **(2) メンテモード判定**
if ($this->app->maintenanceMode()->active()) {
$data = $this->app->maintenanceMode()->data();
// **(3) シークレット URL バイパス**
if (isset($data['secret']) && $request->path() === $data['secret']) {
return $this->bypassResponse($data['secret']);
}
// **(4) バイパスクッキー許可**
if ($this->hasValidBypassCookie($request, $data)) {
return $next($request);
}
// **(5) リダイレクト/テンプレート応答**
if (isset($data['redirect'])) {
return redirect($data['redirect']);
}
if (isset($data['template'])) {
return response($data['template'], $data['status'] ?? 503, $this->getHeaders($data));
}
// **(6) それ以外 → 503 例外**
throw new HttpException($data['status'] ?? 503, 'Service Unavailable', null, $this->getHeaders($data));
}
// **(7) 通常モード → 通常処理へ**
return $next($request);
}
- リクエストの流れとしてはこんなイメージ?
┌── HTTP リクエスト受信
│
│─┬─ ミドルウェア起動順 ──┬─ PreventRequestsDuringMaintenance がヒット?
│ │ │
│ │ ├─ いいえ → 次のミドルウェアへ
│ │ └─ はい →
│ │ ├─ メンテ状態か?
│ │ │ ├─ いいえ → 次へ
│ │ │ └─ はい →
│ │ │ ├─ except URI か?
│ │ ├─ secret パラメータ or IP 許可か?
│ │ └─ いずれも該当しない → 503 応答
│ │
│ └─…(他のミドルウェア/ルーティング処理)…
│
└── アプリケーション処理
注意点
- 以下の書き方をすると、現在のグローバルミドルウェアスタックをまるごと上書きしてしまいここに記載ないミドルウェアが効かなくなるので注意
bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
$middleware->use([
// ここに列挙したものだけが新しいグローバルスタックになる
TrustProxies::class,
HandleCors::class,
]);
});
- 追加で設定したい場合は以下の書き方をする
bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
// 既存の全ミドルウェアを保持したまま、末尾に追加
$middleware->append(\App\Http\Middleware\CustomMiddleware::class);
});
- 複数サーバでのメンテナンスモードするときは、
.env
でできるみたい
Laravelはデフォルトで、ファイルベースのシステムを使ってアプリケーションがメンテナンスモードかを判断します。つまり、メンテナンスモードを有効にするには、アプリケーションをホストしている各サーバ上でphp artisan downコマンドを実行する必要があります。
あるいは、Laravelはメンテナンスモードをキャッシュベースで処理する方法を提供しています。この方法では、ただ1つのサーバ上で、php artisan downコマンドを実行するだけです。この方法を使用するには、アプリケーションの.envファイルでメンテナンスモード変数を変更します。すべてのサーバからアクセス可能なキャッシュstoreを選択します。これにより、メンテナンスモードの状態が、すべてのサーバで一貫して維持されるようになります。
APP_MAINTENANCE_DRIVER=cache
APP_MAINTENANCE_STORE=database
ドキュメントより引用
Laravelのメンテナンスモードの挙動を確認した際のメモです。
Views: 0