CloudFront配置问题:启用Clean URL时HTML文件仍被缓存的解决问询
CloudFront Clean URL配置下HTML文件被缓存的原因及修复方法
问题原因
你的猜测完全正确:CloudFront是在执行viewer-request阶段的函数之前匹配缓存行为的。具体逻辑如下:
- 用户发起的初始请求(比如
/about或/)会先匹配默认缓存行为(*),应用CachingOptimized缓存策略; - 之后CloudFront才会执行你的Clean URL函数,把请求URI修改为
/about/index.html或/index.html; - 最终源站返回的HTML文件会按照之前匹配的默认行为规则被缓存,完全不会触发你定义的
*.html缓存行为。
修复方案
下面提供两种可行的修复思路,你可以根据场景选择:
方案一:基于路径模式反向配置缓存行为
调整缓存行为的优先级和匹配规则,先针对Clean URL路径和HTML文件禁用缓存,再默认缓存静态资源:
修改后的CloudFormation配置:
CacheBehaviors: # 1. 匹配所有以斜杠结尾的路径(如 /about/),禁用缓存 - PathPattern: '*/' TargetOriginId: s3origin CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad # CachingDisabled ViewerProtocolPolicy: redirect-to-https AllowedMethods: [GET, HEAD, OPTIONS] CachedMethods: [GET, HEAD, OPTIONS] Compress: true FunctionAssociations: - EventType: viewer-request FunctionARN: !GetAtt RedirectFunction.Outputs.FunctionArn # 2. 匹配直接访问的HTML文件,禁用缓存 - PathPattern: '*.html' TargetOriginId: s3origin CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad # CachingDisabled ViewerProtocolPolicy: redirect-to-https AllowedMethods: [GET, HEAD, OPTIONS] CachedMethods: [GET, HEAD, OPTIONS] Compress: true FunctionAssociations: - EventType: viewer-request FunctionARN: !GetAtt RedirectFunction.Outputs.FunctionArn DefaultCacheBehavior: # 3. 默认行为:缓存所有带后缀的静态资源(如css/js/png等) TargetOriginId: s3origin CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6 # CachingOptimized ViewerProtocolPolicy: redirect-to-https AllowedMethods: [GET, HEAD, OPTIONS] CachedMethods: [GET, HEAD, OPTIONS] Compress: true FunctionAssociations: - EventType: viewer-request FunctionARN: !GetAtt RedirectFunction.Outputs.FunctionArn
工作原理:
- 用户访问
/about时,函数会重定向到/about/,这个重定向后的请求会匹配第一个缓存行为,禁用缓存; - 函数接着把
/about/的URI修改为/about/index.html,源站返回的HTML文件会按照禁用缓存的规则处理; - 直接访问
/about.html会匹配第二个缓存行为,同样禁用缓存; - 所有带后缀的静态资源(如
/style.css)会匹配默认行为,应用缓存优化策略。
方案二:通过自定义请求头标记HTML请求
修改Clean URL函数,给最终指向HTML文件的请求添加自定义头,再基于这个头匹配禁用缓存的行为:
步骤1:修改CloudFront Function代码
var indexDocument = 'index.html'; function redirect(uri) { return { statusCode: 301, statusDescription: 'Moved Permanently', headers: { location: { value: uri } }, }; } function handler(event) { var request = event.request; var uri = request.uri || '/'; var isHTML = false; if (uri.endsWith('/')) { request.uri = uri + indexDocument; isHTML = true; } else if (uri.endsWith('/' + indexDocument)) { return redirect(uri.slice(0, -indexDocument.length)); } else if (!request.uri.includes('.')) { return redirect(uri + '/'); } else if (uri.endsWith('.html')) { isHTML = true; } // 给HTML请求添加自定义标记头 if (isHTML) { request.headers['x-is-html'] = { value: 'true' }; } return request; }
步骤2:修改CloudFormation缓存行为配置
DefaultCacheBehavior: TargetOriginId: s3origin CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6 # CachingOptimized ViewerProtocolPolicy: redirect-to-https AllowedMethods: [GET, HEAD, OPTIONS] CachedMethods: [GET, HEAD, OPTIONS] Compress: true FunctionAssociations: - EventType: viewer-request FunctionARN: !GetAtt RedirectFunction.Outputs.FunctionArn CacheBehaviors: # 匹配带有X-Is-HTML: true头的请求,禁用缓存 - PathPattern: '*' TargetOriginId: s3origin CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad # CachingDisabled ViewerProtocolPolicy: redirect-to-https AllowedMethods: [GET, HEAD, OPTIONS] CachedMethods: [GET, HEAD, OPTIONS] Compress: true FunctionAssociations: - EventType: viewer-request FunctionARN: !GetAtt RedirectFunction.Outputs.FunctionArn # 配置请求头匹配条件 HeadersConfig: HeaderBehavior: whitelist Headers: ['X-Is-HTML'] # 添加请求头匹配规则:仅当X-Is-HTML等于true时应用此行为 Condition: HeaderCondition: Header: 'X-Is-HTML' Value: 'true'
工作原理:
- 函数会给所有最终指向HTML文件的请求添加
X-Is-HTML: true头; - CloudFront会优先匹配带有这个头的请求,应用禁用缓存策略;
- 其他不带该头的静态资源请求会走默认的缓存优化策略。
内容的提问来源于stack exchange,提问作者dawaltco
相关产品推荐
相关产品推荐

