Tighten thumbnail/legacy photo handling and exclude download/photo traffic from session visitor tracking so those hot paths stay cheap.
134 lines
4.5 KiB
PHP
134 lines
4.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Models\Artwork;
|
|
|
|
function encodeLegacyPhotoId(int $value, string $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'): string
|
|
{
|
|
if ($value === 0) {
|
|
return '0';
|
|
}
|
|
|
|
$encoded = '';
|
|
|
|
while ($value > 0) {
|
|
$encoded = $chars[$value % 62] . $encoded;
|
|
$value = intdiv($value, 62);
|
|
}
|
|
|
|
return $encoded;
|
|
}
|
|
|
|
it('redirects legacy photo thumbnail urls to the mapped CDN thumbnail size', function (): void {
|
|
config([
|
|
'cdn.files_url' => 'https://cdn.example.test',
|
|
'uploads.object_storage.prefix' => 'artworks',
|
|
]);
|
|
|
|
$artwork = Artwork::factory()->create([
|
|
'hash' => 'aabbccddeeff0011',
|
|
'thumb_ext' => 'webp',
|
|
'file_ext' => 'jpg',
|
|
'file_path' => '',
|
|
]);
|
|
|
|
$response = $this->get('/photo/' . encodeLegacyPhotoId($artwork->id) . '_6.png');
|
|
|
|
$response
|
|
->assertStatus(301)
|
|
->assertRedirect('https://cdn.example.test/artworks/md/aa/bb/aabbccddeeff0011.webp');
|
|
});
|
|
|
|
it('redirects legacy full-size photo urls to the original CDN asset', function (): void {
|
|
config([
|
|
'cdn.files_url' => 'https://cdn.example.test',
|
|
'uploads.object_storage.prefix' => 'artworks',
|
|
]);
|
|
|
|
$artwork = Artwork::factory()->create([
|
|
'hash' => '1122334455667788',
|
|
'thumb_ext' => 'webp',
|
|
'file_ext' => 'png',
|
|
'file_path' => '',
|
|
]);
|
|
|
|
$response = $this->get('/photo/' . encodeLegacyPhotoId($artwork->id) . '_7.png');
|
|
|
|
$response
|
|
->assertStatus(301)
|
|
->assertRedirect('https://cdn.example.test/artworks/original/11/22/1122334455667788.png');
|
|
});
|
|
|
|
it('returns a cheap 404 for zero or invalid decoded photo ids', function (): void {
|
|
$this->get('/photo/0_6.png')->assertNotFound();
|
|
$this->head('/photo/0_6.png')->assertNotFound();
|
|
});
|
|
|
|
it('returns 404 for a nonexistent artwork', function (): void {
|
|
$this->get('/photo/' . encodeLegacyPhotoId(999999) . '_6.png')->assertNotFound();
|
|
});
|
|
|
|
it('returns 404 for private, unapproved, or unpublished artworks', function (): void {
|
|
$private = Artwork::factory()->create(['is_public' => false, 'hash' => 'aabbccddeeff0011', 'thumb_ext' => 'webp']);
|
|
$unapproved = Artwork::factory()->create(['is_approved' => false, 'hash' => 'bbccddeeff001122', 'thumb_ext' => 'webp']);
|
|
$unpublished = Artwork::factory()->create(['published_at' => null, 'hash' => 'ccddeeff00112233', 'thumb_ext' => 'webp']);
|
|
|
|
$this->get('/photo/' . encodeLegacyPhotoId($private->id) . '_6.png')->assertNotFound();
|
|
$this->get('/photo/' . encodeLegacyPhotoId($unapproved->id) . '_6.png')->assertNotFound();
|
|
$this->get('/photo/' . encodeLegacyPhotoId($unpublished->id) . '_6.png')->assertNotFound();
|
|
});
|
|
|
|
it('returns 404 for eligible legacy artwork with no usable media instead of redirecting to a dead CDN path', function (): void {
|
|
config(['cdn.files_url' => 'https://cdn.example.test']);
|
|
|
|
$artwork = Artwork::factory()->create([
|
|
'hash' => null,
|
|
'thumb_ext' => null,
|
|
'file_ext' => null,
|
|
'file_path' => 'legacy/uploads/old-photo.jpg',
|
|
'is_public' => true,
|
|
'is_approved' => true,
|
|
'published_at' => now()->subDay(),
|
|
]);
|
|
|
|
$this->get('/photo/' . encodeLegacyPhotoId($artwork->id) . '_6.png')->assertNotFound();
|
|
$this->get('/photo/' . encodeLegacyPhotoId($artwork->id) . '_7.png')->assertNotFound();
|
|
});
|
|
|
|
it('maps size 3 to the sm thumbnail variant', function (): void {
|
|
config([
|
|
'cdn.files_url' => 'https://cdn.example.test',
|
|
'uploads.object_storage.prefix' => 'artworks',
|
|
]);
|
|
|
|
$artwork = Artwork::factory()->create([
|
|
'hash' => 'aabbccddeeff0011',
|
|
'thumb_ext' => 'webp',
|
|
'file_ext' => 'jpg',
|
|
'file_path' => '',
|
|
]);
|
|
|
|
$this->get('/photo/' . encodeLegacyPhotoId($artwork->id) . '_3.png')
|
|
->assertStatus(301)
|
|
->assertRedirect('https://cdn.example.test/artworks/sm/aa/bb/aabbccddeeff0011.webp');
|
|
});
|
|
|
|
it('preserves HEAD redirects for valid modern hash-based photos', function (): void {
|
|
config([
|
|
'cdn.files_url' => 'https://cdn.example.test',
|
|
'uploads.object_storage.prefix' => 'artworks',
|
|
]);
|
|
|
|
$artwork = Artwork::factory()->create([
|
|
'hash' => 'aabbccddeeff0011',
|
|
'thumb_ext' => 'webp',
|
|
'file_ext' => 'jpg',
|
|
'file_path' => '',
|
|
]);
|
|
|
|
$this->head('/photo/' . encodeLegacyPhotoId($artwork->id) . '_6.png')
|
|
->assertStatus(301)
|
|
->assertRedirect('https://cdn.example.test/artworks/md/aa/bb/aabbccddeeff0011.webp');
|
|
});
|