简体   繁体   中英

Laravel 5 how to set Cache-Control HTTP header globally?

My Laravel application is returning Cache-Control: no-cache, private HTTP header by default for each site. How can I change this behaviour?

PS: It is not a PHP.ini problem, because changing session.cache_limiter to empty/public does not change anything.

Laravel 5.6+

There's no longer any need to add your own custom middleware.

The SetCacheHeaders middleware comes out of the box with Laravel, aliased as cache.headers

The nice thing about this Middleware is that it only applies to GET and HEAD requests - it will not cache POST or PUT requests since you almost never want to do that.

You can apply this globally easily by updating your RouteServiceProvider :

protected function mapWebRoutes()
{
    Route::middleware('web')
        ->middleware('cache.headers:private;max_age=3600') // added this line
        ->namespace($this->namespace)
        ->group(base_path('routes/web.php'));
}

protected function mapApiRoutes()
{
    Route::prefix('api')
        ->middleware('api')
        ->middleware('cache.headers:private;max_age=3600') // added this line
        ->namespace($this->namespace)
        ->group(base_path('routes/api.php'));
}

I don't recommend that though. Instead, as with any middleware, you can easily apply to specific endpoints, groups, or within the controller itself, eg:

Route::middleware('cache.headers:private;max_age=3600')->group(function() {
    Route::get('cache-for-an-hour', 'MyController@cachedMethod');
    Route::get('another-route', 'MyController@alsoCached');
    Route::get('third-route', 'MyController@alsoAlsoCached');
});

Note that the options are separated by semicolon not comma, and hyphens are replaced by underscores. Also, Symfony only supports a limited number of options :

'etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public', 'immutable'

In other words you can't simply copy and paste a standard Cache-Control header value, you will need to update the formatting:

CacheControl format:       private, no-cache, max-age=3600
  ->
Laravel/Symfony format:    private;max_age=3600

Laravel 5.5 <

You can have a global middleware for that. something like:

<?php

namespace App\Http\Middleware;

use Closure;

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

        $response->header('Cache-Control', 'no-cache, must-revalidate');
        // Or whatever you want it to be:
        // $response->header('Cache-Control', 'max-age=100');

        return $response;
    }
}

then just register this as a global middleware in the Kernel file:

protected $middleware = [
    ....
    \App\Http\Middleware\CacheControl::class
];

For people that seek a way to write less code, here is another way you can add headers to a response without extra steps.

In the example above, I created a middleware to prevent routes from being cached in the end user browser.

<?php

class DisableRouteCache
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        return $next($request)->withHeaders([
            "Pragma" => "no-cache",
            "Expires" => "Fri, 01 Jan 1990 00:00:00 GMT",
            "Cache-Control" => "no-cache, must-revalidate, no-store, max-age=0, private",
        ]);
    }
}

Source: Attaching Headers To Responses

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM