Skip to content

Commit bcefd69

Browse files
committed
Avoid preloading background images larger than 2MB
1 parent 5373233 commit bcefd69

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

plugins/image-prioritizer/helper.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,30 @@ static function ( $host ) {
234234
);
235235
}
236236

237-
// TODO: Check for the Content-Length and return invalid if it is gigantic?
237+
/*
238+
* Validate that the Content-Length is not too massive, as it would be better to err on the side of
239+
* not preloading something so weighty in case the image won't actually end up as LCP.
240+
* The value of 2MB is chosen because according to Web Almanac 2022, the largest image by byte size
241+
* on a page is 1MB at the 90th percentile: <https://almanac.httparchive.org/en/2022/media#fig-12>.
242+
* The 2MB value is double this 1MB size.
243+
*/
244+
$content_length = (array) wp_remote_retrieve_header( $r, 'content-length' );
245+
if ( ! is_numeric( $content_length[0] ) ) {
246+
return new WP_Error(
247+
'background_image_content_length_unknown',
248+
__( 'HEAD request for background image URL did not include a Content-Length response header.', 'image-prioritizer' )
249+
);
250+
} elseif ( (int) $content_length[0] > 2 * MB_IN_BYTES ) {
251+
return new WP_Error(
252+
'background_image_content_length_too_large',
253+
sprintf(
254+
/* translators: %s is the content length of the response */
255+
__( 'HEAD request for background image URL returned Content-Length greater than 2MB: %s.', 'image-prioritizer' ),
256+
$content_length[0]
257+
)
258+
);
259+
}
260+
238261
return true;
239262
}
240263

plugins/image-prioritizer/tests/test-helper.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,37 @@ static function ( $pre, $parsed_args, $url ) use ( $video_url ) {
639639
'expect_error' => 'background_image_response_not_image',
640640
),
641641

642+
'bad_content_length' => array(
643+
'set_up' => static function (): string {
644+
$image_url = home_url( '/massive-image.jpg' );
645+
646+
add_filter(
647+
'pre_http_request',
648+
static function ( $pre, $parsed_args, $url ) use ( $image_url ) {
649+
if ( 'HEAD' !== $parsed_args['method'] || $image_url !== $url ) {
650+
return $pre;
651+
}
652+
return array(
653+
'headers' => array(
654+
'content-type' => 'image/jpeg',
655+
'content-length' => (string) ( 2 * MB_IN_BYTES + 1 ),
656+
),
657+
'body' => '',
658+
'response' => array(
659+
'code' => 200,
660+
'message' => 'OK',
661+
),
662+
);
663+
},
664+
10,
665+
3
666+
);
667+
668+
return $image_url;
669+
},
670+
'expect_error' => 'background_image_content_length_too_large',
671+
),
672+
642673
'bad_redirect' => array(
643674
'set_up' => static function (): string {
644675
$redirect_url = home_url( '/redirect.jpg' );

0 commit comments

Comments
 (0)