How can I change HTTP headers only to posts of a specific category from a plugin

I have a plugin for injecting additional HTTP headers. It works fine with the following CODE:

add_action( 'send_headers', 'jim_stop' );
function jim_stop() {

    header( 'Cache-Control: no-store, no-cache, must-revalidate, max-age=0' );
    header( 'Pragma: no-cache' );
    header( 'Expires: Thu, 01 Dec 1994 16:00:00 GMT' );

}

It sets the above HTTP headers to all the posts. However, I want to inject the headers only to the pages of a specific category. For example, say the category slug is x and id is 75.

To set the HTTP headers specific to the posts of category x, I’ve used in_category( 'x' ) in conditional as follows:

add_action( 'send_headers', 'jim_stop' );
function jim_stop() {
    if ( in_category( 'x' ) ) {
        // category specific HTTP headers    
    }
}

but that didn’t work.

I’ve also tried to check the category like this:

$cat = get_query_var( 'cat' );
if ( $cat == '75' ) {
    // category specific HTTP headers
}

and also like this:

global $post;
if ( in_category ( 'x', $post->ID ) ) {
    // category specific HTTP headers
}

but those fail too.

As the category check didn’t work with the send_headers action hook, I’ve tried to do it with wp_headers filter hook, like the following:

add_filter( 'wp_headers', 'add_header_xua' );
function add_header_xua( $headers ) {
    if ( in_category( 'x' ) ) {
        // category specific HTTP header changes
    }
    return $headers;
}

but it fails too. So my question is:

  • How can I restrict the HTTP header changes only to the posts of a specific category?

1 Answer
1

Why it doesn’t work:

send_headers hook is fired once the HTTP headers for caching, content etc. have been sent, but before the main query is properly initiated. That’s why in_category() function doesn’t work when you use it in this action hook. Same goes for the wp_headers filter hook.

To make it work:

  1. You may use the template_redirect action hook (or even wp action hook). This hook is fired after the main database query related objects are properly initiated, but before any output is generated. So this hook is good for setting additional HTTP headers, redirecting to another URL etc.

  2. Also you need to check is_single() as you want to apply it only to the posts from that category. Otherwise it’ll apply to the category archive page as well.

So the working CODE will be like the following:

add_action( 'template_redirect', 'jim_stop' );
function jim_stop() {
    if( is_single() && in_category( 'x' ) ) {
        header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
        header('Pragma: no-cache');
        header('Expires: Thu, 01 Dec 1990 16:00:00 GMT');
    }
}

Now the category check will work and those additional HTTP headers will only apply to the posts from category x.

Leave a Comment