简体   繁体   中英

How to remove Cache-control header no-cache

My team and I are working on a Laravel API which communicates with a Vue.js frontend that uses the Apollo client to consume the GraphQL responses.

We have an issue with cache-control headers being added to the response.

Apollo cannot cache the contents because the response contains this header:

Cache-Control: no-cache, private

In php.ini, we have this to disable sending cache-control headers by PHP:

; Set to {nocache,private,public,} to determine HTTP caching aspects
; or leave this empty to avoid sending anti-caching headers.
; http://php.net/session.cache-limiter
session.cache_limiter =

In the nginx config we cannot find anything that is setting those headers. I checked the global nginx.conf and config file we setup in sites/available.

I can add this to the nginx config, but it will only add another header:

add_header Cache-Control "public";

Cache-Control: no-cache, private
Cache-Control: public

If this header is not coming from PHP or nginx, then where could it be coming from? And how can I remove or overwrite it?

  • Laravel 5.5
  • Folkloreatelier/laravel-graphql
  • PHP 7.1
  • nginx 1.14.0
  • Ubuntu 16.04

in any middleware you can use this example

public function handle($request, Closure $next)
{
    $response= $next($request);
    return $response->header('X-TEST-HEADER','test header value');
}

but i do not know this fix your problem

you can do this by Adding in your .htaccess if you are using apache

Header always set Cache-Control "no-cache, public"

so it will remove the Cache-Control:private and give the header response as

Cache-Control:no-cache , public

In Laravel, the Cache-Control: no-cache, private header is set in the vendor package Symfony http-foundation by the following logic:


    /**
     * Returns the calculated value of the cache-control header.
     *
     * This considers several other headers and calculates or modifies the
     * cache-control header to a sensible, conservative value.
     *
     * @return string
     */
    protected function computeCacheControlValue()
    {
        if (!$this->cacheControl) {
            if ($this->has('Last-Modified') || $this->has('Expires')) {
                return 'private, must-revalidate'; // allows for heuristic expiration (RFC 7234 Section 4.2.2) in the case of "Last-Modified"
            }

            // conservative by default
            return 'no-cache, private';
        }

        $header = $this->getCacheControlHeader();
        if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) {
            return $header;
        }

        // public if s-maxage is defined, private otherwise
        if (!isset($this->cacheControl['s-maxage'])) {
            return $header.', private';
        }

        return $header;
    }

Source: Laravel 5.6 vendor/symfony/http-foundation/ResponseHeaderBag.php lines 269-299

As the OP stated in his comment to @ the_hasanov's answer , the header can be overwritten by implementing a middleware.

  1. php artisan make:middleware CachePolicy

  2. edit the new app/Http/Middleware/Cachepolicy.php so that it reads:

<?php

namespace App\Http\Middleware;

use Closure;

class CachePolicy
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
      // return $next($request);
      $response= $next($request);
      return $response->header('Cache-Control','no-cache, public');
    }
}
  1. Modify app/http/Kernel.php to include the new middleware:
...
protected $middleware = [
   ...
   \App\Http\Middleware\CachePolicy::class,
  ];
...

Please note that no cache does NOT mean " don't cache ", which is no-store , no cache "allows caches to store a response but requires them to revalidate it before reuse." Check here https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control for detailed information.

To revalidate, your server response should have etag or Last-Modified . Check here https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching for detailed information. For example, at the section starts with "Validation is done by using a conditional request that includes an If-Modified-Since or If-None-Match request header." So your server probably don't have those fields for revalidation.

The private means "cache that exists in the client. It is also called local cache or browser cache. It can store and reuse personalized content for a single user."

@Vardkin's answer correctly pointed out it is in computeCacheControlValue() that set those fields,

    if (!$this->cacheControl) {
        if ($this->has('Last-Modified') || $this->has('Expires')) {
            return 'private, must-revalidate'; // allows for heuristic expiration (RFC 7234 Section 4.2.2) in the case of "Last-Modified"
        }

        // conservative by default
        return 'no-cache, private';
    }

I want to add that must-revalidate also explained in those articles I attached.

  1. in Cache-Control

HTTP allows caches to reuse stale responses when they are disconnected from the origin server. must-revalidate is a way to prevent this from happening

  1. in HTTP caching

Stale responses are not immediately discarded. HTTP has a mechanism to transform a stale response into a fresh one by asking the origin server...Validation is done by using a conditional request

But I never figure how much difference between no-cache & must-revalidate since they all need to validate.

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