From f72e4b378bc51ab9ae299f3216b310f8371c8414 Mon Sep 17 00:00:00 2001
From: Stephen Mustgrave <smustgrave@gmail.com>
Date: Fri, 28 Mar 2025 16:52:41 -0400
Subject: [PATCH] Issue #3342122 by mastap, smustgrave: /node/{id} not working
 for 404 exclusion

---
 .../CacheexcludeSubscriber.php                | 11 +++
 tests/src/Functional/CacheExclude404Test.php  | 80 +++++++++++++++++++
 2 files changed, 91 insertions(+)
 create mode 100644 tests/src/Functional/CacheExclude404Test.php

diff --git a/src/EventSubscriber/CacheexcludeSubscriber.php b/src/EventSubscriber/CacheexcludeSubscriber.php
index 16a629d..b2f2b14 100644
--- a/src/EventSubscriber/CacheexcludeSubscriber.php
+++ b/src/EventSubscriber/CacheexcludeSubscriber.php
@@ -107,6 +107,17 @@ class CacheexcludeSubscriber implements EventSubscriberInterface {
       if ($path_matches || $alias_path_matches) {
         return TRUE;
       }
+
+      $system404 = $this->configFactory->get('system.site')->get('page.404');
+
+      if (isset($system404)) {
+        if (is_array($pages) && in_array($current_path, $pages)) {
+          return TRUE;
+        }
+        elseif ($system404 === $pages) {
+          return TRUE;
+        }
+      }
     }
 
     return FALSE;
diff --git a/tests/src/Functional/CacheExclude404Test.php b/tests/src/Functional/CacheExclude404Test.php
new file mode 100644
index 0000000..c0ab455
--- /dev/null
+++ b/tests/src/Functional/CacheExclude404Test.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace Drupal\Tests\cacheexclude\Functional;
+
+use Drupal\Tests\BrowserTestBase;
+use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait;
+
+/**
+ * Test CacheExclude on 404 pages.
+ *
+ * @group cacheexclude
+ */
+class CacheExclude404Test extends BrowserTestBase {
+
+  use AssertPageCacheContextsAndTagsTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['cacheexclude', 'page_cache', 'node'];
+
+  /**
+   * Node ID for 404 page.
+   *
+   * @var int
+   */
+  protected int $id;
+
+  /**
+   * Setup cacheexclude setting.
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $this->drupalCreateContentType(['type' => 'page']);
+    $this->id = $this->drupalCreateNode()->id();
+
+    // Set 404 page.
+    $this->config('system.site')->set('page.404', '/node/' . $this->id)->save();
+
+    // Enable page cache.
+    $this->config('system.performance')->set('cache.page.max_age', 300)->save();
+
+    drupal_flush_all_caches();
+  }
+
+  /**
+   * Tests that cacheexclude works as expected.
+   *
+   * @throws \Behat\Mink\Exception\ExpectationException
+   */
+  public function testCacheExclude404(): void {
+    $path = 'trigger_404';
+
+    $this->drupalGet($path);
+    $this->assertSession()->responseHeaderEquals('X-Drupal-Cache', 'MISS');
+    // Second request should HIT.
+    $this->drupalGet($path);
+    $this->assertSession()->responseHeaderEquals('X-Drupal-Cache', 'HIT');
+
+    // Set Cache Exclude to 404 page.
+    $this->config('cacheexclude.settings')->set('cacheexclude_list', '/node/' . $this->id)->save();
+    drupal_flush_all_caches();
+
+    $this->drupalGet($path);
+    if (str_starts_with(\Drupal::VERSION, '11.0')) {
+      // See https://www.drupal.org/node/2958442
+      $this->assertSession()->responseHeaderDoesNotExist('X-Drupal-Cache');
+    }
+    else {
+      // See https://www.drupal.org/node/2958442
+      $this->assertSession()->responseHeaderEquals('X-Drupal-Cache', 'UNCACHEABLE (response policy)');
+    }
+  }
+
+}
-- 
GitLab