如何配置CloudFront与S3,使所有路由自动指向对应目录下的index.html?
解决S3+CloudFront托管静态站点子目录自动指向index.html的问题
这问题我之前帮好几个朋友解决过——S3的默认根对象确实只对根域名生效,子目录的请求它完全管不着。不过别担心,用CloudFront的两种工具就能完美搞定,给你推荐两种方案,按需选就行:
方案一:CloudFront函数(推荐,轻量又免费)
这是现在最省心的方式,CloudFront函数专门处理这类简单的请求改写,延迟低还不额外收费:
- 登录CloudFront控制台,找到你的分发,切换到函数标签页
- 点击「创建函数」,选择「查看器请求」类型,随便起个好记的名字(比如
SubdirectoryIndexRewrite) - 把下面的代码粘贴到编辑器里:
function handler(event) { const request = event.request; const uri = request.uri; // 两种情况自动追加index.html:路径以/结尾,或者没有文件后缀的路径 if (uri.endsWith('/')) { request.uri += 'index.html'; } else if (!uri.includes('.')) { request.uri += '/index.html'; } return request; }
- 点击「发布」,然后回到分发的函数关联页面,把这个函数绑定到你的分发的查看器请求事件上
- 等个几分钟让CloudFront部署完成,之后访问
/articles或者/article1,就会自动指向对应的index.html了
方案二:Lambda@Edge(适合复杂场景)
如果你的需求更复杂(比如要加一些自定义判断逻辑),可以用Lambda@Edge,功能更灵活:
- 注意:Lambda@Edge必须在**us-east-1(弗吉尼亚北部)**区域创建,先切换到这个区域
- 创建一个Node.js运行时的Lambda函数,粘贴下面的代码:
exports.handler = async (event) => { const request = event.Records[0].cf.request; const uri = request.uri; // 判断逻辑和CloudFront函数一致:处理以/结尾或无后缀的路径 if (uri.endsWith('/')) { request.uri += 'index.html'; } else if (!uri.match(/\.[0-9a-z]+$/i)) { request.uri += '/index.html'; } return request; };
- 给Lambda函数添加权限:在函数的「配置」→「权限」里,确保有允许CloudFront调用的权限(创建函数时如果选了CloudFront触发器,会自动添加)
- 回到CloudFront控制台,编辑你的分发的默认行为,在「Lambda函数关联」里添加这个Lambda,事件类型选查看器请求,选择函数的最新版本
- 部署分发后,测试子目录访问即可
额外注意事项
- 测试前记得清一下CloudFront的缓存,避免旧缓存干扰结果
- 两种方案都会自动忽略带后缀的请求(比如
.css、.js、图片),不会影响静态资源的正常访问 - CloudFront函数相比Lambda@Edge成本更低、延迟更小,优先推荐用方案一
内容的提问来源于stack exchange,提问作者Blueboye
相关产品推荐
相关产品推荐

