From f8807120a2a161c762fc854b908d209789653fd4 Mon Sep 17 00:00:00 2001 From: roncodes <816371+roncodes@users.noreply.github.com> Date: Sat, 20 Dec 2025 22:42:11 -0500 Subject: [PATCH] Fix: Critical cache key collision bug - include all query parameters in cache key Previously, generateQueryCacheKey() only included a hardcoded whitelist of 11 parameters, causing cache key collisions when different filter values were used (e.g., type=customer vs type=contact generated the same cache key). This fix includes ALL query parameters in the cache key generation, excluding only internal/cache-busting parameters like '_', 'timestamp', 'nocache', and '_method'. Impact: - Fixes data integrity issue where different queries returned cached results from other queries - Ensures accurate cache HIT/MISS behavior for all filter combinations - Backward compatible - existing cache keys will naturally expire and regenerate Example: Before: /contacts?type=customer and /contacts?type=contact had SAME cache key After: /contacts?type=customer and /contacts?type=contact have DIFFERENT cache keys --- src/Support/ApiModelCache.php | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/Support/ApiModelCache.php b/src/Support/ApiModelCache.php index 4869542..2a45c38 100644 --- a/src/Support/ApiModelCache.php +++ b/src/Support/ApiModelCache.php @@ -58,21 +58,22 @@ public static function generateQueryCacheKey(Model $model, Request $request, arr $table = $model->getTable(); $companyUuid = static::getCompanyUuid($request); - // Get all relevant query parameters - $params = [ - 'limit' => $request->input('limit'), - 'offset' => $request->input('offset'), - 'page' => $request->input('page'), - 'sort' => $request->input('sort'), - 'order' => $request->input('order'), - 'query' => $request->input('query'), - 'search' => $request->input('search'), - 'filter' => $request->input('filter'), - 'with' => $request->input('with'), - 'expand' => $request->input('expand'), - 'columns' => $request->input('columns'), + // Get ALL query parameters from the request + // This ensures different filters (e.g., type=customer vs type=contact) generate different cache keys + $params = $request->query(); + + // Remove internal/non-cacheable parameters that shouldn't affect cache key + $excludedParams = [ + '_', // Cache-busting timestamp + 'timestamp', // Cache-busting timestamp + 'nocache', // Explicit cache bypass + '_method', // Laravel method override ]; + foreach ($excludedParams as $excluded) { + unset($params[$excluded]); + } + // Merge additional parameters $params = array_merge($params, $additionalParams);