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

短链接服务中CloudFront路由API Gateway与S3的问题排查

解决CloudFront短链接路由到API Gateway的问题

核心问题原因

当前CloudFront的默认*行为优先级覆盖了短链接请求,导致/1234abc这类无前缀的请求直接路由到S3,而非API Gateway的/{key}端点。CloudFront的路径匹配遵循从上到下、最具体优先的规则,需要调整行为配置或通过Lambda@Edge实现精准路由。

解决方案一:调整CloudFront行为优先级与路径匹配

通过分层设置行为,区分API请求、静态资源和短链接请求:

  • 保留现有/api/*行为(优先级设为最高):路由至API Gateway,处理/shorten_url等API请求。
  • 添加静态资源行为:路径模式设为/*.*(匹配所有带后缀的文件,如.css/.js/.png),优先级次之,路由至S3静态托管源。
  • 添加短链接行为:路径模式设为/*,优先级低于静态资源行为,路由至API Gateway。
  • 保留默认*行为(优先级最低):路由至S3的index.html,处理前端SPA路由场景。

这样配置后:

  • /api/shorten_url会匹配/api/*行为,走API Gateway;
  • /css/main.css会匹配/*.*行为,走S3;
  • /1234abc会匹配/*行为,走API Gateway的/{key}端点;
  • 根路径/会匹配默认*行为,返回前端首页。

解决方案二:用Lambda@Edge实现动态路由(更灵活)

如果静态资源后缀不固定,或需要自定义短链接格式校验,可通过Lambda@Edge的Viewer Request触发器动态调整路由:

  1. 创建部署在us-east-1区域的Lambda函数,逻辑如下:
exports.handler = (event, context, callback) => {
  const request = event.Records[0].cf.request;
  const uri = request.uri;

  // API请求直接放行到API Gateway
  if (uri.startsWith('/api/')) {
    callback(null, request);
    return;
  }

  // 带后缀的静态资源路由到S3
  if (uri.includes('.')) {
    request.origin = {
      s3: {
        domainName: '你的S3静态托管域名',
        region: '',
        authMethod: 'none',
        path: '',
        customHeaders: {}
      }
    };
    callback(null, request);
    return;
  }

  // 短链接请求路由到API Gateway
  request.origin = {
    custom: {
      domainName: '你的API Gateway域名',
      port: 443,
      protocol: 'https',
      path: '',
      sslProtocols: ['TLSv1.2'],
      readTimeout: 5,
      keepaliveTimeout: 5,
      customHeaders: {}
    }
  };
  callback(null, request);
};
  1. 在CloudFront的默认*行为中添加该Lambda函数作为Viewer Request触发器。

配套API Gateway Lambda逻辑校验

确保API Gateway的/{key}端点对应的Lambda函数能正确读取S3中/u/{key}的文件并返回重定向:

import boto3
import os

s3 = boto3.client('s3')
BUCKET_NAME = os.environ['BUCKET_NAME']

def lambda_handler(event, context):
    key = event['pathParameters']['key']
    try:
        s3_obj = s3.get_object(Bucket=BUCKET_NAME, Key=f'u/{key}')
        long_url = s3_obj['Body'].read().decode('utf-8')
        return {
            'statusCode': 302,
            'headers': {'Location': long_url}
        }
    except s3.exceptions.NoSuchKey:
        return {'statusCode': 404, 'body': 'Short URL not found'}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 02:52:53