Problem/Motivation
Setting 'Enforce clean and canonical URLs.' breaks CSS aggregation on multilingual Drupal 10.1.x with browser caching enabled and where your language has a prefix (f.e. 'en' for English) configured.
Change record https://www.drupal.org/node/3301716 introduced a performance improvement that boils down to: Instead of a page request creating and writing several files before it can be sent to the browser, now the main page request just generates the URLs, and the actual CSS or JavaScript aggregate is individually created by PHP (and still written to disk assuming it's valid).
Behaviour before the change:
A page is requested, the main request generates the aggregated CSS files and writes them to the disk. The HTML of the page is returned to the browser. The browser requests the aggregated CSS files and they are present of the disk so they are returned.
Behaviour after the change:
A page is requested, it no longer generates the aggregated CSS files. The HTML of the page is returned to the browser. The browser requests the aggregated CSS files. They are not present on the disk so they are generated. The RouteNormalizerRequestSubscriber from this module is now triggered when aggregated CSS files are requested from the browser and a redirect response is returned from it redirecting /sites/default/files/css/css_MXjpf7HZqh... to /en/sites/default/files/css/css_MXjpf7HZqh... . The browser then requests /en/sites/default/files/css/css_MXjpf7HZqh... which loads fine but later requests for this URL are blocked by the browser because of MIME type checks because the MIME type is no longer 'text/css' but 'text/plain'.
Steps to reproduce
- Install Drupal 10.1.0 or later
- Install the redirect module and enable it. The setting 'Enforce clean and canonical URLs.' will be enabled by default.
- At Config > Performance , 'Aggregate CSS files' is enabled by default. Set 'Browser and proxy cache maximum age' to 5 minutes.
- Enable the 'Language' core module.
- At Configuration > Region and language > Languages > Detection and selection , 'URL' is enabled by default. Configure 'URL' to use 'en' as language prefix for English.
- Clear cache and delete the generated aggregated CSS files from disk
- Visit a page, it will load correctly
- Visit the page again and the aggregated CSS will no longer be loaded. In browser console you will find errors like Refused to apply style from 'https://my-drupal10-site.ddev.site/en/sites/default/files/css/css_MXjpf7......' because its MIME type ('text/plain') is not a supported stylesheet MIME type, and strict MIME checking is enabled.
Proposed resolution
Add an exception in RouteNormalizerRequestSubscriber or in RedirectChecker::canRedirect for aggregated CSS paths.
Remaining tasks
Discuss how we want to fix this and fix it.
User interface changes
?
API changes
N/A
Data model changes
N/A
| Comment | File | Size | Author |
|---|---|---|---|
| #61 | 3373123-60_redirect_dont-normalize-assets.patch | 6.79 KB | bonrita |
| #39 | 3373123_redirect_dont-normalize-assets.patch | 642 bytes | jhuhta |
| #17 | 3373123_redirect-5.patch | 3.63 KB | bladedu |
| CSS_aggregation_fails.png | 144.31 KB | stefdewa |
Issue fork redirect-3373123
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:
- 3373123-setting-enforce-clean
changes, plain diff MR !93
- 8.x-1.x
changes, plain diff MR !67
Comments
Comment #2
bladeduI confirm the issue on Drupal 10.1 and redirect module.
My scenario is simpler: I have css/js aggregation active and a plain drupal installation.
all files under /sites/default/files/css or js gets redirected to itself appending the query parameters to the existing path until NGINX replies with 414 Request-URI Too Large
Comment #3
dioni commentedI can confirm it too
Comment #4
dioni commentedI have create a patch because it was blocking my current project.
Comment #5
dioni commentedPlease, use the patch -2, I forgot to include the preg_quote function.
Comment #6
dioni commentedComment #8
dioni commentedComment #9
dioni commentedComment #10
dioni commentedComment #12
dioni commentedComment #13
dioni commentedComment #15
dioni commentedComment #16
dioni commentedComment #17
bladeduI refined a bit your patch (using injected service, but also using a different method for fetching the base path
getDirectoryPath()method is defined as abstract method from LocalStream from which all other streams are extended.basePath, instead, is defined by concrete classes and their implementation of getDirectoryPath calls basePath.Eventually it's the same, but bit more robust (and usable with s3fs module)
Comment #19
bladeduFixed tests and add one more test to verify that redirect checker returns false when asset path is provided.
Comment #20
bladeduComment #21
bladeduThis last patch should work. Going to switch it back to need review.
Thanks!
Comment #22
dioni commentedCool, thanks!!!
Comment #23
stefdewa commentedThe issue is fixed in Drupal 10.1.2 . Issue #3371358: When AssetControllerBase delivers existing file should add content-type makes sure the correct Content-Type is specified (Fix in code: https://git.drupalcode.org/project/drupal/-/commit/6c8799d135b23bfadbf43... ). Lowering priority to 'Normal'.
Nonetheless, we can go forward with the change here because that reduces website calls.
Comment #24
stefdewa commentedComment #25
pub497 commentedhmm this seems to still be an issue for me on drupal 10.1.3...although it might be for a different reason as we are not using multilingual support, this is what a resulting css file path looks like:
Works fine on drupal 9, also it seems to work fine with the addition of advagg module
Comment #26
andreasderijckeI'm having this issue also on 10.1.3 when running on our hosting, but not when running in DDEV.
The patch does fix the issue on the hosting.
So far not been able to identify the reason, gut feeling points toward nginx config.
Comment #27
andreasderijcke@pub497 Turns out or issue was indeed due to outdated nginx config, as explained in #3368769-2: 10.1.x breaks Nginx + PHP-FPM with too many redirects even when nginx config is changed
Comment #28
pub497 commentedhey @andreasderijcke thanks for that! that was exactly the issue I was having
Comment #31
juanjolI confirm that this Issue is currently still occurring in core version 10.1.5 with Redirect version 8.x-1.9.
I have created an MR to make it easier for maintainers to merge this issue. I have added some of the previous patches to the issue so that the contributors don't lose the credits, I hope I did it right. In this MR I have also corrected a problem from patch #20 with CSS/JS added on sites whose basepath is not /.
What I have done is that when checking the requests not only is done on $assetsStreamWrapper->getDirectoryPath() but also takes into account the basePath of the $request.
I had thought that perhaps it would be more efficient to use a str_starts_with instead of preg_match, but I have seen that it would not be controlled if these requests are expressly CSS/JS and I believe that on this occasion it is interesting to do it this way, isn't it?
Finally, it seems to me that this issue is important because CSS and JS aggregation is failing in lot of sites, so I have raised the priority to Major. I hope that this last one does not generate discomfort.
Comment #32
juanjol-
Comment #33
juanjolI have been rethinking and update a bit the MR so that instead of checking the uri of the request, which contains the base path included and extra parameters, what we check is the path info of the request. This is more similar to what we get from the getDirectoryPath of the asset stream.
Comment #34
juanjolAdded patch with changes from MR to facilitate the installation of the patch with composer until the issue is fixed.
Comment #35
mullzk commentedHi
I tested #34 on my installation and it worked.
Drupal 10.1.5, Redirect 8.x-1.9, multilingual
=> Having redirect AND css/js-aggregation enabled leads to css/js-files no longer being loaded.
=> Using the issue-fork from juanjol fixes this (as does disabling css/js-aggregetion or disabling redirect).
Thanks a lot for your work. Hope this gets merged soon.
Being still a Newbie in regard to Drupal-Contrib - if anyone tells me how I can be of assistance for further review, I'll gladly help...
Comment #36
juanjolHi mullzk! Welcome :)
If you have tested the latest patch or the MR changes and they are working for you, please consider changing the issue state from Needs review to 'Reviewed and tested by the community'.
Thanks!
Comment #37
bladeduComment #38
mullzk commentedTested on 10.1.5 as described in #35, MR resolves the issue
Tested on Drupal 9.5.11 as well, Redirect works as expected, CSS-& JS-Assets are generated as usual.
Comment #39
jhuhta commentedI'm not 100% sure if I had the same issue. However, the new 10.1 aggregation and Redirect together causes an extra language prefix redirect on a multilingual site. But there's a simpler way to prevent that from happening: just disable the normalization on a given route. Here's a patch that works for me on that.
Comment #40
catchPatch in #39 looks good to me.
Comment #41
dpacassiUsing #39 on two big Drupal sites, has been working so far :)
Comment #42
mschudders commentedI can also confirm #39 works on a big Drupal multilingual Drupal 10.1.5 with Apache (no NGINX)
Comment #44
juanjolAfter some thought and testing, as far as I can see the solution in #39 is much cleaner than the one we had previously so far, so with your permission I have removed the MR and leave the latest patch as the proposed solution.
Comment #45
flocondetoileAggregated JS/CSS was completly broken after upgrading from 9.5.11 to 10.1.6. Using Apache and PHP-FPM.
Patch #39 solves the issue.
RTBC +1
Comment #46
bladeduYes I confirm patch #39 solves the issue.
Comment #47
volkerk commentedPatch #39 works fine on https://www.drupal.org/project/la_eu
So another +1
Comment #48
volkerk commentedComment #49
raffaeljI can also confirm that patch #39 solves the issue.
In my case I experienced redirects for aggregated CSS an JS files from `/sites/default/files/css/css_{hash}` to `/de/sites/default/files/css/css_{hash}` with a 301 status code after rebuilding the cache on a multilingual site - only on front page, that is redirected from `/` to `/{lang}`.
Because I don't want to wait (and 301s are browser cached), I added the code from #39 to a custom module and use it in production now. Thanks @jhuhta.
Comment #50
thomaswalther commented#39 solves the issue with endless redirection.
I am missing this patch (with checking the new two collections "system.js_asset" and "system.css_asset") in the newest release 1.9.
Comment #51
andrerb commentedI have tried the patch from #39, but it does not solve our problem with the css files not being found.
* Server: Apache
* Drupal 10.2.2
* redirect 1.9 (patched)
* multilingual
* multidomain
The error occurs during an AJAX request if both options ("Enforce clean and canonical URLs" and "Aggregate CSS files") are enabled.
The Error-Message: "An error occurred during the execution of the Ajax response: The following files could not be loaded: /sites/default/files/css/css_CmPeBLE1CkXCsJ5fW5NMix3CFDsvxnLYkuIr83jPmVU.css?delta=1&language=en-us"
If one or the other option is deactivated, the AJAX request works without problems.
We are still trying to find the reason for this
Comment #52
bbu23While this behaviour can be confirmed (a multilingual D10 with Enforce clean URLs enabled), in my case I had multiple servers with the same project code & db, but some servers were not affected, they were working fine.
While temporarily disabling the "Enforce clean URLs" confirmed the potential fix of the patch (I was not applying it yet), the question why other server were not affected by this still remained. After deeper investigation, there were permissions + ownership issues with the files folder (recursively). That fixed the problem and no patch was required anymore. Re-enabled the "Enforce clean URLs" and all was fine.
Also temporary dir was fixed in this (there was another issue there)
EDIT: False alarm, we did have to go for the patch, but then the mystery of why the others servers work without will be left unsolved. Confirming that the patch works.
Comment #53
sergeimalyshev commentedPatch #39 causes this issue https://www.drupal.org/project/drupal/issues/3377310.
Comment #54
berdir#39 is the correct fix, please provide this as a merge request.
Comment #58
berdirMerged.
Comment #60
rolki commented+1 RTBC, see https://github.com/open-y-subprojects/openy_custom/pull/73
Comment #61
bonrita commentedUpdating the patch https://www.drupal.org/files/issues/2023-10-20/3373123_redirect_fix_aggr... It is no longer commaptible with the current version 1.10
Comment #62
mibstar commentedDitto to sergeimalyshev on #53.
I can't enable JS aggregation without getting errors using redirect 1.10.0 on a new D10 site. Any ideas why?
Full details on https://www.drupal.org/project/drupal/issues/3377310#comment-15852105