How to override cache tags in a Drupal response object
While working on some improvements to the caching granularity in the Prosple platform, I found myself needing to override the cache tags being sent in a GraphQL response.
This is because Drupal has a lot of cache tags, and while they are all incredibly useful you might find yourself in a situation where they never get used and, for caching systems like CDNs, it can cause you to do over the allowed limits for header sizes.
So how to do this?
Add an Event Subscriber to your custom module
The first thing we need to do is to create an event subscriber.
You can do this by creating a new module or adding it to an existing custom one, which is what I’ll do here. The module is called example
.
First, make sure that you have an example.services
.yml
file in your module root where you define your Event Subscriber. Here is one for the example
module:
services:
example_event_subscriber:
class: '\Drupal\example\EventSubscriber\ExampleEventSubscriber'
tags:
- { name: 'event_subscriber' }
Create an Event Subscriber
Next, we are going to create the actual Event Subscriber:
<?php
namespace Drupal\example\EventSubscriber;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Class ExampleEventSubscriber.
*
* @package Drupal\example\EventSubscriber
*/
class ExampleEventSubscriber implements EventSubscriberInterface {
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
KernelEvents::RESPONSE => ['onKernelResponse', 100],
];
}
/**
* React to a response event
*
* @param FilterResponseEvent $event
* The response event.
*/
public function onKernelResponse(FilterResponseEvent $event) {
/** @var \Drupal\Core\Cache\CacheableJsonResponse $response */
$response = $event->getResponse();
if(is_a($response, '\Drupal\Core\Cache\CacheableJsonResponse')){
$cache_tags = ['test'];
$response->getCacheableMetadata()->setCacheTags($cache_tags);
}
else{
return;
}
}
}
So let’s look at this closely.
First, we implement the getSubscribedEvents method. You can see more details on how to create Event Subscribers in https://www.drupal.org/docs/8/creating-custom-modules/subscribe-to-and-dispatch-events
The important part here is that priority argument (which I’m setting to 100). This is to ensure that this Event Subscriber runs before the FinishResponseSubscriber
.
Now, within our onKernelResponse
method we can get our Response object and override the cache tags.
In our case, we are checking that the response is a CacheableJSONResponse
, which might not make sense to you.
What matters is what’s inside that conditional statement:
$cache_tags = ['test'];
$response->getCacheableMetadata()->setCacheTags($cache_tags);
I’m just setting a list of dummy tags here, you could get the ones in the response by using $response->getCacheableMetadata() or I can just set my own list as I’m doing above.
Then I call the method setCacheTags
in the CacheableMetadata
class and add the list of tags I want.
That’s it!