diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 4ac8f0f13a..dfa070063c 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -544,7 +544,7 @@ App::init() $isImageTransformation = $route->getPath() === '/v1/storage/buckets/:bucketId/files/:fileId/preview'; $isDisabled = isset($plan['imageTransformations']) && $plan['imageTransformations'] === -1 && !Auth::isPrivilegedUser(Authorization::getRoles()); - $key = md5($request->getURI() . '*' . implode('*', $request->getParams()) . '*' . APP_CACHE_BUSTER); + $key = $request->cacheIdentifier(); $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $cache = new Cache( new Filesystem(APP_STORAGE_CACHE . DIRECTORY_SEPARATOR . 'app-' . $project->getId()) @@ -803,7 +803,7 @@ App::shutdown() $resourceType = $parseLabel($pattern, $responsePayload, $requestParams, $user); } - $key = md5($request->getURI() . '*' . implode('*', $request->getParams()) . '*' . APP_CACHE_BUSTER); + $key = $request->cacheIdentifier(); $signature = md5($data['payload']); $cacheLog = Authorization::skip(fn () => $dbForProject->getDocument('cache', $key)); $accessedAt = $cacheLog->getAttribute('accessedAt', ''); diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index c50dea2713..558f0cdf09 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -220,4 +220,17 @@ class Request extends UtopiaRequest return UtopiaRequest::getUserAgent($default); } + + /** + * Creates a unique stable cache identifier for this GET request. + * Stable-sorts query params, use `serialize` to ensure key&value are part of cache keys. + * + * @return string + */ + public function cacheIdentifier(): string + { + $params = $this->getParams(); + ksort($params); + return md5($this->getURI() . '*' . serialize($params) . '*' . APP_CACHE_BUSTER); + } }