跳转到内容
搜索文档

自定义缓存

以编程方式从缓存中存储、检索和删除资源。使用此模板优化性能并实施自定义缓存策略。

最后更新 查看 MarkdownAgent 设置

以编程方式从缓存中存储、检索和删除资源。使用此模板优化性能并实施自定义缓存策略。

// 定义可配置的缓存时长,以秒为单位(默认值:30 天)
const CACHE_DURATION_SECONDS = 30 * 24 * 60 * 60;

// 定义要在缓存键中包含请求的哪些部分
const USE_PATH = true; // 在缓存键中包含路径
const USE_QUERY_STRING = true; // 在缓存键中包含查询字符串
const INCLUDE_HEADERS = ["User-Agent"]; // 要包含在缓存键中的标头

export default {
	async fetch(request, env, ctx) {
		// 根据用户偏好生成自定义缓存键
		const cacheKey = createCacheKey(request);
		console.log(`Retrieving cache for: ${cacheKey.url}.`);

		// 访问默认的 Cache API
		const cache = caches.default;

		// 尝试检索缓存的响应
		let response = await cache.match(cacheKey);

		if (!response) {
			// 缓存未命中:从源站获取资源
			console.log(`Cache miss for: ${cacheKey.url}. Fetching from origin...`);
			response = await fetch(request);

			// 包装源站响应以便缓存
			response = new Response(response.body, response);

			// 设置 Cache-Control 标头以定义 TTL
			response.headers.set(
				"Cache-Control",
				`s-maxage=${CACHE_DURATION_SECONDS}`,
			);
			response.headers.set("x-snippets-cache", "stored");

			// 将响应存储在缓存中
			await cache.put(cacheKey, response.clone());
		} else {
			// 缓存命中:返回缓存的响应
			console.log(`Cache hit for: ${cacheKey.url}.`);
			response = new Response(response.body, response);
			response.headers.set("x-snippets-cache", "hit");

			// 可选操作:根据年龄检查缓存是否已过期
			const ageHeader = response.headers.get("Age");
			if (ageHeader && parseInt(ageHeader, 10) > CACHE_DURATION_SECONDS) {
				console.log(
					`Cache expired for: ${cacheKey.url}. Deleting cached response...`,
				);
				await cache.delete(cacheKey);
				response.headers.set("x-snippets-cache", "deleted");
			}
		}

		// 将响应返回给客户端
		return response;
	},
};

/**
 * 根据请求属性创建自定义缓存键的函数
 * @param {Request} request - 传入的请求对象
 * @returns {Request} - 基于 URL 的有效缓存键
 */
function createCacheKey(request) {
	const url = new URL(request.url); // 使用请求的基础 URL
	const cacheKey = new URL(url.origin); // 以源站(方案 + 主机名)开头

	// 可选操作:包含路径
	if (USE_PATH) {
		cacheKey.pathname = url.pathname;
	}

	// 可选操作:包含查询字符串
	if (USE_QUERY_STRING) {
		cacheKey.search = url.search;
	}

	// 可选操作:包含特定标头
	if (INCLUDE_HEADERS.length > 0) {
		const headerParts = INCLUDE_HEADERS.map(
			(header) => `${header}=${request.headers.get(header) || ""}`,
		).join("&");
		cacheKey.searchParams.append("headers", headerParts);
	}

	// 返回构建后的 URL 作为缓存键
	return new Request(cacheKey.toString(), {
		method: "GET",
	});
}

这篇文档对您有帮助吗?