Problem/Motivation

In certain multilingual scenario's, combining this module with the redirect module where the option "Enforce clean and canonical URLs." is enabled, leads to incorrect use of cached redirect responses.

Check the steps to reproduce for which setup.

This module make sure that certain query parameters are ignored when fetching cache results from the page cache module. F.e. when you ignore 'fbclid' the next URLs are threated the same by the page cache module:

  1. https://mysite.local
  2. https://mysite.local?fbclid=abc
  3. https://mysite.local?fbclid=whatever

The problem happens when redirect responses are cached. Redirect responses are created by the redirect module when your website uses language prefixes and you visit the website without a language prefix.

When you visit https://mysite.local?fbclid=abc a redirect response is created to https://mysite.local/nl?fbclid=abc (/ -> /nl) and this is cached for cid "https://mysite.local/:". When you visit the site again but his time you visit https://mysite.local, you will be redirected to https://mysite.local/nl?fbclid=abc because you will get the cached redirect response.

IMHO this module works as designed. The "problem", or at least, the source, lies in the redirect module as it creates the redirect response.

Another possibility is preventing a redirect from / to /nl. If the path generated for the frontpage is /, there won't be a redirect response as the redirect module checks if the original and generated url are not the same. So if #1255092: Return "/" instead of the internal path when asked for the URL of the frontpage ever gets fixed, redirect won't create a redirect response and this problem will be fixed as well.

Either way, disabling the option "Enforce clean and canonical URLs." (from the redirect module) stops the redirect module from creating redirects. That in turn "fixes" this issue.

Steps to reproduce

  1. Install Drupal 9 in English
  2. Enable Dutch with language prefix 'nl'
  3. At "URL language detection configuration" use path prefix 'en' for English and 'nl' for Dutch (/admin/config/regional/language/detection/url)
  4. At "Selected language configuration" select Dutch (/admin/config/regional/language/detection/selected)
  5. Install modules page_cache_query_ignore (2.1.0) and redirect (8.x-1.7)
  6. Make sure the option "Enforce clean and canonical URLs." is enabled in redirect config (/admin/config/search/redirect/settings)
  7. Create a node and set it as the homepage in "Basic site settings" (/admin/config/system/site-information)
  8. Configure page_cache_query_ignore to ignore fbclid (/admin/config/development/performance/page_cache_query_ignore)
  9. As an anonymous user, visit your homepage with the fbclid query parameter F.e. https://mysite.local?fbclid=abc . You will be redirected to https://mysite.local/nl?fbclid=abc .
  10. As an anonymous user, visit your homepage with https://mysite.local

Expected result

The user is redirected to https://mysite.local/nl

Actual result

The user is redirected to https://mysite.local/nl?fbclid=abc

Proposed resolution

Put a disclaimer in the readme of this module: when using the redirect module in multilingual setup, disable "Enforce clean and canonical URLs."

Remaining tasks

Discuss.

User interface changes

N/A

API changes

N/A

Data model changes

N/A

Original description

Hi nterbogt,

Nice work with going through all the issues and giving the module some attention!

So I've had an issue with the combination of the redirect module (https://www.drupal.org/project/redirect) and this one.
I did manage to solve it for myself recently but I'm not really sure about the "beauty" of the solution.

The situation:

Besides allowing users to manually create redirects it also automatically creates and caches redirects from for example /node/1 to its alias /test or from / to /en if you have a multilanguage setup etc. These redirects are cached in the cache_page table, as TrustedRedirectResponses.

The response looks like this:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="refresh" content="0;url='http://test.com/en/search'" />

        <title>Redirecting to http://test.com/en/search</title>
    </head>
    <body>
        Redirecting to <a href="http://test.com/en/search">http://test.com/en/search</a>.
    </body>
</html>

So far so good.

Now let's suppose I have the multilanguage setup with English as the default language so everybody going to / get redirect to /en, and this redirect is of course cached. Now some bots are visiting my website with queries like http://test.com?something=a and http://test.com?something=b etc. These requests all create separate rows in the cache_page table filling it up with thousands of records. So to prevent that I choose to ignore the query "something".

However, now we get in the situation where the cid in the cache_page table becomes http://test.com instead of http://test.com?something=a, but the redirect module will still redirect it to http://test.com/en?something=a and cache that redirect. So now all the visitors who go to http://test.com get redirected to http://test.com/en?something=a, due to the fact that the redirect target query is not being cleaned by this module yet.

