用Python(FastAPI/Flask)搭建映射AWS S3的代理服务器及Nginx方案咨询
需求与解决方案:S3静态站点的反向代理配置
需求背景
我已将静态站点部署在AWS S3存储桶中,其URL格式如下:
https://{bucket_name}.s3.{zone}.amazonaws.com/website/{ID}/index.html
需要实现的流量转发规则:
username.localhost:9000 -> https://{bucket_name}.s3.{zone}.amazonaws.com/website/{username}/index.html
即把访问username.localhost:9000的流量转发到对应用户名的S3站点路径,同时需要Nginx实现方案建议。
我尝试的FastAPI解决方案
import uvicorn from fastapi import FastAPI, Request, HTTPException from fastapi.responses import StreamingResponse import boto3 app = FastAPI() S3_BUCKET_NAME = ${bucket} async def proxy_request(request: Request): s3_client = boto3.client('s3') # 根据需求构造S3对象键 x = request.url.path.split("/")[-2:] y = '/'.join(x) s3_key = f"website/{y}" try: # 从S3获取对象 response = s3_client.get_object(Bucket=S3_BUCKET_NAME, Key=s3_key) except s3_client.exceptions.NoSuchKey: raise HTTPException(status_code=404, detail="对象未找到") # 将S3对象内容返回给客户端 return StreamingResponse( content=response['Body'].iter_chunks(), status_code=200, headers={"Content-Type": response['ContentType']}, ) @app.middleware("http") async def proxy_middleware(request: Request, call_next): try: return await proxy_request(request) except HTTPException as exc: return exc if __name__ == "__main__": uvicorn.run(app, host="127.0.0.1", port=9000)
Nginx实现方案建议
核心配置思路
通过Nginx的正则捕获子域名(即username),拼接成对应的S3路径后完成反向代理转发。
完整配置示例
server { listen 9000; # 正则捕获子域名作为username变量 server_name ~^(?<username>.+)\.localhost$; location / { # 默认根路径指向对应username的index.html set $s3_target https://{bucket_name}.s3.{zone}.amazonaws.com/website/$username/index.html; # 如果请求是具体文件路径,替换为对应S3对象路径 if ($request_uri != "/") { set $s3_target https://{bucket_name}.s3.{zone}.amazonaws.com/website/$username$request_uri; } # 反向代理到S3 proxy_pass $s3_target; # 必须设置正确的Host头,否则S3会返回403 proxy_set_header Host {bucket_name}.s3.{zone}.amazonaws.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 拦截S3返回的错误,自定义处理 proxy_intercept_errors on; error_page 404 /404.html; } # 自定义404错误页面(可选) location = /404.html { root /path/to/your/error/pages; internal; } }
配置说明
server_name ~^(?<username>.+)\.localhost$:用正则提取子域名部分,赋值给$username变量,匹配所有xxx.localhost格式的域名。proxy_pass:根据请求路径拼接目标S3 URL,根路径默认指向index.html,具体文件请求则直接转发对应路径。proxy_set_header Host:S3会校验请求的Host头,必须设置为存储桶的S3域名,否则会拒绝请求。proxy_intercept_errors:开启后可自定义处理S3返回的404等错误,避免直接返回S3的默认错误页面。
注意事项
- 确保Nginx服务器能正常解析S3域名,可提前用
curl测试S3 URL的可用性。 - 如果S3开启了静态网站托管,也可以使用静态站点Endpoint(格式为
http://{bucket_name}.s3-website-{zone}.amazonaws.com)作为代理目标,配置逻辑一致。 - 若需要HTTPS访问,可在Nginx中配置SSL证书,监听443端口,同时保持S3目标URL为HTTPS格式。
内容的提问来源于stack exchange,提问作者Nitin Namdev
相关产品推荐
相关产品推荐

