You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

用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的默认错误页面。

注意事项

  1. 确保Nginx服务器能正常解析S3域名,可提前用curl测试S3 URL的可用性。
  2. 如果S3开启了静态网站托管,也可以使用静态站点Endpoint(格式为http://{bucket_name}.s3-website-{zone}.amazonaws.com)作为代理目标,配置逻辑一致。
  3. 若需要HTTPS访问,可在Nginx中配置SSL证书,监听443端口,同时保持S3目标URL为HTTPS格式。

内容的提问来源于stack exchange,提问作者Nitin Namdev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 22:07:49