Cache response status and headers when fetching external stylesheets#4509
Cache response status and headers when fetching external stylesheets#4509westonruter merged 12 commits intodevelopfrom
Conversation
Co-Authored-By: Alain Schlesser <alain.schlesser@gmail.com>
|
Last commit should have been " |
| * @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.
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.
| * @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.
| * @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.
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.
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.
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 ) { |
Co-Authored-By: Alain Schlesser <alain.schlesser@gmail.com>
…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. |
| 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.
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.
| * @var string | ||
| */ | ||
| const TRANSIENT_PREFIX = 'amp_remote_request_'; | ||
| const TRANSIENT_PREFIX = 'amp_remote_request_v2_'; |
There was a problem hiding this comment.
Updated the transient prefix to bust the cache.
There was a problem hiding this comment.
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 <westonruter@google.com>
Co-Authored-By: Weston Ruter <westonruter@google.com>
westonruter
left a comment
There was a problem hiding this comment.
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.
| 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.
Why is this return needed?
| return $response; |
Would removing it make the logic more consistent between cached and non-cached code paths?
| * @var string | ||
| */ | ||
| const TRANSIENT_PREFIX = 'amp_remote_request_'; | ||
| const TRANSIENT_PREFIX = 'amp_remote_request_v2_'; |
There was a problem hiding this comment.
Might not be necessary if we check the type of the class per my comment below.
westonruter
left a comment
There was a problem hiding this comment.
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/bulma@0.8.0/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 <alain.schlesser@gmail.com> * Rename CachedData to CacheResponse * Rename exception not being thrown * Apply suggestions from Alain Co-Authored-By: Alain Schlesser <alain.schlesser@gmail.com> * Add FailedRemoteRequest interface to mark exception classes related to remote requests * Use specific exception name in docblock Co-Authored-By: Weston Ruter <westonruter@google.com> * Use specific exception name in docblock Co-Authored-By: Weston Ruter <westonruter@google.com> * Check if cached response is an instance of CachedResponse::class * Remove unused imports Co-authored-by: Alain Schlesser <alain.schlesser@gmail.com> Co-authored-by: Weston Ruter <westonruter@google.com>
* 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
RemoteGetRequestResponseis 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
RemoteGetRequestResponseobject 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