简体   繁体   中英

How to I get control of the Cache-Control header with Wordpress on Apache?

This is driving me absolutely nuts. We're running Wordpress on Apache (we're new to this stack, if that's not obvious). Specifically this is a Bitnami AMI. Since we're pretty much 100% on AWS, I wanted to use Cloudfront dynamic content caching in front of the Wordpress site. I've read tons of docs/posts about how to use W3 Total Cache (or similar) to make this work. But all I really want to do is get a grip on the Cache-Control header so I can get Cloudfront to work the way it's supposed to.

Currently, I have modified functions.php to include code (based on another post here) which is supposed to modify the header.

function varnish_safe_http_headers() {
    session_cache_limiter('');
    header_remove("Cache-Control");
    header("Cache-Control: public, max-age=60");
  if( !session_id() )
  {
    session_start();
  }
}
add_action( 'template_redirect', 'varnish_safe_http_headers' );

Unfortunately, what I wind up with is TWO headers.

Cache-Control:public, max-age=60
Cache-Control:max-age=0, no-cache

The first header is mine. The second header is coming from some other location in the stack that I can't seem to find/configure. I've searched the entire contents of the Wordpress directory for any string that I can think of that would help me find code that does this.

I've also tried changing the "hook" in the add_action call to any number of values, working my way from "send_headers" down through. The only result is that the two cache-control headers change order. I cannot, so far, remove/overwrite the "max-age=0, no-cache" value.

I've also tried modifying .htaccess, the Bitnami-specific.htaccess.conf file, etc, etc.

EDIT : After reading here , it seems that the second header must be caused somewhere within Wordpress/PHP. This document makes it appear that the "handler" (in this case PHP) gets the last word on response processing. Once that phase is complete, there is only sending the response to the client and logging.

EDIT 2 : I added a foo.php file to the root of the site. It calls no Wordpress functions at all. Both Cache-Control headers still appear. Here are the entire contents of the file.

<?php
header("Cache-Control: public, max-age=60");
?>

Apache's mod_pagespeed is the culprit. It sets Cache-Control: no-cache, max-age=0 by default.

You need to update apache2/conf/pagespeed.conf to include

ModPagespeedModifyCachingHeaders off

then run this to restart apache

$ cd installdir
$ ./ctlscript.sh restart apache

References:

The answer was to start over. I built a completely new AWS Linux instance and installed Apache, MySql, PHP, and Wordpress myself. I used my own configuration in .htaccess to set Cache-Control headers based on file types. I installed mod_pagespeed to help out with giant images uploaded by incompetent content writers. Then I wasted a great deal of time fixing the image URLs in all the posts. The only Wordpress plugins installed are the import/export plugin (so I could get all the content from the old server) and a "slider" plugin for allowing users to page through images in a post.

Now I can finally use Cloudfront properly in front of Wordpress. If you want to do the same, do yourself a favor and skip all the super-duper-whiz-bang caching plugins. Totally unnecessary.

I am posting this solution because this page shows as one of the first results when searching for "WordPress cache control headers".

If you see in your WordPress site health report that your site is not using cache control headers, then instead of making changes to Apache config or .htaccess, you can modify the headers generated by WordPress, or lack there off. As of this writing WordPress only generates cache control headers when you are in the admin dashboard. Outside of that cache should be handled by a plug-in or custom solution, like the one below.

The following solution will:

  1. Make changes to WordPress headers to enable client cache control
  2. If the user is NOT in the admin dashboard.
  • This has been tested with WordPress 6.2.2
  • You can place this in your currently active theme "functions.php" file.
  • Works for both logged in and anonymous users.

if ( ! function_exists( 'mysite_client_cache' ) ) :
    function mysite_client_cache( $headers ) {
        global $wp;

        $current_request_path = $wp->requet;

        if ( '' !== $current_request_path ) {
            $current_request_path = trim( $current_request_path, '/' );

            if ( 'wp-admin' !== $current_request_path ) {
                $headers[ 'Cache-Control' ] = 'public, max-age=604800';
            }
        }

        return $headers;
}
endif;

add_filter( 'wp_headers', 'mysite_client_cache', 100, 1);

This will work fine for infrequently updated sites. The solution can be improved by lowering the "max-age" value or going more granular about which request paths (home page vs post page) are cache and for how long.

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