diff --git a/plugins/image-prioritizer/helper.php b/plugins/image-prioritizer/helper.php index ba7a88800..e80b8f41c 100644 --- a/plugins/image-prioritizer/helper.php +++ b/plugins/image-prioritizer/helper.php @@ -234,7 +234,30 @@ static function ( $host ) { ); } - // TODO: Check for the Content-Length and return invalid if it is gigantic? + /* + * Validate that the Content-Length is not too massive, as it would be better to err on the side of + * not preloading something so weighty in case the image won't actually end up as LCP. + * The value of 2MB is chosen because according to Web Almanac 2022, the largest image by byte size + * on a page is 1MB at the 90th percentile: . + * The 2MB value is double this 1MB size. + */ + $content_length = (array) wp_remote_retrieve_header( $r, 'content-length' ); + if ( ! is_numeric( $content_length[0] ) ) { + return new WP_Error( + 'background_image_content_length_unknown', + __( 'HEAD request for background image URL did not include a Content-Length response header.', 'image-prioritizer' ) + ); + } elseif ( (int) $content_length[0] > 2 * MB_IN_BYTES ) { + return new WP_Error( + 'background_image_content_length_too_large', + sprintf( + /* translators: %s is the content length of the response */ + __( 'HEAD request for background image URL returned Content-Length greater than 2MB: %s.', 'image-prioritizer' ), + $content_length[0] + ) + ); + } + return true; } diff --git a/plugins/image-prioritizer/tests/test-helper.php b/plugins/image-prioritizer/tests/test-helper.php index 7d3d3a5db..45e91cccd 100644 --- a/plugins/image-prioritizer/tests/test-helper.php +++ b/plugins/image-prioritizer/tests/test-helper.php @@ -639,6 +639,37 @@ static function ( $pre, $parsed_args, $url ) use ( $video_url ) { 'expect_error' => 'background_image_response_not_image', ), + 'bad_content_length' => array( + 'set_up' => static function (): string { + $image_url = home_url( '/massive-image.jpg' ); + + add_filter( + 'pre_http_request', + static function ( $pre, $parsed_args, $url ) use ( $image_url ) { + if ( 'HEAD' !== $parsed_args['method'] || $image_url !== $url ) { + return $pre; + } + return array( + 'headers' => array( + 'content-type' => 'image/jpeg', + 'content-length' => (string) ( 2 * MB_IN_BYTES + 1 ), + ), + 'body' => '', + 'response' => array( + 'code' => 200, + 'message' => 'OK', + ), + ); + }, + 10, + 3 + ); + + return $image_url; + }, + 'expect_error' => 'background_image_content_length_too_large', + ), + 'bad_redirect' => array( 'set_up' => static function (): string { $redirect_url = home_url( '/redirect.jpg' );