PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.3.2
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.3.2
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 1.1.7 1.1.8 All 29 releases
← All changes | includes/modules/Cache/CacheModule.php +3 -136 1.3.31.3.2 View file →
@@ -170,11 +170,9 @@
170 170 '/xmlrpc.php',
171 171 '~wp-.*\.php',
172 172 '/feed/',
173 173 'index.php',
174 - // `sitemaps?` — SEOPress generates sitemaps.xml (plural).
175 - '~sitemaps?(_index)?\.xml',
176 - '/robots.txt',
174 + '~sitemap(_index)?\.xml',
177 175 // Bare (no trailing slash) so "contains" matches both
178 176 // /cart and /cart/items — WooCommerce serves both forms.
179 177 '/cart',
180 178 '/checkout',
@@ -230,53 +228,8 @@
230 228 'default' => false,
231 229 'label' => __( 'Separate Mobile Cache', 'xspeed' ),
232 230 'description' => __( 'Keep mobile and desktop responses in separate cache buckets. Turn on for AMP, mobile-specific themes (WPtouch / Jetpack mobile theme), or any setup that serves different HTML by device.', 'xspeed' ),
233 231 ),
234 - 'edge_provider' => array(
235 - 'type' => 'enum',
236 - 'default' => 'auto',
237 - 'options' => array( 'auto', 'off', 'cloudflare', 'fastly', 'varnish', 'nginx', 'akamai', 'cloudfront', 'google', 'keycdn', 'bunny', 'sucuri', 'incapsula', 'generic', 'custom' ),
238 - 'option_labels' => array(
239 - 'auto' => 'Detect automatically',
240 - 'off' => 'Off — send nothing',
241 - 'cloudflare' => 'Cloudflare',
242 - 'varnish' => 'Varnish',
243 - 'nginx' => 'nginx proxy cache',
244 - 'cloudfront' => 'Amazon CloudFront',
245 - 'google' => 'Google Cloud CDN',
246 - 'keycdn' => 'KeyCDN',
247 - 'bunny' => 'Bunny',
248 - // These four cannot be presented as supported on the same
249 - // footing as the ones above. Vendor documentation either
250 - // does not establish that they honour what we send, or
251 - // establishes that they ignore origin cache headers until
252 - // the property is configured to respect them — Akamai
253 - // caches for a theoretically infinite time by default, and
254 - // Sucuri's default caching level ignores the headers
255 - // outright. Naming them without the caveat would promise a
256 - // protection the CDN is not currently giving.
257 - 'fastly' => 'Fastly (needs CDN configuration)',
258 - 'akamai' => 'Akamai (needs CDN configuration)',
259 - 'sucuri' => 'Sucuri (needs CDN configuration)',
260 - 'incapsula' => 'Imperva / Incapsula (needs CDN configuration)',
261 - 'generic' => 'Something else',
262 - 'custom' => 'Custom headers',
263 - ),
264 - 'label' => __( 'Cache In Front Of This Site', 'xspeed' ),
265 - 'description' => __( 'Ask a CDN or proxy in front of your site not to store pages xSpeed refused to cache. Leave it on Detect automatically unless you know what is in front of you; the marked providers ignore origin headers until you configure them to respect it.', 'xspeed' ),
266 - 'info_title' => __( 'Cache in front of this site', 'xspeed' ),
267 - 'info' => __( 'Naming your provider narrows the headers to the one it reads. Detect automatically works it out per request and otherwise sends a set every cache ignores unless it understands it, so it is safe not to know. Run "wp xspeed cache edge" to see what was detected and what gets sent.', 'xspeed' )
268 - ),
269 - 'edge_custom_headers' => array(
270 - 'type' => 'list',
271 - 'default' => array(),
272 - 'item_type' => 'string',
273 - 'label' => __( 'Custom Edge Headers', 'xspeed' ),
274 - 'dependsOn' => array( 'field' => 'edge_provider', 'value' => 'custom' ),
275 - 'description' => __( 'One header per line, as Name: value — for example "Surrogate-Control: no-store". Lines starting with # are ignored.', 'xspeed' ),
276 - 'info_title' => __( 'Custom edge headers', 'xspeed' ),
277 - 'info' => __( 'These replace the headers xSpeed would have picked for your CDN. Two baselines are still added underneath: a Cache-Control, and "X-Accel-Expires: 0" for a page cache running in nginx on your own server. Name either one yourself and yours is used instead. Values containing $, % or a backslash are dropped — the same pairs go into nginx and Apache directives, where those cannot be escaped safely. Content-Length, Content-Encoding, Content-Type, Transfer-Encoding, Set-Cookie and Location are refused.', 'xspeed' )
278 - ),
279 232 );
280 233 }
281 234
282 235 /**
@@ -463,14 +416,14 @@
463 416 ),
464 417 array(
465 418 'name' => 'xspeed cache',
466 419 'callback' => array( $this, 'cli_handler' ),
467 - 'shortdesc' => 'Inspect the Cache module: `status` (settings), `inventory` (which pages are cached, and how old), `size` (where the disk usage goes), `purge-log` (what cleared the cache, when and why), `purge-url <url>` to clear one page, `recheck-rewrite` to re-run the static-rewrite probe, or `nginx-config` to print the unified nginx server-block for pasting into a vhost, or `edge` to show which cache is in front of the site and what xSpeed tells it. To clear the whole site use `wp xspeed purge`.',
420 + 'shortdesc' => 'Inspect the Cache module: `status` (settings), `inventory` (which pages are cached, and how old), `size` (where the disk usage goes), `purge-log` (what cleared the cache, when and why), `purge-url <url>` to clear one page, `recheck-rewrite` to re-run the static-rewrite probe, or `nginx-config` to print the unified nginx server-block for pasting into a vhost. To clear the whole site use `wp xspeed purge`.',
468 421 'synopsis' => array(
469 422 array(
470 423 'type' => 'positional',
471 424 'name' => 'action',
472 - 'options' => array( 'status', 'inventory', 'size', 'purge-log', 'purge-url', 'recheck-rewrite', 'nginx-config', 'edge' ),
425 + 'options' => array( 'status', 'inventory', 'size', 'purge-log', 'purge-url', 'recheck-rewrite', 'nginx-config' ),
473 426 'optional' => true,
474 427 ),
475 428 array(
476 429 'type' => 'positional',
@@ -879,99 +832,13 @@
879 832 $this->cli_purge_log( $limit );
880 833 return;
881 834 }
882 835
883 - if ( 'edge' === $action ) {
884 - $this->cli_edge();
885 - return;
886 - }
887 -
888 836 $opts = Settings_Manager::get( self::SLUG );
889 837 \WP_CLI::log( 'cache_expiry ' . $opts['cache_expiry'] . 'h' );
890 838 \WP_CLI::log( 'excluded_urls ' . count( $opts['excluded_urls'] ) . ' entries' );
891 839 foreach ( $opts['excluded_urls'] as $u ) {
892 840 \WP_CLI::log( ' - ' . $u );
893 - }
894 - $edge = \XSpeed\Edge_Provider::detect();
895 - \WP_CLI::log( 'edge ' . ( '' !== $edge['provider'] ? $edge['provider'] : $edge['confidence'] ) . ' (' . $edge['source'] . ')' );
896 - }
897 -
898 - /**
899 - * `wp xspeed cache edge` — what we think is in front, and what we say to it.
900 - *
901 - * Worth printing even when nothing is held back. "You are behind
902 - * Cloudflare, and a Cache Rule set to ignore origin headers overrides
903 - * anything xSpeed sends" is the answer to a support question that
904 - * otherwise costs someone a week, and it is true whether or not a hold
905 - * ever fires.
906 - */
907 - private function cli_edge(): void {
908 - $answer = \XSpeed\Edge_Provider::detect();
909 -
910 - \WP_CLI::log( 'provider ' . ( '' !== $answer['provider'] ? $answer['provider'] : '(none named)' ) );
911 - \WP_CLI::log( 'confidence ' . $answer['confidence'] );
912 - \WP_CLI::log( 'source ' . $answer['source'] );
913 -
914 - // A pin outranks detection by design, so nothing re-checks it on the
915 - // site's behalf. Saying the two disagree is the whole mechanism by
916 - // which a site that changed CDN ever finds out.
917 - $sniffed = \XSpeed\Edge_Provider::sniffed();
918 - if ( in_array( $answer['source'], array( 'setting', 'constant', 'filter' ), true )
919 - && '' !== $sniffed['provider']
920 - && $sniffed['provider'] !== $answer['provider'] ) {
921 - \WP_CLI::warning(
922 - sprintf(
923 - 'This request looks like %s, but the provider is pinned to %s. If the site moved, change it — the pinned answer is also baked into the drop-in and the server rules.',
924 - $sniffed['provider'],
925 - '' !== $answer['provider'] ? $answer['provider'] : 'off'
926 - )
927 - );
928 - }
929 -
930 - if ( \XSpeed\Edge_Provider::is_off( $answer ) ) {
931 - \WP_CLI::log( '' );
932 - \WP_CLI::log( 'Nothing is sent: this is switched off.' );
933 - return;
934 - }
935 -
936 - // Resolved through edge_headers_for() rather than straight off the
937 - // provider, so this prints what the serve path would ACTUALLY send —
938 - // including `X-XSpeed-Edge-Hold`, and including the evidence gate.
939 - // Listing the provider's raw set ignored that gate and told operators
940 - // a first render would be held on a site where it would not be.
941 - //
942 - // `bake`, not `request`. Two reasons, and the second one matters:
943 - // this command answers for the site rather than for one response, and
944 - // `request` fires `xspeed_edge_optimization_pending`, whose Pro
945 - // listener resolves the CSS plan — which by its own description is
946 - // what queues a build. A read-only command must not burn a build
947 - // slot, quarantine an entry or purge a page just by being run, and
948 - // under WP-CLI it would do all three against the home page.
949 - $bypass = \XSpeed\Cache::edge_headers_for( 'BYPASS', 'bake', 'logged-in' );
950 - $miss = \XSpeed\Cache::edge_headers_for( 'MISS', 'bake' );
951 -
952 - \WP_CLI::log( '' );
953 - \WP_CLI::log( 'On a page xSpeed refuses to cache (a cart, a logged-in view):' );
954 - foreach ( $bypass as $name => $value ) {
955 - \WP_CLI::log( sprintf( ' %s: %s', $name, $value ) );
956 - }
957 -
958 - \WP_CLI::log( '' );
959 - if ( array() === $miss ) {
960 - \WP_CLI::log( 'On a first render: nothing. A MISS is a performance hedge, so it is held only where a cache in front was detected — and none was. Name the provider in Cache In Front Of This Site to cover first renders too.' );
961 - } else {
962 - \WP_CLI::log( 'On a first render:' );
963 - foreach ( $miss as $name => $value ) {
964 - \WP_CLI::log( sprintf( ' %s: %s', $name, $value ) );
965 - }
966 - }
967 -
968 - \WP_CLI::log( '' );
969 - \WP_CLI::log( 'X-XSpeed-Edge-Hold names why a response was held: bypass, bypass-shape, miss, mobile-split or pending. No header means nothing was held.' );
970 -
971 - if ( 'cloudflare' === $answer['provider'] ) {
972 - \WP_CLI::log( '' );
973 - \WP_CLI::log( 'A Cloudflare Cache Rule whose Edge TTL is "Ignore cache-control header and use this TTL" overrides all of the above. Use "Respect origin TTL" on that rule if pages are still being stored.' );
974 841 }
975 842 }
976 843
977 844 /** `wp xspeed cache inventory [--limit=N]` — which pages are cached, and how old. */