如何避免AWS S3静态站点根目录(如/blog)的302重定向
解决S3托管Middleman博客时/blog与/blog/的302跳转问题
我之前把静态博客部署到S3时也碰到过一模一样的问题——S3的索引文档机制虽然省心,但不带斜杠的路径总会触发302跳转,体验很不友好。这里给你几个可行的解决方案,按推荐程度排序:
方案一:用CloudFront + Lambda@Edge 实现无跳转路径重写
这是最优雅的长期解决方案,不需要修改你的Middleman构建输出,也不用维护重复文件。核心思路是在请求到达CloudFront边缘节点时,悄悄把/blog的请求路径改写为/blog/index.html,用户看到的URL不变,直接返回200状态码的内容。
步骤如下:
- 确保你的S3站点已经配置了CloudFront分发(如果还没配,这一步很值得做,还能带来缓存、HTTPS等额外好处)。
- 创建一个Lambda@Edge函数(选Node.js runtime),代码示例:
exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; const uri = request.uri; // 匹配不带斜杠的/blog路径,重写为索引文档路径 if (uri === '/blog') { request.uri = '/blog/index.html'; } callback(null, request); };
- 将这个函数关联到CloudFront分发的Viewer Request事件(即用户请求刚到达边缘节点时触发)。
- 等待CloudFront部署完成后,访问
/blog和/blog/就能看到都是200状态码,没有跳转了。
方案二:修改Middleman构建输出,生成重复内容对象
如果不想用CloudFront,你可以让Middleman在构建时同时生成blog和blog/index.html两个内容完全一致的文件,这样S3会直接返回对应路径的对象,不会触发索引文档的跳转逻辑。
做法很简单:
- 正常用Middleman构建你的站点:
middleman build
- 在构建完成后,添加一个脚本命令,把
blog/index.html复制为根目录下的blog文件:
cp build/blog/index.html build/blog
- 把整个
build文件夹上传到S3即可。
你也可以把这个复制命令加到你的构建脚本里,比如在package.json的scripts里配置:
"scripts": { "build": "middleman build && cp build/blog/index.html build/blog", "deploy": "aws s3 sync build/ s3://your-bucket-name/" }
这样每次构建部署都会自动同步两个文件,不用手动操作。
方案三:手动在S3中创建blog对象
如果只是临时解决,你可以直接用AWS CLI或S3控制台,把blog/index.html的内容复制到一个名为blog的新对象中:
aws s3 cp s3://your-bucket/blog/index.html s3://your-bucket/blog
不过这个方案的缺点是每次更新博客内容后,都要手动执行这个复制命令,否则blog对象的内容会和blog/index.html不一致,维护成本比较高,不推荐长期使用。
内容的提问来源于stack exchange,提问作者marko
相关产品推荐
相关产品推荐

