短链接服务中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触发器动态调整路由:
- 创建部署在
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); };
- 在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
相关产品推荐
相关产品推荐

