Skip to content
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

URLs not excluded from static cache in a multi-site environment #10089

Closed
aerni opened this issue May 15, 2024 · 3 comments · Fixed by #10092
Closed

URLs not excluded from static cache in a multi-site environment #10089

aerni opened this issue May 15, 2024 · 3 comments · Fixed by #10092

Comments

@aerni
Copy link
Contributor

aerni commented May 15, 2024

Bug description

I've noticed that the static:warm command isn't excluding URLs of sites that use a domain that's different from APP_URL.

It's important to note that this issue doesn't actually affect the statically cached pages. It only affects the URLs that are considered for warming by the static:warm command.

Example

Consider the following setup:

config/statamic/sites.php

'sites' => [

    'gounity' => [
        'name' => 'goUnity',
        'locale' => 'de_DE',
        'url' => env('APP_URL_GOUNITY'),
    ],

    'gomagazin' => [
        'name' => 'goMagazin',
        'locale' => 'de_DE',
        'url' => env('APP_URL_GOMAGAZIN'),
    ],

],

config/statamic/static_caching.php

'exclude' => [
    'urls' => [
        '/story/*',
    ],
],

.env

APP_URL_GOUNITY=https://go-unity.test
APP_URL_GOMAGAZIN=https://gomagazin.test
APP_URL="${APP_URL_GOUNITY}"

When calling the static:warm command, it will correctly exclude the /story/* URLs in the default gounity site. However, it will still warm all the URLs in the gomagazin site.

What's happening

The URLs that should be excluded from the static:warm command are rejected here:

->reject(function ($uri) use ($cacher) {
return $cacher->isExcluded($uri);
})

The issue is that the baseUrl of the DefaultUrlExcluder class will resolve to the URL of the current request as per the getBaseUrl() method in the AbstractCacher class.

public function getBaseUrl()
{
// Check 'base_url' for backward compatibility.
if (! $baseUrl = $this->config('base_url')) {
// This could potentially just be Site::current()->absoluteUrl() but at the
// moment that method gets the URL based on the request. For now, we will
// manually get it from the config, as to not break any existing sites.
$baseUrl = Str::startsWith($url = Site::current()->url(), '/')
? Str::removeRight(config('app.url'), '/').$url
: $url;
}
return rtrim($baseUrl, '/');
}

The $baseUrl will always be Site::current(), which is resolved from request()->getUri(). When running the static:warm command, request()->getUri() will resolve to the APP_URL and not the URL of the site that the URL that is about to be cached belongs to.

cms/src/Sites/Sites.php

Lines 72 to 77 in 024aad4

private function findByCurrentUrl()
{
return $this->findByUrl(
$this->currentUrlCallback ? call_user_func($this->currentUrlCallback) : request()->getUri()
);
}

And this leads to the isExcluded() method returning false on any site that doesn't use the APP_URL as base.

public function isExcluded(string $url): bool
{
// Query strings should be ignored.
$url = explode('?', $url)[0];
$url = Str::removeLeft($url, $this->baseUrl);
foreach ($this->exclusions as $excluded) {
if (Str::endsWith($excluded, '*')) {
$prefix = Str::removeRight($excluded, '*');
if (Str::startsWith($url, $prefix) && ! (Str::endsWith($prefix, '/') && $url === $prefix)) {
return true;
}
} elseif (Str::removeRight($url, '/') === Str::removeRight($excluded, '/')) {
return true;
}
}
return false;

Workaround

You can work around this issue by explicitly excluding absolute URLs.

'exclude' => [
    'urls' => [
        '/story/*',
        env('APP_URL_GOMAGAZIN') . '/story/*',
    ],
],

How to reproduce

  1. Create a multi-site with different domains
  2. Exclude a URL from the static cache
  3. Run the static:warm command
  4. Notice the URL only being excluded in the default site

Logs

No response

Environment

Environment
Application Name: goUnity
Laravel Version: 10.48.10
PHP Version: 8.3.7
Composer Version: 2.7.6
Environment: local
Debug Mode: ENABLED
URL: go-unity.test
Maintenance Mode: OFF

Cache
Config: NOT CACHED
Events: NOT CACHED
Routes: NOT CACHED
Views: CACHED

Drivers
Broadcasting: log
Cache: statamic
Database: mysql
Logs: stack / single, flare
Mail: smtp
Queue: redis
Session: file

Locales
Installed
LaravelLang\Actions\Plugin: 1.8.2
LaravelLang\Attributes\Plugin: 2.10.5
LaravelLang\HttpStatuses\Plugin: 3.8.3
LaravelLang\Lang\Plugin: 13.12.0
Locales Version: 1.9.0
Protected
Publisher Version: 15.0.2

Statamic
Addons: 11
Antlers: runtime
Sites: 2 (goUnity, goMagazin)
Stache Watcher: Enabled
Static Caching: full
Version: 4.58.2 PRO

Statamic Addons
aerni/advanced-seo: 2.4.7
aerni/livewire-forms: 8.1.0
aerni/social-links: 3.2.0
jacksleight/statamic-bard-texstyle: 3.2.2
jonassiewertsen/statamic-jobs: 1.5.0
jonassiewertsen/statamic-livewire: 2.12.0
marcorieser/tailwind-merge-statamic: 1.1.0
rias/statamic-redirect: 3.7.1
spatie/statamic-responsive-images: 4.1.1
stillat/antlers-components: 2.2.0
stillat/relationships: 2.2.0

Installation

Fresh statamic/statamic site via CLI

Additional details

This issue sounds very similar to #7456.

@jasonvarga
Copy link
Member

Thanks for the detailed info. 👍

@aerni
Copy link
Contributor Author

aerni commented May 15, 2024

No worries. I just edited the issue, as it wasn't quite correct. It should be good now.

I also found this related issue #4732 and this PR #5065

@aerni
Copy link
Contributor Author

aerni commented May 15, 2024

I already worked out a fix. Will PR soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants