# Site health check: Page cache not detected

**URL:** https://discourse.roots.io/t/site-health-check-page-cache-not-detected/25640
**Category:** trellis
**Tags:** trellis
**Created:** 2023-07-11T18:28:53Z
**Posts:** 2

## Post 1 by @strarsis — 2023-07-11T18:28:53Z

Trellis has always used nginx microcaching, basically page caching.

The WordPress site health check fails the page caching test on Trellis though,  
as it expects one or more caching-specific HTTP headers and values for page caching being considered working.  
`cache-control, expires, age, last-modified, etag, x-cache-enabled, x-cache-disabled, x-srcache-store-status, x-srcache-fetch-status`

The response header for the frontend front page is `Cache-Control: no-cache, must-revalidate, max-age=0`. This would not satisfy the page caching test in WordPress site health.

Although this is less of an issue with agency sites, I would still want to see all health checks pass.  
Can the header checks be modified to detect a Trellis-specific page caching header or behavior for example?

> <https://github.com/WordPress/WordPress/blob/9e0f2faa28f1aa04a69e0b4eaa410a38adcd2e1e/wp-admin/includes/class-wp-site-health.php#L3146>

---

## Post 2 by @strarsis — 2024-03-15T11:37:57Z

Follow up:

Those are the HTTP response headers that a test PHP loopback request receives:

```
HTTP/2 200 
server: nginx
date: Fri, 15 Mar 2024 12:00:00 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
link: <https://example.com/>; rel=shortlink
fastcgi-cache: MISS
strict-transport-security: max-age=31536000; ;
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
x-ua-compatible: IE=Edge
content-security-policy: frame-ancestors 'self'
x-frame-options: SAMEORIGIN
```

> ****
>
> \<?php $url = "https://example.com/";
> 
> $curl = curl\_init($url);  
> curl\_setopt($curl, CURLOPT\_RETURNTRANSFER, true);  
> curl\_setopt($curl, CURLOPT\_HEADER, true);  
> curl\_setopt($curl, CURLOPT\_NOBODY, true);
> 
> $response = curl\_exec($curl);  
> curl\_close($curl);
> 
> echo $response;

So I have to correct my assumption that `Cache-Control: no-cache, must-revalidate, max-age=0` is added as HTTP response header, as this is set for outside requests, not for internal requests from `nginx` to PHP FPM.

A related [`Fastcgi-Cache` HTTP header is added by Trellis](https://github.com/roots/trellis/blob/02cfc360911c545611d624c01ce4d97f197c6d00/roles/wordpress-setup/templates/wordpress-site.conf.j2#L20), but not used by the WordPress site health check.

IMHO, the currently best approach (IMHO) would add the `x-cache-enabled: true` HTTP header to requests from `nginx` to PHP (`fpm`):

```
map $upstream_cache_status $header_x_cache_enabled {
  default true;
  BYPASS "";
}
```

```
# Extra header for WordPress (notably its Site Health check)
  add_header X-Cache-Enabled $header_x_cache_enabled;
```

(A fitting place can be after the aforementioned [`Fastcgi-Cache` header directive](https://github.com/roots/trellis/blob/02cfc360911c545611d624c01ce4d97f197c6d00/roles/wordpress-setup/templates/wordpress-site.conf.j2#L20), the map would be set before the `server` block).

For extending the configuration template:  
(`nginx-includes/wordpress-site.conf.child`):

```
{% extends 'roles/wordpress-setup/templates/wordpress-site.conf.j2' %}

{% block server_before -%}
{{ super() }}
map $upstream_cache_status $header_x_cache_enabled {
  default true;
  BYPASS "";
}

{%- endblock %}

{% block server_basic %}
  {{ super() }}
  # Extra header for WordPress (notably its Site Health check)
  add_header X-Cache-Enabled $header_x_cache_enabled;

{% endblock -%}
```

(`group_vars/all/main.yml` or environment-specific `main.yml`):

```
nginx_wordpress_site_conf: nginx-includes/wordpress-site.conf.child
```

Adding this to Trellis by default appears to be a good idea (no obvious side-effects, improving compatibility with WordPress core (site health check)).

Would this be also worth a WordPress core trac issue, that the `Fastcgi-Cache` HTTP response header is also used as page cache indication in the WordPress site health check?

> <https://github.com/roots/trellis/pull/1513>
>
> This PR adds the `X-Cache-Enabled` HTTP header to `nginx` responses. It will not… be added when upstream cache status is `BYPASS` as then no caching is used for the request.
> 
> WordPress Site Health Page Caching [uses specific HTTP header values](https://github.com/WordPress/WordPress/blob/6.4.3/wp-admin/includes/class-wp-site-health.php#L3333-L3353) in the loopback HTTP response in order to detect that page caching is indeed enabled.
> 
> The related [`Fastcgi-Cache` HTTP header is added by Trellis](https://github.com/roots/trellis/blob/v1.21.0/roles/wordpress-setup/templates/wordpress-site.conf.j2#L20), but not used by the WordPress site health check.
> 
> Adding this to Trellis by default appears to be a good idea (no obvious side-effects, improving compatibility with WordPress core (site health check)).
> 
> See roots discussion: https://discourse.roots.io/t/site-health-check-page-cache-not-detected/25640/2
> 
> Note: Should this `X-Cache-Enabled` HTTP header only be added to loopback requests? On the other hand, the `Fastcgi-Cache` HTTP header is also already added to all requests.
> 
> Possible alternative: A Bedrock MU plugin that uses the `Fastcgi-Cache` HTTP header to set `X-Cache-Enabled` in PHP code.
