基于Lambda@Edge的服务端页面请求追踪方案咨询
最优方案推荐:精准过滤页面请求,替代扩展名排除法
针对你用Lambda@Edge+DynamoDB做流量追踪的场景,单纯排除静态资源扩展名的方法确实存在局限性(比如漏判无扩展名静态资源、误判带扩展名的页面如/index.html),这里提供几个更可靠的方案:
1. 利用CloudFront缓存行为前置过滤(最推荐)
Lambda@Edge是绑定在CloudFront缓存行为上的,你可以直接把页面请求和静态资源请求拆分到不同的缓存行为中,只给页面请求的缓存行为绑定Lambda函数:
- 配置缓存行为1(页面请求):路径模式设置为你的页面路由规则,比如
/、/*.html、/blog/*、/products/*等,在此行为下启用Viewer Request事件的Lambda@Edge。 - 配置缓存行为2(静态资源):路径模式设置为
/*.js、/*.css、/*.png、/*.svg等,不绑定Lambda函数。
这种方式从源头过滤掉不需要处理的请求,既减少了Lambda的执行次数(降低成本),也避免了函数内过滤的逻辑错误,是效率最高的方案。
2. Lambda函数内用正向匹配替代反向排除
如果无法拆分缓存行为,建议在Lambda中用正向匹配页面特征的正则表达式,替代排除扩展名的逻辑,覆盖更多页面场景:
// 匹配规则:空路径/、无扩展名的路由、带.html后缀的路径 const pageRequestPattern = /^\/$|^\/[^.]+(?:\/[^.]+)*$|^\/.*\.html$/; const requestUri = event.Records[0].cf.request.uri; // 仅当匹配页面请求时,执行DynamoDB写入逻辑 if (pageRequestPattern.test(requestUri)) { // 这里写入DynamoDB的代码,比如获取请求IP、用户代理、URI等 await saveToDynamoDB({ uri: requestUri, clientIp: event.Records[0].cf.request.clientIp, userAgent: event.Records[0].cf.request.headers['user-agent'][0].value, timestamp: new Date().toISOString() }); } // 无论是否记录,都返回原始请求 return event.Records[0].cf.request;
这种方法比排除扩展名更健壮,能覆盖SPA无后缀路由、带.html的静态页面等场景,也不会因为新增静态资源类型(如.webp、.webmanifest)而漏过滤。
3. 结合Content-Type判断(适合静态站点)
如果你的站点是S3托管的静态站点,可以在Origin Response事件中根据响应的Content-Type判断是否为页面请求(比如text/html),再记录请求:
const response = event.Records[0].cf.response; const contentTypeHeader = response.headers['content-type']; if (contentTypeHeader && contentTypeHeader[0].value.startsWith('text/html')) { // 记录请求到DynamoDB await saveToDynamoDB({ uri: event.Records[0].cf.request.uri, clientIp: event.Records[0].cf.request.clientIp, timestamp: new Date().toISOString() }); } return response;
注意:这个方法仅在缓存未命中时触发(因为缓存命中时不会走到Origin Response),如果需要记录缓存命中的页面请求,还是要结合前两种方法。
内容的提问来源于stack exchange,提问作者Omiron
相关产品推荐
相关产品推荐

