PHP
laravel

LaravelのルーティングのHTTPレスポンスをブラウザキャッシュさせる

タイトル通りですが、Laravelのレスポンスをブラウザにキャッシュさせたい場合などがあるかと思います。
この投稿ではその設定をした際の手順をメモします。

達成したいこと

  • Laravel のルーティングでブラウザキャッシュを有効にしたい。(主にAPIなど)
  • ルート個別に設定するのは手間なので Middleware を使って一括で設定したい。
  • 処理中で例外が発生したりしたらキャッシュさせない。(特定のステータスコードの場合だけキャッシュさせたいなど)

手順

1. Middleware を作る

After Middleware として作り、レスポンスヘッダに Cache-Control を追加します。
Cache-Control で設定できるものはこちらの方の記事がまとまっていて見やすいです。 → キャッシュについて整理 - Qiita
After Middleware (ルートの処理後に実施するMiddleware) を作るには $next($request) を実行し、それよりも後に実施したい処理を書きます。

$next($request) の戻り値 (Illuminate\Http\Response) からステータスコードを取り出して処理の成功/失敗を判断します。
Response のAPIは以下を参照してください。(以下のリンクはLaravel 5.7です)
Illuminate\Http\Response | Laravel API

ステータスコード 200 または 203 の場合だけキャッシュさせたい場合は以下のようになります。

app/Http/Middleware/OhMyCache.php
<?php

namespace App\Http\Middleware;
use Closure;

class OhMyCache
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        $statusCode = $response->status();
        $isValidResponse = $statusCode === 200 || $statusCode === 203;

        if ($isValidResponse) {
            $response->header('Cache-Control', 'max-age=60');
        }

        return $response;
    }
}

2. ルートに設定する

ルートで使えるよう app/Http/Kernel.php に登録します。

app/Http/Kernel.php
protected $routeMiddleware = [
  // :
  'OhMyCache' => \App\Http\Middleware\OhMyCache::class,
  // :
];

任意のルーティングで使うよう設定して完了です。

routes/api.php
Route::middleware(['OhMyCache'])->group(function () {
    Route::get('/foo', 'SomeController@foo');
    Route::get('/bar', 'SomeController@bar');
});