如何在Laravel中强制设置缓存响应头?
Laravel缓存响应头在Nginx生产环境冲突的解决方法
问题背景
我在Laravel里配置了路由,同时用cache.headers中间件和手动设置响应头,目的是让文件能在客户端缓存,避免重复请求。本地环境一切正常,但部署到Nginx生产环境后,响应头出现冲突——同时存在允许缓存和禁止缓存的头信息,导致缓存失效。
路由配置
Route::group([ 'middleware' => ['cache.headers:public;max_age=600'], ], function () { Route::get('/my-file', function ($locale) { //some logic $contents = 'my file content'; $response = \Response::make($contents, 200); $response->header('Cache-Control', 'public, max-age=600'); $response->header('Expires', now()->addSeconds(600)->toRfc7231String()); $response->header('Content-Type', 'application/javascript'); $response->header('Pragma', ''); return $response; }); });
本地正常响应头
Cache-Control: max-age=600, public Connection: close Content-Type: application/javascript Date: Thu, 08 Feb 2024 19:23:55 GMT, Thu, 08 Feb 2024 19:23:55 GMT Expires: Thu, 08 Feb 2024 19:33:55 GMT Host: 127.0.0.1:8000 Pragma:
生产环境冲突响应头
Cache-Control: no-store, no-cache, must-revalidate Cache-Control: max-age=600, public Connection: keep-alive Content-Encoding: gzip Content-Type: application/javascript; charset=utf-8 Date: Thu, 08 Feb 2024 19:17:21 GMT Expires: Thu, 19 Nov 1981 08:52:00 GMT Expires: Thu, 08 Feb 2024 19:27:21 GMT Pragma: no-cache Pragma: Server: nginx/1.14.0 (Ubuntu)
解决步骤
1. 移除重复的缓存头设置
你同时用了Laravel的缓存中间件和手动设置响应头,这会导致重复输出Cache-Control和Expires。二选一即可,推荐保留中间件简化代码:
Route::group([ 'middleware' => ['cache.headers:public;max_age=600;etag'], ], function () { Route::get('/my-file', function ($locale) { //some logic $contents = 'my file content'; $response = \Response::make($contents, 200); $response->header('Content-Type', 'application/javascript'); $response->header('Pragma', ''); return $response; }); });
2. 修正Nginx配置,覆盖默认禁止缓存的头
冲突的核心是Nginx默认添加了禁止缓存的头(比如no-store, no-cache, must-revalidate和旧的Expires),需要在对应location块中强制覆盖:
如果是反向代理Laravel的配置
location /my-file { # 设置正确的缓存头,always确保在所有响应中都添加 expires 600s; add_header Cache-Control "public, max-age=600" always; add_header Expires $date_gmt; add_header Pragma ""; # 代理到Laravel应用 proxy_pass http://your-laravel-upstream; # 替换成你的Laravel地址,比如127.0.0.1:9000 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 保留gzip配置(如果需要) gzip on; gzip_types application/javascript; }
如果是FastCGI配置(比如php-fpm)
location /my-file { expires 600s; add_header Cache-Control "public, max-age=600" always; add_header Expires $date_gmt; add_header Pragma ""; # 禁止fastcgi根据Pragma头禁用缓存 fastcgi_cache_bypass ""; fastcgi_no_cache ""; # 其他fastcgi配置 fastcgi_pass unix:/run/php/php7.4-fpm.sock; # 替换成你的php-fpm路径 fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }
3. 验证并重启Nginx
修改配置后先验证语法是否正确:
nginx -t
验证通过后重启Nginx:
systemctl restart nginx
4. 测试响应头
再次请求/my-file,检查响应头是否只有一组正确的缓存配置,确保没有冲突的头信息。
内容的提问来源于stack exchange,提问作者iamx
相关产品推荐
相关产品推荐

