Skip to content

Commit a5c48c4

Browse files
authored
Merge pull request #1907 from ShyamGadde/fix/url-encoding-link-header
Fix URL encoding in Link HTTP response header
2 parents ad006e6 + 20a03ca commit a5c48c4

File tree

2 files changed

+55
-6
lines changed

2 files changed

+55
-6
lines changed

plugins/optimization-detective/class-od-link-collection.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -325,19 +325,17 @@ function ( $image_candidate ) {
325325
*
326326
* @since n.e.x.t
327327
*
328-
* @param string $url URL to percent encode. Any existing percent encodings will first be decoded.
328+
* @param string $url URL to percent encode.
329329
* @return string Percent-encoded URL.
330330
*/
331331
private function encode_url_for_response_header( string $url ): string {
332-
$decoded_url = urldecode( $url );
333-
334332
// Encode characters not allowed in a URL per RFC 3986 (anything that is not among the reserved and unreserved characters).
335333
$encoded_url = (string) preg_replace_callback(
336-
'/[^A-Za-z0-9\-._~:\/?#\[\]@!$&\'()*+,;=]/',
334+
'/[^A-Za-z0-9\-._~:\/?#\[\]@!$&\'()*+,;=%]/',
337335
static function ( $matches ) {
338336
return rawurlencode( $matches[0] );
339337
},
340-
$decoded_url
338+
$url
341339
);
342340
return esc_url_raw( $encoded_url );
343341
}

plugins/optimization-detective/tests/test-class-od-link-collection.php

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,58 @@ public function data_provider_to_test_add_link(): array {
489489
'expected_html' => '
490490
<link data-od-added-tag rel="preload" href="https://example.com/חנות/wp-content/uploads/2025/01/example.jpg?ver=1+2" as="image">
491491
',
492-
'expected_header' => 'Link: <https://example.com/%D7%97%D7%A0%D7%95%D7%AA/wp-content/uploads/2025/01/example.jpg?ver=1%202>; rel="preload"; as="image"',
492+
'expected_header' => 'Link: <https://example.com/%D7%97%D7%A0%D7%95%D7%AA/wp-content/uploads/2025/01/example.jpg?ver=1+2>; rel="preload"; as="image"',
493+
'expected_count' => 1,
494+
'error' => '',
495+
),
496+
'comma_in_query' => array(
497+
'links_args' => array(
498+
array(
499+
array(
500+
'rel' => 'preload',
501+
'href' => 'https://example.com/wp-content/uploads/2025/02/example.png?resize=768,432&ssl=1',
502+
'as' => 'image',
503+
),
504+
),
505+
),
506+
'expected_html' => '
507+
<link data-od-added-tag rel="preload" href="https://example.com/wp-content/uploads/2025/02/example.png?resize=768,432&amp;ssl=1" as="image">
508+
',
509+
'expected_header' => 'Link: <https://example.com/wp-content/uploads/2025/02/example.png?resize=768,432&ssl=1>; rel="preload"; as="image"',
510+
'expected_count' => 1,
511+
'error' => '',
512+
),
513+
'percent_encoded_comma_in_query' => array(
514+
'links_args' => array(
515+
array(
516+
array(
517+
'rel' => 'preload',
518+
'href' => 'https://example.com/wp-content/uploads/2025/02/example.png?resize=768%2C432&ssl=1',
519+
'as' => 'image',
520+
),
521+
),
522+
),
523+
'expected_html' => '
524+
<link data-od-added-tag rel="preload" href="https://example.com/wp-content/uploads/2025/02/example.png?resize=768%2C432&amp;ssl=1" as="image">
525+
',
526+
'expected_header' => 'Link: <https://example.com/wp-content/uploads/2025/02/example.png?resize=768%2C432&ssl=1>; rel="preload"; as="image"',
527+
'expected_count' => 1,
528+
'error' => '',
529+
),
530+
'percent_encoded_extension' => array(
531+
'links_args' => array(
532+
array(
533+
array(
534+
'rel' => 'preload',
535+
'href' => 'https://example.com/image.%6Apg',
536+
'as' => 'image',
537+
),
538+
),
539+
),
540+
'expected_html' => '
541+
<link data-od-added-tag rel="preload" href="https://example.com/image.%6Apg" as="image">
542+
',
543+
'expected_header' => 'Link: <https://example.com/image.%6Apg>; rel="preload"; as="image"',
493544
'expected_count' => 1,
494545
'error' => '',
495546
),

0 commit comments

Comments
 (0)