Skip to content

Commit

Permalink
Add some options to limit the number of requests
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurperton committed Dec 16, 2024
1 parent abaa0c2 commit 1b56a16
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 1 deletion.
54 changes: 54 additions & 0 deletions src/Console/Commands/StaticWarm.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ class StaticWarm extends Command
{--p|password= : HTTP authentication password}
{--insecure : Skip SSL verification}
{--uncached : Only warm uncached URLs}
{--max-depth= : Maximum depth of URLs to warm}
{--include= : Only warm specific URLs}
{--exclude= : Exclude specific URLs}
';

protected $description = 'Warms the static cache by visiting all URLs';
Expand Down Expand Up @@ -179,6 +182,9 @@ private function uris(): Collection
->merge($this->customRouteUris())
->merge($this->additionalUris())
->unique()
->filter(fn ($uri) => $this->shouldInclude($uri))
->reject(fn ($uri) => $this->shouldExclude($uri))
->reject(fn ($uri) => $this->exceedsMaxDepth($uri))
->reject(function ($uri) use ($cacher) {
if ($this->option('uncached') && $cacher->hasCachedPage(HttpRequest::create($uri))) {
return true;
Expand All @@ -192,6 +198,54 @@ private function uris(): Collection
->values();
}

private function shouldInclude($uri): bool
{
if (! $inclusions = $this->option('include')) {
return true;
}

$inclusions = explode(',', $inclusions);

return collect($inclusions)->contains(fn ($included) => $this->uriMatches($uri, $included));
}

private function shouldExclude($uri): bool
{
if (! $exclusions = $this->option('exclude')) {
return false;
}

$exclusions = explode(',', $exclusions);

return collect($exclusions)->contains(fn ($excluded) => $this->uriMatches($uri, $excluded));
}

private function uriMatches($uri, $pattern): bool
{
$uri = URL::makeRelative($uri);

if (Str::endsWith($pattern, '*')) {
$prefix = Str::removeRight($pattern, '*');

if (Str::startsWith($uri, $prefix) && ! (Str::endsWith($prefix, '/') && $uri === $prefix)) {
return true;
}
} elseif (Str::removeRight($uri, '/') === Str::removeRight($pattern, '/')) {
return true;
}

return false;
}

private function exceedsMaxDepth($uri): bool
{
if (! $max = $this->option('max-depth')) {
return false;
}

return count(explode('/', trim(URL::makeRelative($uri), '/'))) > $max;
}

private function shouldVerifySsl(): bool
{
if ($this->option('insecure')) {
Expand Down
85 changes: 84 additions & 1 deletion tests/Console/Commands/StaticWarmTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public function it_warms_the_static_cache()
}

#[Test]
public function it_only_visits_uncached_urls_when_the_eco_option_is_used()
public function it_only_visits_uncached_urls_when_the_uncached_option_is_used()
{
$mock = Mockery::mock(Cacher::class);
$mock->shouldReceive('hasCachedPage')->times(2)->andReturn(true, false);
Expand All @@ -58,6 +58,89 @@ public function it_only_visits_uncached_urls_when_the_eco_option_is_used()
->assertExitCode(0);
}

#[Test]
public function it_only_visits_included_urls()
{
config(['statamic.static_caching.strategy' => 'half']);

$this->createPage('blog');
$this->createPage('news');

Collection::make('blog')
->routes('/blog/{slug}')
->template('default')
->save();

Collection::make('news')
->routes('/news/{slug}')
->template('default')
->save();

EntryFactory::slug('post-1')->collection('blog')->id('blog-post-1')->create();
EntryFactory::slug('post-2')->collection('blog')->id('blog-post-2')->create();
EntryFactory::slug('article-1')->collection('news')->id('news-article-1')->create();
EntryFactory::slug('article-2')->collection('news')->id('news-article-2')->create();
EntryFactory::slug('article-3')->collection('news')->id('news-article-3')->create();

$this->artisan('statamic:static:warm', ['--include' => '/blog/post-1,/news/*'])
->expectsOutput('Visiting 4 URLs...')
->assertExitCode(0);
}

#[Test]
public function it_doesnt_visit_excluded_urls()
{
config(['statamic.static_caching.strategy' => 'half']);

$this->createPage('blog');
$this->createPage('news');

Collection::make('blog')
->routes('/blog/{slug}')
->template('default')
->save();

Collection::make('news')
->routes('/news/{slug}')
->template('default')
->save();

EntryFactory::slug('post-1')->collection('blog')->id('blog-post-1')->create();
EntryFactory::slug('post-2')->collection('blog')->id('blog-post-2')->create();
EntryFactory::slug('article-1')->collection('news')->id('news-article-1')->create();
EntryFactory::slug('article-2')->collection('news')->id('news-article-2')->create();
EntryFactory::slug('article-3')->collection('news')->id('news-article-3')->create();

$this->artisan('statamic:static:warm', ['--exclude' => '/about,/contact,/blog/*,/news/article-2'])
->expectsOutput('Visiting 4 URLs...')
->assertExitCode(0);
}

#[Test]
public function it_respects_max_depth()
{
config(['statamic.static_caching.strategy' => 'half']);

Collection::make('blog')
->routes('/awesome/blog/{slug}')
->template('default')
->save();

Collection::make('news')
->routes('/news/{slug}')
->template('default')
->save();

EntryFactory::slug('post-1')->collection('blog')->id('blog-post-1')->create();
EntryFactory::slug('post-2')->collection('blog')->id('blog-post-2')->create();
EntryFactory::slug('post-3')->collection('blog')->id('blog-post-3')->create();
EntryFactory::slug('article-1')->collection('news')->id('news-article-1')->create();

$this->artisan('statamic:static:warm', ['--max-depth' => 2])
->expectsOutput('Visiting 3 URLs...')
->assertExitCode(0);
}

#[Test]
public function it_doesnt_queue_the_requests_when_connection_is_set_to_sync()
{
Expand Down

0 comments on commit 1b56a16

Please sign in to comment.