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

基于Lambda Edge函数的S3存储桶内容路由可行性及实现方案

实现Lambda Edge路由到S3单桶多目录或多桶(URL不变)

完全可以实现你的需求,不管是单S3桶内的目录路由,还是多S3桶的切换,都可以通过Origin Request类型的Lambda Edge函数完成,且用户可见的URL不会改变,无需重定向。

核心原理

Origin Request触发器的Lambda Edge函数会在CloudFront将请求转发到源站(S3)之前执行,你可以在这个阶段修改请求的目标路径(单桶场景)或直接切换源站域名(多桶场景),CloudFront会根据修改后的请求拉取对应内容并返回给用户,整个过程对用户透明。


场景1:单S3桶多目录路由

假设你的S3桶结构如下:

my-bucket/
├─ siteA/
│  ├─ index.html
│  ├─ css/
│  └─ js/
└─ siteB/
   ├─ index.html
   ├─ css/
   └─ js/

实现步骤

  1. 配置CloudFront分发,将源设置为你的S3桶,确保CloudFront通过OAI(Origin Access Identity)有权访问桶内内容。
  2. 创建并部署Origin Request类型的Lambda Edge函数(必须部署在us-east-1区域),逻辑如下:
    • 调用后端API获取路由标识(如siteA或siteB)。
    • 修改请求的uri,在原路径前添加对应目录前缀。
    • 处理根路径(/)的默认文档跳转,比如自动指向/siteA/index.html。

示例代码(Node.js)

exports.handler = async (event) => {
    const request = event.Records[0].cf.request;

    try {
        // 调用后端API获取路由规则
        const apiRes = await fetch('https://your-api-domain.com/get-route', {
            method: 'GET',
            headers: { 'Content-Type': 'application/json' }
        });
        const routeInfo = await apiRes.json();
        const sitePrefix = routeInfo.site === 'siteA' ? '/siteA' : '/siteB';

        // 修改请求URI,添加目录前缀
        if (request.uri === '/') {
            // 根路径默认指向对应目录的index.html
            request.uri = `${sitePrefix}/index.html`;
        } else {
            // 其他路径直接拼接前缀
            request.uri = `${sitePrefix}${request.uri}`;
        }
    } catch (err) {
        // API调用失败时的降级逻辑,默认路由到siteA
        request.uri = request.uri === '/' ? '/siteA/index.html' : `/siteA${request.uri}`;
    }

    return request;
};

场景2:多S3桶路由

如果使用两个独立的S3桶(siteA-bucket和siteB-bucket)分别存放静态站点,实现逻辑类似,但需要修改请求的源站域名。

实现步骤

  1. 为两个S3桶分别配置CloudFront OAI访问权限,确保CloudFront能读取桶内内容。
  2. 创建Origin Request类型的Lambda Edge函数,逻辑如下:
    • 调用后端API获取路由标识。
    • 修改请求的origin.s3.domainName为对应桶的域名。
    • 更新请求的Host头,匹配目标桶的域名,避免S3返回403错误。

示例代码(Node.js)

exports.handler = async (event) => {
    const request = event.Records[0].cf.request;

    try {
        // 调用后端API获取路由规则
        const apiRes = await fetch('https://your-api-domain.com/get-route', {
            method: 'GET',
            headers: { 'Content-Type': 'application/json' }
        });
        const routeInfo = await apiRes.json();

        // 根据路由结果切换S3源
        const targetBucket = routeInfo.site === 'siteA' 
            ? 'siteA-bucket.s3.amazonaws.com' 
            : 'siteB-bucket.s3.amazonaws.com';

        // 修改源站域名
        request.origin.s3.domainName = targetBucket;
        // 更新Host头,匹配目标桶域名
        request.headers['host'] = [{ key: 'Host', value: targetBucket }];
    } catch (err) {
        // 降级到siteA桶
        request.origin.s3.domainName = 'siteA-bucket.s3.amazonaws.com';
        request.headers['host'] = [{ key: 'Host', value: 'siteA-bucket.s3.amazonaws.com' }];
    }

    return request;
};

关键注意事项

  • 触发器类型必须选Origin Request:只有这个阶段能修改请求的源或路径,且不会触发重定向。
  • Lambda部署区域限制:Lambda Edge函数必须部署在us-east-1区域,才能关联到CloudFront分发。
  • API性能优化:后端API的响应延迟会直接影响用户访问速度,建议添加缓存逻辑(比如用Redis缓存路由结果),同时设置合理的超时时间。
  • 错误处理:必须添加API调用失败的降级逻辑,避免用户看到5xx错误。
  • 缓存策略:如果路由规则是基于用户身份的(比如不同用户看到不同站点),需要在CloudFront缓存策略中排除用户标识相关的Cookie/Header,或者将其加入缓存键,防止缓存共享导致错误路由。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 15:45:43