Problem/Motivation
This may be something that is limited to our Drupal setups as we run our admin side on a different subdomain to the subdomain that the anonymous customers access the site on. Ie. Drupal users login to the site on https://admin.example.com while the general public are accessing https://www.example.com.
purge_file assumes FileInterface::createFileUrl() always returns a relative path when building URLs for url and wildcardurl invalidation. On sites where public file URLs are already absolute, this produces malformed URLs by prepending base_urls a second time.
Actual behaviour:
When a file is uploaded from the admin subdomain (https://admin.example.com), createFileUrl() can return an absolute URL such as:
https://www.example.com/sites/default/files/...
purge_file then builds the purge target like this:
https://www.example.com + https://www.example.com/sites/default/files/...
That triggers Purge’s validation error:
InvalidExpressionException: The URL is invalid.
Expected behaviour:
If createFileUrl() already returns an absolute URL, purge_file should use it as-is. Only relative URLs should be prefixed with base_urls.
Steps to reproduce
I'm not sure how others can recreate this because we use our own custom module to provide the admin subdomain functionality, but this should be true of anyone who has configured their files to come from a subdomain (or even a different domain) other than what admin users log in on? Possibly this is hitting users who have https://www.drupal.org/project/domain installed and are serving shared images? Any environment where public file URLs are absolute can hit this, including:
- separate admin and frontend domains
- CDN/public-file rewriting
- other absolute URL stream wrapper setups
1. Enable purge_file with workflow: queue and invalidation_type: url.
2. Upload a file through a new 'Image' media item on a domain other than what the images will be served on.
3. Observe the malformed double-prefixed URL and the invalidation error in watchdog:
Drupal\purge\Plugin\Purge\Invalidation\Exception\InvalidExpressionException exception during file invalidation via workflow "queue", File id: 741813, File: public://assets/media/image/1234567890.jpg, Invalidator: url, Error: The URL is invalid.
Proposed resolution
The fix for this is to check whether the value returned by $file->createFileUrl() is absolute.
--- a/purge_file.module
+++ b/purge_file.module
@@ -5,6 +5,7 @@
* Purge files that have changed in the system (uri / size).
*/
+use Drupal\Component\Utility\UrlHelper;
use Drupal\file\FileInterface;
@@ -115,20 +116,27 @@
// Allow others to dynamically alter the base urls to purge.
\Drupal::moduleHandler()->alter('purge_file_base_urls', $base_urls, $file);
+ $file_url = $file->createFileUrl();
+
// Build urls to purge.
$urls = [];
if (in_array($invalidator, ['url', 'wildcardurl'], TRUE)) {
- foreach ($base_urls as $base_url) {
- $urls[] = rtrim($base_url, '/') . $file->createFileUrl();
+ if (UrlHelper::isExternal($file_url)) {
+ $urls[] = $file_url;
+ }
+ else {
+ foreach ($base_urls as $base_url) {
+ $urls[] = rtrim($base_url, '/') . $file_url;
+ }
}
}
else {
- $urls[] = ltrim($file->createFileUrl(), '/');
+ $urls[] = ltrim($file_url, '/');
}
$invalidations = [];
Potentially the code should take the absolute URL and then try to get the relative one so that base_urls can be prepended?
Remaining tasks
Decide whether the code needs to also work out the relative URL so that the base_urls can be successfully prepended.
| Comment | File | Size | Author |
|---|
Issue fork purge_file-3601241
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
altcom_neil commentedComment #5
omarlopesinoHi, many thanks for pointing out this bug!
I have created a merge request that based on your patch. It additionally excludes from purging URLs not managed by the self domain.
After checking the MR is okay I will merge it.
Comment #7
omarlopesinoThis is fixed in the main branch. I am working on a release with more solved issues.
Now the module don't send to purge URLs that do not belong to the drupal site base URLs.