Skip to content

Commit ddcd3ae

Browse files
committed
Revert gzip compression of URL Metric data
1 parent 47eef00 commit ddcd3ae

File tree

6 files changed

+10
-323
lines changed

6 files changed

+10
-323
lines changed

plugins/optimization-detective/detect.js

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -329,23 +329,6 @@ function extendElementData( xpath, properties ) {
329329
Object.assign( elementData, properties );
330330
}
331331

332-
/**
333-
* Compresses a (JSON) string using CompressionStream API.
334-
*
335-
* @param {string} jsonString - JSON string to compress.
336-
* @return {Promise<Blob>} Compressed data.
337-
*/
338-
async function compress( jsonString ) {
339-
const encodedData = new TextEncoder().encode( jsonString );
340-
const compressedDataStream = new Blob( [ encodedData ] )
341-
.stream()
342-
.pipeThrough( new CompressionStream( 'gzip' ) );
343-
const compressedDataBuffer = await new Response(
344-
compressedDataStream
345-
).arrayBuffer();
346-
return new Blob( [ compressedDataBuffer ], { type: 'application/gzip' } );
347-
}
348-
349332
/**
350333
* @typedef {{timestamp: number, creationDate: Date}} UrlMetricDebugData
351334
* @typedef {{groups: Array<{url_metrics: Array<UrlMetricDebugData>}>}} CollectionDebugData
@@ -361,8 +344,6 @@ async function compress( jsonString ) {
361344
* @param {boolean} args.isDebug - Whether to show debug messages.
362345
* @param {string} args.restApiEndpoint - URL for where to send the detection data.
363346
* @param {string} [args.restApiNonce] - Nonce for the REST API when the user is logged-in.
364-
* @param {boolean} args.gzdecodeAvailable - Whether application/gzip can be sent to the REST API.
365-
* @param {number} args.maxUrlMetricSize - Maximum size of the URL Metric to send.
366347
* @param {string} args.currentETag - Current ETag.
367348
* @param {string} args.currentUrl - Current URL.
368349
* @param {string} args.urlMetricSlug - Slug for URL Metric.
@@ -381,8 +362,6 @@ export default async function detect( {
381362
extensionModuleUrls,
382363
restApiEndpoint,
383364
restApiNonce,
384-
gzdecodeAvailable,
385-
maxUrlMetricSize,
386365
currentETag,
387366
currentUrl,
388367
urlMetricSlug,
@@ -817,17 +796,7 @@ export default async function detect( {
817796
const maxBodyLengthBytes = maxBodyLengthKiB * 1024;
818797

819798
const jsonBody = JSON.stringify( urlMetric );
820-
if ( jsonBody.length > maxUrlMetricSize ) {
821-
error(
822-
`URL Metric is ${ jsonBody.length.toLocaleString() } bytes, exceeding the maximum size of ${ maxUrlMetricSize.toLocaleString() } bytes:`,
823-
urlMetric
824-
);
825-
return;
826-
}
827-
828-
const payloadBlob = gzdecodeAvailable
829-
? await compress( jsonBody )
830-
: new Blob( [ jsonBody ], { type: 'application/json' } );
799+
const payloadBlob = new Blob( [ jsonBody ], { type: 'application/json' } );
831800
const percentOfBudget =
832801
( payloadBlob.size / ( maxBodyLengthKiB * 1000 ) ) * 100;
833802

plugins/optimization-detective/detection.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,6 @@ static function ( OD_URL_Metric_Group $group ): array {
140140
'storageLockTTL' => OD_Storage_Lock::get_ttl(),
141141
'freshnessTTL' => od_get_url_metric_freshness_ttl(),
142142
'webVitalsLibrarySrc' => $web_vitals_lib_src,
143-
'gzdecodeAvailable' => function_exists( 'gzdecode' ),
144-
'maxUrlMetricSize' => od_get_maximum_url_metric_size(),
145143
);
146144
if ( is_user_logged_in() ) {
147145
$detect_args['restApiNonce'] = wp_create_nonce( 'wp_rest' );
@@ -174,8 +172,6 @@ function od_register_rest_url_metric_store_endpoint(): void {
174172
$endpoint_controller::ROUTE_BASE,
175173
$endpoint_controller->get_registration_args()
176174
);
177-
178-
add_filter( 'rest_pre_dispatch', array( $endpoint_controller, 'decompress_rest_request_body' ), 10, 3 );
179175
}
180176

181177
/**

plugins/optimization-detective/storage/class-od-rest-url-metrics-store-endpoint.php

Lines changed: 7 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,13 @@ public function handle_rest_request( WP_REST_Request $request ) {
230230
);
231231
}
232232

233-
// Limit JSON payload size to safeguard against clients sending possibly malicious payloads much larger than allowed.
234-
$max_size = od_get_maximum_url_metric_size();
233+
/*
234+
* The limit for data sent via navigator.sendBeacon() is 64 KiB. This limit is checked in detect.js so that the
235+
* request will not even be attempted if the payload is too large. This server-side restriction is added as a
236+
* safeguard against clients sending possibly malicious payloads much larger than 64 KiB which should never be
237+
* getting sent.
238+
*/
239+
$max_size = 64 * 1024; // 64 KB
235240
$content_length = strlen( (string) wp_json_encode( $url_metric ) );
236241
if ( $content_length > $max_size ) {
237242
return new WP_Error(
@@ -307,65 +312,4 @@ public function handle_rest_request( WP_REST_Request $request ) {
307312
)
308313
);
309314
}
310-
311-
/**
312-
* Decompresses the REST API request body for the URL Metrics endpoint.
313-
*
314-
* @since n.e.x.t
315-
* @access private
316-
*
317-
* @phpstan-param WP_REST_Request<array<string, mixed>> $request
318-
*
319-
* @param mixed $result Response to replace the requested version with. Can be anything a normal endpoint can return, or null to not hijack the request.
320-
* @param WP_REST_Server $server Server instance.
321-
* @param WP_REST_Request $request Request used to generate the response.
322-
* @return mixed Passed through $result if successful, or otherwise a WP_Error.
323-
*/
324-
public function decompress_rest_request_body( $result, WP_REST_Server $server, WP_REST_Request $request ) {
325-
unset( $server ); // Unused.
326-
327-
if (
328-
$request->get_route() === '/' . self::ROUTE_NAMESPACE . self::ROUTE_BASE &&
329-
'application/gzip' === $request->get_header( 'Content-Type' ) &&
330-
function_exists( 'gzdecode' )
331-
) {
332-
$compressed_body = $request->get_body();
333-
334-
/*
335-
* The limit for data sent via navigator.sendBeacon() is 64 KiB. This limit is checked in detect.js so that the
336-
* request will not even be attempted if the payload is too large. This server-side restriction is added as a
337-
* safeguard against clients sending possibly malicious payloads much larger than 64 KiB which should never be
338-
* getting sent.
339-
*/
340-
$max_size = 64 * 1024; // 64 KB
341-
$content_length = strlen( $compressed_body );
342-
if ( $content_length > $max_size ) {
343-
return new WP_Error(
344-
'rest_content_too_large',
345-
sprintf(
346-
/* translators: 1: the size of the payload, 2: the maximum allowed payload size */
347-
__( 'Compressed JSON payload size is %1$s bytes which is larger than the maximum allowed size of %2$s bytes.', 'optimization-detective' ),
348-
number_format_i18n( $content_length ),
349-
number_format_i18n( $max_size )
350-
),
351-
array( 'status' => 413 )
352-
);
353-
}
354-
355-
$decompressed_body = @gzdecode( $compressed_body ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- We need to suppress errors here.
356-
357-
if ( false === $decompressed_body ) {
358-
return new WP_Error(
359-
'rest_invalid_payload',
360-
__( 'Unable to decompress the gzip payload.', 'optimization-detective' ),
361-
array( 'status' => 400 )
362-
);
363-
}
364-
365-
// Update the request so later handlers see the decompressed JSON.
366-
$request->set_body( $decompressed_body );
367-
$request->set_header( 'Content-Type', 'application/json' );
368-
}
369-
return $result;
370-
}
371315
}

