avatar caching improvement

This commit is contained in:
Yuri Kuznetsov
2025-04-04 12:27:07 +03:00
parent fe70eba7d6
commit 927fd7a589
2 changed files with 53 additions and 8 deletions
+37 -3
View File
@@ -138,7 +138,17 @@ class Avatar extends Image
}
if ($user->getAvatarId()) {
$this->show($response, $user->getAvatarId(), $size, true);
if ($this->processEtagMatch($request, $response, $user->getAvatarId())) {
return;
}
$this->show(
response: $response,
id: $user->getAvatarId(),
size: $size,
disableAccessCheck: true,
etag: $user->getAvatarId(),
);
return;
}
@@ -159,6 +169,12 @@ class Avatar extends Image
$name = $this->getName($user, $userId);
$etag = md5($color . $name);
if ($this->processEtagMatch($request, $response, $etag)) {
return;
}
$avatar = (new InitialAvatar())->name($name);
if ($user->getName() && !self::isAllowedLanguage($avatar)) {
@@ -176,8 +192,9 @@ class Avatar extends Image
->generate();
$response
->setHeader('Cache-Control', 'max-age=360000, must-revalidate')
->setHeader('Content-Type', 'image/png');
->setHeader('Cache-Control', 'max-age=600, stale-while-revalidate=864000')
->setHeader('Content-Type', 'image/png')
->setHeader('Etag', $etag);
$response->writeBody($image->stream('png', 100));
}
@@ -299,4 +316,21 @@ class Avatar extends Image
return $name;
}
private function processEtagMatch(Request $request, Response $response, string $etag): bool
{
$matchEtag = $request->getHeader('If-None-Match');
if (!$matchEtag) {
return false;
}
if ($matchEtag === $etag) {
$response->setStatus(304);
return true;
}
return false;
}
}
+16 -5
View File
@@ -85,10 +85,15 @@ class Image implements EntryPoint
* @throws NotFound
* @throws ForbiddenSilent
*/
protected function show(Response $response, string $id, ?string $size, bool $disableAccessCheck = false): void
{
/** @var ?Attachment $attachment */
$attachment = $this->entityManager->getEntityById(Attachment::ENTITY_TYPE, $id);
protected function show(
Response $response,
string $id,
?string $size,
bool $disableAccessCheck = false,
?string $etag = null,
): void {
$attachment = $this->entityManager->getRDBRepositoryByClass(Attachment::class)->getById($id);
if (!$attachment) {
throw new NotFoundSilent("Attachment not found.");
@@ -147,9 +152,15 @@ class Image implements EntryPoint
$response
->setHeader('Content-Disposition', 'inline;filename="' . $fileName . '"')
->setHeader('Cache-Control', 'private, max-age=864000, immutable')
->setHeader('Content-Length', (string) $fileSize)
->setHeader('Content-Security-Policy', "default-src 'self'");
if ($etag) {
$response->setHeader('Cache-Control', 'max-age=600, stale-while-revalidate=864000');
$response->setHeader('Etag', $etag);
} else {
$response->setHeader('Cache-Control', 'private, max-age=864000, immutable');
}
}
/**