-
Notifications
You must be signed in to change notification settings - Fork 383
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
Cache response status and headers when fetching external stylesheets #4509
Conversation
Co-Authored-By: Alain Schlesser <[email protected]>
Last commit should have been " |
@@ -101,42 +102,48 @@ public function __construct( | |||
* | |||
* @param string $url URL to get. | |||
* @return Response Response for the executed request. | |||
* @throws FailedToGetFromRemoteUrl If retrieving the contents from the URL failed. | |||
* @throws FailedToGetFromRemoteUrl|FailedToGetCachedResponseData If retrieving the contents from the reponse failed. |
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.
Actually, the FailedToGetFromRemoteUrl
is being caught, so the only one that might be thrown here is FailedToGetCachedResponseData
.
However, that actually contradicts the interface RemoteGetRequest
... So we should either adapt the interface to consider both types of exceptions, or roll everything into one agaon.
@@ -101,42 +102,48 @@ public function __construct( | |||
* | |||
* @param string $url URL to get. | |||
* @return Response Response for the executed request. | |||
* @throws FailedToGetFromRemoteUrl If retrieving the contents from the URL failed. | |||
* @throws FailedToGetFromRemoteUrl|FailedToGetCachedResponseData If retrieving the contents from the reponse failed. |
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.
* @throws FailedToGetFromRemoteUrl|FailedToGetCachedResponseData If retrieving the contents from the reponse failed. | |
* @throws FailedToGetFromRemoteUrl|FailedToGetCachedResponseData If retrieving the contents from the response failed. |
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.
Alright, I think what should happen here is that we provide an exception interface FailedRemoteRequest
and have both FailedToGetFromRemoteUrl
and FailedToGetCachedResponseData
implement that.
That way, we can add a @throws FailedRemoteRequest ...
to the RemoteGetRequest
interface, and when we provide more specific exceptions in the implementations, we won't contradict the RemoteGetRequest
interface.
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.
Done in af0b450.
src/RemoteRequest/CachedResponse.php
Outdated
* @param int $status_code Cached status code. | ||
* @param DateTimeInterface $expiry Expiry of the cached value. | ||
*/ | ||
public function __construct( $body, array $headers, $status_code, DateTimeInterface $expiry ) { |
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.
Don't use a type declaration with array
, as that is broken in PHP. There's no possibility whatsoever to extend the array
into an object with added logic and still pass that type declaration. Therefore, this is a hard lock-in into the exact array
type, without any leeway.
public function __construct( $body, array $headers, $status_code, DateTimeInterface $expiry ) { | |
public function __construct( $body, $headers, $status_code, DateTimeInterface $expiry ) { |
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.
Done in e87ab88.
Co-Authored-By: Alain Schlesser <[email protected]>
…o remote requests
All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the ℹ️ Googlers: Go here for more info. |
@@ -8,3 +8,5 @@ parameters: | |||
- %currentWorkingDirectory%/src/ | |||
autoload_files: | |||
- %currentWorkingDirectory%/vendor/autoload.php | |||
ignoreErrors: | |||
- '#^PHPDoc tag @throws with type AmpProject\\Exception\\FailedRemoteRequest is not subtype of Throwable$#' |
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.
phpstan complains about FailedRemoteRequest
not being a subtype of Throwable
, but Throwable
is not available in PHP 5.6 so I'm ignoring it for now.
@@ -28,7 +30,7 @@ final class CachedRemoteGetRequest implements RemoteGetRequest { | |||
* | |||
* @var string | |||
*/ | |||
const TRANSIENT_PREFIX = 'amp_remote_request_'; | |||
const TRANSIENT_PREFIX = 'amp_remote_request_v2_'; |
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.
Updated the transient prefix to bust the cache.
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.
Might not be necessary if we check the type of the class per my comment below.
@schlessera This one's for you. |
@googlebot I consent. |
CLAs look good, thanks! ℹ️ Googlers: Go here for more info. |
Linting problems:
|
Co-Authored-By: Weston Ruter <[email protected]>
Co-Authored-By: Weston Ruter <[email protected]>
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.
A couple minor suggestions
} | ||
} | ||
|
||
if ( false === $cached_data || $cached_data->is_expired() ) { | ||
if ( false === $cached_response || $cached_response->is_expired() ) { |
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.
if ( false === $cached_response || $cached_response->is_expired() ) { | |
if ( ! $cached_response instanceof CachedResponse || $cached_response->is_expired() ) { |
|
||
return $response; |
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.
Why is this return
needed?
return $response; |
Would removing it make the logic more consistent between cached and non-cached code paths?
@@ -28,7 +30,7 @@ final class CachedRemoteGetRequest implements RemoteGetRequest { | |||
* | |||
* @var string | |||
*/ | |||
const TRANSIENT_PREFIX = 'amp_remote_request_'; | |||
const TRANSIENT_PREFIX = 'amp_remote_request_v2_'; |
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.
Might not be necessary if we check the type of the class per my comment below.
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.
It does fix the issue but I want to defer to @schlessera for his final approval.
Looks Good An external stylesheet: add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_style( 'bulma-cdn', 'https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css' );
} ); ...still appears after clicking 'Recheck', or refreshing a front-end URL: Before, validation resulted in the notice 'Unable to validate URL. A white screen of death was encountered which is likely due to a PHP fatal error. ' The error in the log didn't look to be related to the But with this PR, the error didn't appear. |
…4509) * Cache response status code and headers when fetching external stylesheets * Remove whitespace * Separate throw annotations Co-Authored-By: Alain Schlesser <[email protected]> * Rename CachedData to CacheResponse * Rename exception not being thrown * Apply suggestions from Alain Co-Authored-By: Alain Schlesser <[email protected]> * Add FailedRemoteRequest interface to mark exception classes related to remote requests * Use specific exception name in docblock Co-Authored-By: Weston Ruter <[email protected]> * Use specific exception name in docblock Co-Authored-By: Weston Ruter <[email protected]> * Check if cached response is an instance of CachedResponse::class * Remove unused imports Co-authored-by: Alain Schlesser <[email protected]> Co-authored-by: Weston Ruter <[email protected]>
* tag '1.5.2': Bump 1.5.2 Bump version to 1.5.1-RC1 Cache response status and headers when fetching external stylesheets (#4509) Fix securing multi-line mustache templates (#4521) Add CSS monitoring time series to Site Health debugging info (#4519) Update hostname used for WordPress TV embeds to fix external HTTP requests (#4524) Fix processing of element child sanitization loop when invalid elements are replaced with children (#4512) Account for more YouTube URL formats (#4508) Update selected featured image ID on select (#4453) Raise default threshold for disabling CSS caching (#4513) Cast i-amphtml-intrinsic-sizer dimensions to integers (#4506) Only move meta tags to the head when required and add processing for meta[http-equiv] (#4505) Fix failing tests (#4507) Bump 1.5.2-alpha
…aching-reenable-button * 'develop' of github.com:ampproject/amp-wp: Restore unification of multi-page post content in Reader mode (#4547) Prevent styles from being removed when in Customizer preview with Standard mode (#4553) Omit Jetpack from being activated during PHPUnit test runs Use title case for Paired Browsing link in edit post screen (#4540) Ensure that validation query vars persist through redirects (#4544) Update dependency babel-jest to v25.2.6 (#4510) Update dependency css-loader to v3.5.0 (#4537) Update dependency autoprefixer to v9.7.6 (#4539) Add requirements to plugin file header (#4543) Force status code of validation responses to be 200 (#4533) Update optimizer test specs (#4527) Bump stable tag to 1.5.2 Cache response status and headers when fetching external stylesheets (#4509) Fix securing multi-line mustache templates (#4521) Add CSS monitoring time series to Site Health debugging info (#4519) Update hostname used for WordPress TV embeds to fix external HTTP requests (#4524) Mock Imgur embed tests Mock Facebook embed tests Standardize file and class names for embed handlers
Summary
When an external stylesheet URL is fetched for the first time, the body (stylesheet), headers, and status code are retrieved from the response and cached. A
RemoteGetRequestResponse
is then returned containing the stylesheet, headers and status code from the response.On a subsequent request to that same URL, the cached stylesheet is retrieved and a
RemoteGetRequestResponse
object is again returned, but this time the headers and status code being returned are set to their default values:amp-wp/src/RemoteRequest/CachedRemoteGetRequest.php
Lines 109 to 110 in 00036be
When the style sanitizer receives this response object it checks it throws an error due to the status code being
null
:amp-wp/includes/sanitizers/class-amp-style-sanitizer.php
Lines 1446 to 1451 in 5718373
This is then displayed to the user as the stylesheet failing to be retrieved:
This PR fixes the issue by caching the headers and status code from the first request of the stylesheet so that when it is to be retrieved again the correct response data is returned.
Fixes #4503.
Checklist