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

基于Next.js 13与SST,实现CloudFront外部URL重写的方案咨询

背景

我有一个基于CRA React的大型仓库,需要为SSR添加SEO功能。因此创建了一个新的Next.js 13仓库,仅将需要SEO功能的页面(如着陆页)放在其中,希望通过URL重写实现增量迁移,让用户无感知。

需求目标

需要实现简单的外部URL重写:https://my-domain.com/company → https://my-domain-legacy.com/company

仓库与基础设施

创建了一个仅包含index路由的空Next.js 13项目,通过SST部署。已知Next.js提供rewrites功能,但目前SST仅支持内部URL重写,不支持外部URL重写。

问题

有什么方案可以实现需求?比如替代SST的工具,或通过Lambda@Edge/CloudFront函数实现的方法?

已尝试操作

尝试在Lambda@Edge函数中创建简单的内部URL重写:

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

    request.uri = request.uri
        .replace(/\/company$/,'/');

    return callback(null, request);
};

但访问Next.js路由中不存在的页面时,始终返回AccessDenied错误。

补充说明1

当前的函数代码:

exports.handler = (event, context, callback) => {
    console.log(event);
    
    const request = event.Records[0].cf.request;

    // request.uri = request.uri
    //     .replace(/\/company$/,'/');
    request.origin.custom.domainName = "https://my-domain-legacy.com"
    

    return callback(null, request);
};

使用上述Lambda函数时出现请求失败的错误,当前Lambda@Edge已配置基础执行权限。


可行解决方案

1. 修正Lambda@Edge函数实现外部重写

你的Lambda@Edge代码存在两处关键问题:

  • 设置origin.custom.domainName时不能带https://,只需填写纯域名
  • 未正确配置源的协议和请求头,导致CloudFront无法正确转发请求

修改后的函数代码如下:

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const uri = request.uri;

    // 匹配需要重写的路径,支持/company及子路径
    if (uri === '/company' || uri.startsWith('/company/')) {
        // 替换源信息为旧站点
        request.origin = {
            custom: {
                domainName: 'my-domain-legacy.com',
                port: 443,
                protocol: 'https',
                readTimeout: 5,
                keepaliveTimeout: 5,
                customHeaders: {},
                sslProtocols: ['TLSv1.2', 'TLSv1.1'],
            }
        };
        // 修改Host头为旧域名,确保旧站点能正确处理请求
        request.headers.host = [{
            key: 'Host',
            value: 'my-domain-legacy.com'
        }];
        // 保留原请求路径,无需修改uri
    }

    return callback(null, request);
};

同时需确保Lambda@Edge函数部署在us-east-1区域,并拥有以下权限:

  • cloudfront:UpdateDistribution
  • lambda:InvokeFunction
  • 允许关联到CloudFront分发的对应行为上

2. 改用支持外部重写的部署工具

如果不想编写Lambda函数,可以替换SST为以下工具:

  • Vercel:原生支持Next.js的rewrites配置,直接在next.config.js中添加外部重写规则:
    module.exports = {
        async rewrites() {
            return [
                {
                    source: '/company/:path*',
                    destination: 'https://my-domain-legacy.com/company/:path*',
                },
            ];
        },
    };
    
  • Serverless Framework:通过配置CloudFront自定义源和行为,实现外部URL重写,灵活性更高

3. CloudFront直接配置行为规则

无需编写代码,直接在CloudFront分发中配置:

  1. 新增行为,路径模式设为/company*
  2. 将该行为的源设置为旧站点的自定义源(my-domain-legacy.com)
  3. 配置缓存策略,确保请求头(如Host)正确转发到旧站点

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 23:55:18