PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.3.5
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.3.5
1.3.5 1.3.4 1.3.3 1.3.2 1.3.1 1.3.0 1.2.4 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 All 31 releases
← All changes | includes/modules/Health/HealthModule.php +98 -0 1.3.41.3.5 View file →
@@ -75,8 +75,52 @@
75 75 * embedded when nginx is detected. Skipped entirely when cache is
76 76 * disabled — no point telling the user to install a rewrite they
77 77 * haven't opted into.
78 78 */
79 + /**
80 + * Decide what the nginx static rewrite is actually doing.
81 + *
82 + * Extracted so the ordering is testable without a WordPress bootstrap,
83 + * and so Site Health and the dashboard Health panel cannot drift apart
84 + * again — the whole point of #480.
85 + *
86 + * Returns one of: 'active', 'mobile_separate', 'skipped_nonce',
87 + * 'unverified', 'required'.
88 + *
89 + * @param array<string, mixed> $probe probe_static_rewrite() result.
90 + * @param string $block_reason A known refusal, or ''.
91 + */
92 + public static function nginx_rewrite_verdict( array $probe, string $block_reason ): string {
93 + $is_active = (bool) ( $probe['active'] ?? false );
94 + $inconclusive = (bool) ( $probe['inconclusive'] ?? false );
95 +
96 + // A known refusal OUTRANKS the probe. probe_static_rewrite() writes
97 + // its own file under the static-cache dir and fetches that, which
98 + // succeeds whenever the server can serve a static file at all — even
99 + // when no real page is on the static path. It also outranks
100 + // "inconclusive", so a blocked rewrite whose probe merely failed to
101 + // complete is reported as the refusal it is. (FBS-83145)
102 + if ( '' !== $block_reason ) {
103 + if ( 'mobile_separate' === $block_reason ) {
104 + return 'mobile_separate';
105 + }
106 + if ( 'skipped_nonce' === $block_reason ) {
107 + return 'skipped_nonce';
108 + }
109 + return 'required';
110 + }
111 +
112 + if ( $is_active ) {
113 + return 'active';
114 + }
115 +
116 + // The probe never reached a verdict (blocked loopback, self-signed
117 + // cert, timeout, a CDN/WAF answering instead of the origin). That is
118 + // not evidence the config is wrong, and must not produce a
119 + // "paste this snippet" banner. (FBS-84012, #480)
120 + return $inconclusive ? 'unverified' : 'required';
121 + }
122 +
79 123 public function site_status_static_rewrite(): array {
80 124 $result = array(
81 125 'label' => __( 'xSpeed static-rewrite cache is active', 'xspeed' ),
82 126 'status' => 'good',
@@ -120,8 +164,62 @@
120 164 return $result;
121 165 }
122 166
123 167 if ( \XSpeed\Server::NGINX === $server_type ) {
168 + // Ask the same question the dashboard Health panel asks, the same
169 + // way. This test used to return "config required" unconditionally,
170 + // so every correctly-configured nginx site — every xCloud site,
171 + // where the panel installs the block for you — was told to paste a
172 + // snippet it already had, and re-running the check never cleared
173 + // it. Worse, the dashboard said the opposite at the same moment.
174 + // Reuse probe_static_rewrite() + the refusal reasons so the two
175 + // surfaces cannot disagree. (#480)
176 + $probe = \XSpeed\Cache::probe_static_rewrite( true );
177 + $probe_reason = (string) ( $probe['reason'] ?? '' );
178 +
179 + $block_reason = \XSpeed\Cache::static_rewrite_block_reason();
180 + $skip = \XSpeed\Cache::last_static_skip();
181 + if ( '' === $block_reason && ! empty( $skip['reason'] ) ) {
182 + $block_reason = 'skipped_' . (string) $skip['reason'];
183 + }
184 +
185 + switch ( self::nginx_rewrite_verdict( $probe, $block_reason ) ) {
186 + case 'active':
187 + $result['label'] = __( 'xSpeed nginx static rewrite is active', 'xspeed' );
188 + $result['status'] = 'good';
189 + $result['description'] = '<p>' . esc_html__( 'nginx is serving cache hits directly — PHP is bypassed (~5-15ms TTFB). No action needed.', 'xspeed' ) . '</p>';
190 + return $result;
191 +
192 + case 'mobile_separate':
193 + $result['label'] = __( 'xSpeed static rewrite is off (Separate Mobile Cache)', 'xspeed' );
194 + $result['status'] = 'recommended';
195 + $result['description'] = '<p>' . esc_html__( 'Separate Mobile Cache is on, so cache hits are served by the PHP drop-in to keep per-device HTML correct. Turn Separate Mobile Cache off if your site serves the same HTML to every device to regain the faster static path.', 'xspeed' ) . '</p>';
196 + return $result;
197 +
198 + case 'skipped_nonce':
199 + $result['label'] = __( 'xSpeed is serving cache hits through PHP (pages contain nonces)', 'xspeed' );
200 + $result['status'] = 'recommended';
201 + $result['description'] = '<p>' . esc_html__( 'Your nginx config is correct, but pages are not reaching the static cache, so hits are served by PHP. They contain nonces, and a static file is served with no PHP — nothing could ever refresh them, so every anonymous form on the page would break once they expire. Keeping these pages on PHP is deliberate.', 'xspeed' ) . '</p>';
202 + return $result;
203 +
204 + case 'unverified':
205 + // The probe never reached a verdict (blocked loopback,
206 + // self-signed cert, timeout, a CDN/WAF answering instead of
207 + // the origin). Not evidence the config is wrong, so don't
208 + // say "required" and don't dump a snippet the user has
209 + // probably already pasted. (FBS-84012, and why #480 was filed.)
210 + $result['label'] = __( 'xSpeed could not verify the nginx static rewrite', 'xspeed' );
211 + $result['status'] = 'recommended';
212 + $result['description'] = '<p>' . esc_html(
213 + sprintf(
214 + /* translators: %s: the reason the probe could not complete. */
215 + __( 'The check itself did not complete, so this is not evidence that your config is wrong — if you have already pasted the snippet it may well be working. Reason: %s', 'xspeed' ),
216 + $probe_reason
217 + )
218 + ) . '</p>';
219 + return $result;
220 + }
221 +
124 222 $snippet = \XSpeed\Cache::nginx_snippet();
125 223 $result['label'] = __( 'xSpeed nginx server config required', 'xspeed' );
126 224 $result['status'] = 'recommended';
127 225 $result['description'] = '<p>' . esc_html__( 'xSpeed can\'t write nginx config from PHP. Paste this snippet into your site\'s server { } block, then reload nginx so cache hits serve without booting PHP:', 'xspeed' ) . '</p>'