Add cache purge API with version-based invalidation
- POST /api/purge/:customer - purge cache for specific customer - POST /api/purge-all - purge all cache globally - Cache keys now include version from KV, incrementing version invalidates all cached entries - No need for Cloudflare Dashboard access to purge
This commit is contained in:
@@ -434,18 +434,28 @@ async function handleAPI(request, env, url) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST /api/purge/:customer - 고객 사이트 캐시 퍼지
|
// POST /api/purge/:customer - 고객 사이트 캐시 퍼지 (캐시 버전 증가)
|
||||||
const purgeMatch = path.match(/^\/api\/purge\/([^\/]+)$/);
|
const purgeMatch = path.match(/^\/api\/purge\/([^\/]+)$/);
|
||||||
if (purgeMatch && method === 'POST') {
|
if (purgeMatch && method === 'POST') {
|
||||||
const customer = purgeMatch[1];
|
const customer = purgeMatch[1];
|
||||||
// Workers Cache API에서 해당 고객 캐시 삭제는 개별 키 기반이라
|
const newVersion = Date.now().toString();
|
||||||
// 실질적으로는 캐시 바이패스 플래그를 설정
|
await env.USAGE.put(`cache-version:${customer}`, newVersion);
|
||||||
// Cloudflare Edge 캐시는 zone-level purge 필요
|
|
||||||
// 여기서는 Worker 내부 캐시(caches.default)를 무효화
|
|
||||||
return jsonResponse({
|
return jsonResponse({
|
||||||
success: true,
|
success: true,
|
||||||
message: `Cache bypass enabled. Use ?nocache query param to bypass cache for ${customer}`,
|
customer,
|
||||||
hint: 'For full purge, use Cloudflare Dashboard or API zone purge',
|
cache_version: newVersion,
|
||||||
|
message: `Cache purged for ${customer}. All cached pages will be refreshed on next request.`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /api/purge-all - 전체 캐시 퍼지
|
||||||
|
if (path === '/api/purge-all' && method === 'POST') {
|
||||||
|
const newVersion = Date.now().toString();
|
||||||
|
await env.USAGE.put('cache-version:__global__', newVersion);
|
||||||
|
return jsonResponse({
|
||||||
|
success: true,
|
||||||
|
cache_version: newVersion,
|
||||||
|
message: 'Global cache purged. All cached pages will be refreshed on next request.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,7 +465,8 @@ async function handleAPI(request, env, url) {
|
|||||||
'PUT /api/tier/:customer {"tier": "free|basic|pro"}',
|
'PUT /api/tier/:customer {"tier": "free|basic|pro"}',
|
||||||
'GET /api/stats',
|
'GET /api/stats',
|
||||||
'DELETE /api/customer/:customer',
|
'DELETE /api/customer/:customer',
|
||||||
'POST /api/purge/:customer',
|
'POST /api/purge/:customer - purge cache for a customer',
|
||||||
|
'POST /api/purge-all - purge all cache',
|
||||||
]}, 404);
|
]}, 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,8 +530,15 @@ export default {
|
|||||||
const bypassCache = url.searchParams.has('nocache') ||
|
const bypassCache = url.searchParams.has('nocache') ||
|
||||||
request.headers.get('Cache-Control') === 'no-cache';
|
request.headers.get('Cache-Control') === 'no-cache';
|
||||||
|
|
||||||
// 캐시 키 생성
|
// 캐시 버전 조회 (퍼지 시 버전이 변경되어 캐시 무효화)
|
||||||
const cacheKey = new Request(`https://cache.internal/${customer}${filePath}`);
|
const [customerVersion, globalVersion] = await Promise.all([
|
||||||
|
env.USAGE.get(`cache-version:${customer}`),
|
||||||
|
env.USAGE.get('cache-version:__global__'),
|
||||||
|
]);
|
||||||
|
const cacheVersion = customerVersion || globalVersion || '0';
|
||||||
|
|
||||||
|
// 캐시 키 생성 (버전 포함)
|
||||||
|
const cacheKey = new Request(`https://cache.internal/${customer}/v${cacheVersion}${filePath}`);
|
||||||
const cache = caches.default;
|
const cache = caches.default;
|
||||||
|
|
||||||
// 1. 캐시에서 먼저 확인 (바이패스가 아닌 경우)
|
// 1. 캐시에서 먼저 확인 (바이패스가 아닌 경우)
|
||||||
|
|||||||
Reference in New Issue
Block a user