Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

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

like image 626
manifestor Avatar asked Aug 13 '18 11:08

manifestor


People also ask

How do I set up Cache-Control headers?

To use Cache-Control headers, choose Content Management | Cache Control Directives in the administration server. Then, using the Resource Picker, choose the directory where you want to set the headers. After setting the headers, click 'OK'.

What is the use of Cache-Control in HTTP response header?

Cache-control is an HTTP header used to specify browser caching policies in both client requests and server responses. Policies include how a resource is cached, where it's cached and its maximum age before expiring (i.e., time to live).

What should you add to a Cache-Control response header to specify that a response?

private. The private response directive indicates that the response can be stored only in a private cache (e.g. local caches in browsers). You should add the private directive for user-personalized content, especially for responses received after login and for sessions managed via cookies.

Where can I set headers in Laravel?

In Laravel headers should be set on the response object.


2 Answers

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, e.g.:

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
like image 111
andrewtweber Avatar answered Oct 17 '22 18:10

andrewtweber


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
];
like image 29
Khalid Dabjan Avatar answered Oct 17 '22 19:10

Khalid Dabjan