I hope you the idea. If not, let me know.

So now my current solution, I solved this by putting the cleaning function in a separate service (you've already noticed it here: https://www.drupal.org/project/page_cache_query_ignore/issues/3127834#co...) . Patch the redirect module to allow for the target url query string to be altered and add that alter hook in the module file of this module. This way, both the cid and the target url will always be equal.

I'll provide the 3 patches below that show this current solution, but I think there should be a prettier solution for this. Do you any ideas on this?

Comments

Nicasso created an issue. See original summary.

nicasso’s picture

Issue summary: View changes
nterbogt’s picture

Status: Active » Postponed (maintainer needs more info)

Hi Nicasso,

I understand the problem, but to be honest I can't reproduce it. I have essentially identical setup on a few of my sites.
I can't actually see the redirect service caching in the page_cache. I only get results for the final URL in the cache.

I use some language detection plugins to do my / to /en and redirect for the paths following that.

That said, I'm happy to support the move of the cleaner to a service if that will help you... but we can't really include anything in this module directly because your solution has side effects for other sites.

Say I have a page that has user customised content on it... and I have that URL come in from an email with a token. https://my.server/my-cool-alias?custom_code=abc.

I want that to redirect to https://my.server/en/resources/my-cool-page?custom_code=abc for users from english speaking countries and https://my.server/es/resources/my-cool-page?custom_code=abc for spanish ones. But I also want to exclude custom_code from the page_cache arguments because it's content that is brought in client-side via JS. So the page is 'cacheable' without the argument.

There are a few other examples I can think of where this is the same.

Depending on whether you regularly require redirects with arguments to flow through... there is a checkbox in the redirect settings that will also allow you to exclude all arguments when doing the redirect... so anything that gets passed in will be ignored.

An alternative option would be to extend get() and set() in our page cache override. get() to check for the full URL, then the clean URL in the cache. And set() to check the response object type, and use full URL for redirect and clean URL for everything else... This won't solve your large database problem though.

Again, I can't reproduce the error though. I'm using the latest versions of everything (core/redirect/page_cache_query_ignore). If you have a series of steps to create the issue, please send them through and I'll take another look.

stefdewa’s picture

Issue summary: View changes
stefdewa’s picture

peterwcm’s picture

Hi Nathan,

We recently encountered the same issue on our websites.

When people visit the home page URL
- https://website.com
they got redirected to
- https://website.com/en-us?fbclid=querystring
instead of just https://website.com/en-us

Although I haven't verified the theory mentioned in the issue description, it seems to make sense. Due to the fact that we are ignoring gclid param, the root path / would be sharing the same cache ID as /?fbclid=querystring and the redirect module probably uses the same cache ID to cache the redirect.

I can reproduce this by visiting https://website.com?fbclid=querystring straight after a clear cache command
After that, any subsequent requests to https://website.com would be redirected to https://website.com/en-us?fbclid=querystring

However, if the first ever request to the home page is just https://website.com (without any query params), there won't be any issues afterwards because the redirect cache is not caching the query string in its destination path.

validoll’s picture

Status: Postponed (maintainer needs more info) » Fixed

Same root cause as #3563815 — the module was caching redirect responses under the query-stripped cache ID, so subsequent clean URL requests were being served the stripped-CID entry that happened to be a redirect generated from a very different original URL.

Resolved in 2.5.0 by the "Ignore redirects" option (#3563815). When it is enabled, redirect responses use the core page-cache CID (full URL) while 200 responses continue to use the stripped CID.

Please upgrade to 2.5.0, enable "Ignore redirects", and confirm the multilingual + "Enforce clean and canonical URLs" scenario works as expected. Marking as fixed on that basis; feel free to reopen if it doesn't.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

anybody’s picture

@validoll maybe it makes sense to add a suggestion to the Ignore redirects setting like "You typically want to enable this if using the Redirect module" or something like that. I think the redirect module is EXTREMELY common!

Currently I think the description:

When enabled, this module will not process redirects. If a cache entry with stripped query parameters results in a redirect, regular response caching will happen.

is not very clear without examples. At least I'd be unsure if I should enable it or not.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.