New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve URL handling in Optimization Detective #1043
Changes from all commits
7f170e6
7a93aad
56f2ebe
b259404
b6095dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,9 +85,49 @@ function od_get_normalized_query_vars(): array { | |
return $normalized_query_vars; | ||
} | ||
|
||
/** | ||
* Get the URL for the current request. | ||
* | ||
* This is essentially the REQUEST_URI prefixed by the scheme and host for the home URL. | ||
* This is needed in particular due to subdirectory installs. | ||
* | ||
* @since n.e.x.t | ||
* @access private | ||
* | ||
* @return string Current URL. | ||
*/ | ||
function od_get_current_url(): string { | ||
$parsed_url = wp_parse_url( home_url() ); | ||
if ( ! is_array( $parsed_url ) ) { | ||
$parsed_url = array(); | ||
} | ||
|
||
if ( empty( $parsed_url['scheme'] ) ) { | ||
$parsed_url['scheme'] = is_ssl() ? 'https' : 'http'; | ||
} | ||
if ( ! isset( $parsed_url['host'] ) ) { | ||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized | ||
$parsed_url['host'] = isset( $_SERVER['HTTP_HOST'] ) ? wp_unslash( $_SERVER['HTTP_HOST'] ) : 'localhost'; | ||
} | ||
|
||
$current_url = $parsed_url['scheme'] . '://' . $parsed_url['host']; | ||
if ( isset( $parsed_url['port'] ) ) { | ||
$current_url .= ':' . $parsed_url['port']; | ||
} | ||
$current_url .= '/'; | ||
|
||
if ( isset( $_SERVER['REQUEST_URI'] ) ) { | ||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized | ||
$current_url .= ltrim( wp_unslash( $_SERVER['REQUEST_URI'] ), '/' ); | ||
} | ||
Comment on lines
+119
to
+122
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thinking about my favorite edge-case of sites within a subdirectory, this works as expected, right? I guess since There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, |
||
return esc_url_raw( $current_url ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does this use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, humm, since potentially malicious data is present in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would think this is already handled by |
||
} | ||
|
||
/** | ||
* Gets slug for URL metrics. | ||
* | ||
* A slug is the hash of the normalized query vars. | ||
* | ||
* @since 0.1.0 | ||
* @access private | ||
* | ||
|
@@ -110,12 +150,14 @@ function od_get_url_metrics_slug( array $query_vars ): string { | |
* | ||
* @see wp_create_nonce() | ||
* @see od_verify_url_metrics_storage_nonce() | ||
* @see od_get_url_metrics_slug() | ||
* | ||
* @param string $slug URL metrics slug. | ||
* @param string $slug Slug (hash of normalized query vars). | ||
* @param string $url URL. | ||
* @return string Nonce. | ||
*/ | ||
function od_get_url_metrics_storage_nonce( string $slug ): string { | ||
return wp_create_nonce( "store_url_metrics:$slug" ); | ||
function od_get_url_metrics_storage_nonce( string $slug, string $url ): string { | ||
return wp_create_nonce( "store_url_metrics:$slug:$url" ); | ||
} | ||
|
||
/** | ||
|
@@ -126,13 +168,15 @@ function od_get_url_metrics_storage_nonce( string $slug ): string { | |
* | ||
* @see wp_verify_nonce() | ||
* @see od_get_url_metrics_storage_nonce() | ||
* @see od_get_url_metrics_slug() | ||
* | ||
* @param string $nonce URL metrics storage nonce. | ||
* @param string $slug URL metrics slug. | ||
* @param string $nonce Nonce. | ||
* @param string $slug Slug (hash of normalized query vars). | ||
* @param String $url URL. | ||
* @return bool Whether the nonce is valid. | ||
*/ | ||
function od_verify_url_metrics_storage_nonce( string $nonce, string $slug ): bool { | ||
return (bool) wp_verify_nonce( $nonce, "store_url_metrics:$slug" ); | ||
function od_verify_url_metrics_storage_nonce( string $nonce, string $slug, string $url ): bool { | ||
return (bool) wp_verify_nonce( $nonce, "store_url_metrics:$slug:$url" ); | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -141,25 +141,25 @@ static function ( $url_metric_data ) use ( $trigger_error ) { | |
} | ||
|
||
/** | ||
* Stores URL metric by merging it with the other URL metrics for a given URL. | ||
* Stores URL metric by merging it with the other URL metrics which share the same normalized query vars. | ||
* | ||
* @since 0.1.0 | ||
* @access private | ||
* | ||
* @param string $url URL for the URL metrics. This is used purely as metadata. | ||
* @param string $slug URL metrics slug (computed from query vars). | ||
* @param string $slug Slug (hash of normalized query vars). | ||
* @param OD_URL_Metric $new_url_metric New URL metric. | ||
* @return int|WP_Error Post ID or WP_Error otherwise. | ||
*/ | ||
function od_store_url_metric( string $url, string $slug, OD_URL_Metric $new_url_metric ) { | ||
|
||
// TODO: What about storing a version identifier? | ||
function od_store_url_metric( string $slug, OD_URL_Metric $new_url_metric ) { | ||
$post_data = array( | ||
'post_title' => $url, // TODO: Should we keep this? It can help with debugging. | ||
// The URL is supplied as the post title in order to aid with debugging. Note that an od-url-metrics post stores | ||
// multiple URL Metric instances, each of which also contains the URL for which the metric was captured. The URL | ||
// appearing in the post title is therefore the most recent URL seen for the URL Metrics which have the same | ||
// normalized query vars among them. | ||
'post_title' => $new_url_metric->get_url(), | ||
); | ||
|
||
$post = od_get_url_metrics_post( $slug ); | ||
|
||
if ( $post instanceof WP_Post ) { | ||
$post_data['ID'] = $post->ID; | ||
$post_data['post_name'] = $post->post_name; | ||
|
@@ -190,7 +190,7 @@ static function ( OD_URL_Metric $url_metric ): array { | |
}, | ||
$group_collection->get_flattened_url_metrics() | ||
), | ||
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES // TODO: No need for pretty-printing. | ||
JSON_UNESCAPED_SLASHES // No need for escaped slashes since not printed to frontend. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Completely unrelated question: Why is this relevant? Do frontend slashes have to be escaped? I'm asking since the Speculation Rules plugin JSON output contains backslashes which Domenic suggested to remove in my Speculation Rules post draft code example. I'm confused about whether those should or shouldn't be there. 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question. The slashes should always be present when the JSON is inline in HTML, as this prevents malicious strings from breaking out of the containing In the context of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Er, so that should probably be restored to Speculation Rules 😊 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, thanks for explaining. I believe Speculation Rules already does this correctly then, feel free to check. I was referring to the Make Core post draft I've been working on. |
||
); | ||
|
||
$has_kses = false !== has_filter( 'content_save_pre', 'wp_filter_post_kses' ); | ||
|
@@ -201,10 +201,11 @@ static function ( OD_URL_Metric $url_metric ): array { | |
|
||
$post_data['post_type'] = OD_URL_METRICS_POST_TYPE; | ||
$post_data['post_status'] = 'publish'; | ||
$slashed_post_data = wp_slash( $post_data ); | ||
if ( isset( $post_data['ID'] ) ) { | ||
$result = wp_update_post( wp_slash( $post_data ), true ); | ||
$result = wp_update_post( $slashed_post_data, true ); | ||
} else { | ||
$result = wp_insert_post( wp_slash( $post_data ), true ); | ||
$result = wp_insert_post( $slashed_post_data, true ); | ||
} | ||
|
||
if ( $has_kses ) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inspired by the same function in the AMP plugin: https://github.com/ampproject/amp-wp/blob/5708e19c60cf0f88ce522349fba955266b6892f6/includes/amp-helper-functions.php#L617-L662