plugins/optimization-detective/storage/data.php

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -460,40 +460,3 @@ function od_get_url_metrics_breakpoint_sample_size(): int {
460460

461461
return $sample_size;
462462
}
463-
464-
/**
465-
* Gets the maximum allowed size in bytes for a URL Metric serialized to JSON.
466-
*
467-
* @since n.e.x.t
468-
* @access private
469-
*
470-
* @return positive-int Maximum allowed byte size.
471-
*/
472-
function od_get_maximum_url_metric_size(): int {
473-
/**
474-
* Filters the maximum allowed size in bytes for a URL Metric serialized to JSON.
475-
*
476-
* The default value is 1 MB.
477-
*
478-
* @since n.e.x.t
479-
*
480-
* @param int $max_size Maximum allowed byte size.
481-
* @return int Filtered maximum allowed byte size.
482-
*/
483-
$size = (int) apply_filters( 'od_maximum_url_metric_size', MB_IN_BYTES );
484-
if ( $size <= 0 ) {
485-
_doing_it_wrong(
486-
esc_html( "Filter: 'od_maximum_url_metric_size'" ),
487-
esc_html(
488-
sprintf(
489-
/* translators: %s: size */
490-
__( 'Invalid size "%s". Must be greater than zero.', 'optimization-detective' ),
491-
$size
492-
)
493-
),
494-
'Optimization Detective 1.0.0'
495-
);
496-
$size = MB_IN_BYTES;
497-
}
498-
return $size;
499-
}

0 commit comments

Comments
 (0)