From dcf0fe3d336d003f071bf36762e312054318d6d1 Mon Sep 17 00:00:00 2001 From: Liam Sarsfield <43409125+LiamSarsfield@users.noreply.github.com> Date: Fri, 15 May 2026 19:20:13 +0100 Subject: [PATCH 1/2] Boost LCP: preserve trailing slash on cornerstone URLs sent to cloud analyzer --- .../boost/app/lib/cornerstone/class-cornerstone-utils.php | 2 +- .../boost/changelog/fix-lcp-cornerstone-trailing-slash | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 projects/plugins/boost/changelog/fix-lcp-cornerstone-trailing-slash diff --git a/projects/plugins/boost/app/lib/cornerstone/class-cornerstone-utils.php b/projects/plugins/boost/app/lib/cornerstone/class-cornerstone-utils.php index 92c36ab6d419..db57588e6ba2 100644 --- a/projects/plugins/boost/app/lib/cornerstone/class-cornerstone-utils.php +++ b/projects/plugins/boost/app/lib/cornerstone/class-cornerstone-utils.php @@ -98,7 +98,7 @@ public static function get_provider_key( $url ) { public static function prepare_provider_data( $url ) { return array( 'key' => self::get_provider_key( $url ), - 'url' => self::sanitize_url( $url ), + 'url' => $url, ); } diff --git a/projects/plugins/boost/changelog/fix-lcp-cornerstone-trailing-slash b/projects/plugins/boost/changelog/fix-lcp-cornerstone-trailing-slash new file mode 100644 index 000000000000..8e8f758fec27 --- /dev/null +++ b/projects/plugins/boost/changelog/fix-lcp-cornerstone-trailing-slash @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +LCP: Fix Cornerstone Page analysis errors on some sites. From 0dc8aa252088e5c3f14ac24cc39ce252e758d5bd Mon Sep 17 00:00:00 2001 From: Brandon Kraft Date: Thu, 4 Jun 2026 09:28:07 -0500 Subject: [PATCH 2/2] Boost LCP: document trailing-slash invariant and add cornerstone util tests Add a comment on prepare_provider_data() explaining why the url is forwarded verbatim while the key stays sanitized, so a future refactor does not re-symmetrize them and reintroduce the edge/WAF 301/403 failure. Add unit tests pinning that url preserves the trailing slash and key is slash-agnostic. --- .../cornerstone/class-cornerstone-utils.php | 5 ++ .../cornerstone/Cornerstone_Utils_Test.php | 68 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 projects/plugins/boost/tests/php/lib/cornerstone/Cornerstone_Utils_Test.php diff --git a/projects/plugins/boost/app/lib/cornerstone/class-cornerstone-utils.php b/projects/plugins/boost/app/lib/cornerstone/class-cornerstone-utils.php index db57588e6ba2..27bea64d58b0 100644 --- a/projects/plugins/boost/app/lib/cornerstone/class-cornerstone-utils.php +++ b/projects/plugins/boost/app/lib/cornerstone/class-cornerstone-utils.php @@ -98,6 +98,11 @@ public static function get_provider_key( $url ) { public static function prepare_provider_data( $url ) { return array( 'key' => self::get_provider_key( $url ), + // Send the URL verbatim (do not sanitize/untrailingslashit it). The cloud analyzer + // fetches this exact URL, so it must keep the site's canonical trailing-slash form to + // avoid edge/WAF 301s or 403s that break analysis. The `key` is intentionally still + // stripped so storage/retrieval stays slash-agnostic. Do not "simplify" url back to + // self::sanitize_url( $url ). 'url' => $url, ); } diff --git a/projects/plugins/boost/tests/php/lib/cornerstone/Cornerstone_Utils_Test.php b/projects/plugins/boost/tests/php/lib/cornerstone/Cornerstone_Utils_Test.php new file mode 100644 index 000000000000..82fdd8104398 --- /dev/null +++ b/projects/plugins/boost/tests/php/lib/cornerstone/Cornerstone_Utils_Test.php @@ -0,0 +1,68 @@ +justReturn( 'https://example.com' ); + // untrailingslashit() strips trailing slashes/backslashes; reproduce that for the key path. + Functions\when( 'untrailingslashit' )->alias( + static function ( $string ) { + return rtrim( (string) $string, '/\\' ); + } + ); + } + + public function tearDown(): void { + Mockery::close(); + \Brain\Monkey\tearDown(); + parent::tearDown(); + } + + /** + * The `url` sent to the cloud analyzer must be forwarded verbatim, preserving the + * trailing slash. This is the whole point of HOG-562: the cloud fetches this exact URL, + * and stripping the slash caused edge/WAF 301s and 403s that broke analysis. + */ + public function test_prepare_provider_data_preserves_trailing_slash_on_url() { + $data = Cornerstone_Utils::prepare_provider_data( 'https://example.com/about/' ); + + $this->assertSame( 'https://example.com/about/', $data['url'] ); + } + + /** + * The `key` must stay slash-agnostic so storage and retrieval still correlate regardless of + * the URL form. A regression that re-symmetrized `url` and `key` (or stopped stripping the + * key) would surface here. + */ + public function test_prepare_provider_data_key_is_slash_agnostic() { + $with_slash = Cornerstone_Utils::prepare_provider_data( 'https://example.com/about/' ); + $without_slash = Cornerstone_Utils::prepare_provider_data( 'https://example.com/about' ); + + $this->assertSame( + $without_slash['key'], + $with_slash['key'], + 'The provider key must be identical for the trailing-slash and no-slash forms of the same page.' + ); + + // The key is derived from the sanitized URL, so it never carries the trailing slash itself. + $this->assertStringEndsNotWith( '/', $with_slash['key'] ); + } +}