There are many useful middleware registered within Laravel, such as authentication, authorization, throttler and even route model binding. There are also a few mentioned middleware is SetCacheHeaders
that alias is cache.headers
. This middleware can be used to add cache headers to the response.
What are cache headers?
If you do not know cache headers, then you do not know what HTTP Cache Control is.
Put simply, Cache Control is a way to inform the browser of the response that the application sent should be cached or not and under what conditions. Thereby determining whether to request a full response again.
This is a browser-centered mechanism. You will understand the reason after reading this article.
Once you have a rough understanding of HTTP Cache Control and what the SetCacheHeaders
middleware does, learn more in the next section.
How does SetCacheHeaders middleware work?
Let’s take a look at which source code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | <?php namespace IlluminateHttpMiddleware; use Closure; use IlluminateSupportCarbon; class SetCacheHeaders { /** * Add cache related HTTP headers. * * @param IlluminateHttpRequest $request * @param Closure $next * @param string|array $options * @return SymfonyComponentHttpFoundationResponse * * @throws InvalidArgumentException */ public function handle($request, Closure $next, $options = []) { $response = $next($request); if (! $request->isMethodCacheable() || ! $response->getContent()) { return $response; } if (is_string($options)) { $options = $this->parseOptions($options); } if (isset($options['etag']) && $options['etag'] === true) { $options['etag'] = md5($response->getContent()); } if (isset($options['last_modified'])) { if (is_numeric($options['last_modified'])) { $options['last_modified'] = Carbon::createFromTimestamp($options['last_modified']); } else { $options['last_modified'] = Carbon::parse($options['last_modified']); } } $response->setCache($options); $response->isNotModified($request); return $response; } /** * Parse the given header options. * * @param string $options * @return array */ protected function parseOptions($options) { return collect(explode(';', $options))->mapWithKeys(function ($option) { $data = explode('=', $option, 2); return [$data[0] => $data[1] ?? true]; })->all(); } } |
As you can see, there are six main statements in the handle()
of this middleware. Analyze them a little bit:
- Check if the request is a GET or HEAD. You cannot cache a POST response, as this method means that something has been changed.
- Check if you passed any parameters to the middleware and parse them for the Response headers using the
parseOptions()
. - If there is an
etag
option, it will hash the response content so that it can be compared with the etag the request sent. - If there is the
last_modified
option, it will addlast_modified
to the header. - Assign Cache-Control options to Response headers.
- Finally, it checks to see if the response has changed. Otherwise, it will ignore the response and return only the
etag
.
Steps 3 and 6 are the most important. The browser will send the request to the application with the response’s etag
cached, if the original response contains the etag
. Your application will receive the etag
, process the request , and eventually hash the content into the new etag
. By comparing the two etag
mentioned above, your application can know whether to resend the response or just resend the etag
, to notify the browser that the content of the response has not changed.
Handling requests is also an important part. Because the application or the browser will not be able to know if the response content has changed until the response is ready, meaning all logic in the application must still be run from start to finish.
If you want to implement caching for your application, you can think about caching the response at the server and also using the etag
header to optimize both server and client.
Use the SetCacheHeaders middleware
We already know what this middleware does. Let’s do it, a simple example of it.
Below is a Google diagram of the cache-control policy:
Here is an example from the Laravel homepage:
etag
allows users to refresh the page without reloading the content if the content has not changed.public
allows the response to be cached in any way, even when not normally cached ( see more ).- max-age = 2592000 will set the cache expiration to 30 days from the last time the cache was created.
1 2 3 4 5 6 7 8 9 10 | Route::middleware('cache.headers:public;max_age=2592000;etag')->group(function () { Route::get('/privacy', function () { // ... }); Route::get('/terms', function () { // ... }); }); |
See more about the Cache-Control header .
That’s all I want to convey in this article. You do not need to manually create middleware or config in Apache or NGINX. Thank you for reading.