API Gateway代理S3子目录问题:嵌套路径变量为空
我之前也碰到过类似的困扰,针对你描述的情况,这里有几个实用的解决方案:
方案一:修正路径变量与集成配置(无需Proxy+)
这是最直接的解决方式,不用切换集成类型就能搞定嵌套路径的问题:
更新API资源路径
把原来的/bucket/{item}路径修改为/bucket/{item+}。这里的+是API Gateway路径变量的特殊标记,它会把**整个多级嵌套路径(包括斜杠)**完整捕获到item变量里,而不是只抓取第一级路径。调整集成请求的路径覆盖
在AWS Service集成的路径覆盖设置里,保持填写{item}即可。现在当你访问/bucket/mybucketname/foo/bar/test.txt时,item变量会被赋值为mybucketname/foo/bar/test.txt,刚好匹配S3对象的完整键路径。验证参数映射
确认集成请求的路径参数映射中,method.request.path.item已经正确关联到S3集成的路径参数。如果之前的映射是正常的,这一步通常不需要额外修改。检查IAM权限
确保API Gateway使用的执行角色拥有S3的GetObject权限,策略示例如下:{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::mybucketname/*" } ] }
方案二:用Lambda作为中转(支持Proxy+场景)
如果你的业务场景必须使用{proxy+}路径,可以通过Lambda集成来实现,步骤如下:
创建Lambda函数
写一个简单的Python(或其他语言)函数,接收API Gateway的proxy请求,解析出S3的桶名和对象键,再调用S3的GetObject接口返回内容。示例代码:import boto3 from botocore.exceptions import ClientError s3 = boto3.client('s3') def lambda_handler(event, context): # 从proxy请求中提取对象路径 object_key = event['pathParameters']['proxy'] bucket_name = 'mybucketname' # 可根据需求动态获取 try: response = s3.get_object(Bucket=bucket_name, Key=object_key) return { 'statusCode': 200, 'headers': { 'Content-Type': response['ContentType'] }, 'body': response['Body'].read().decode('utf-8'), 'isBase64Encoded': False } except ClientError as e: return { 'statusCode': e.response['ResponseMetadata']['HTTPStatusCode'], 'body': str(e) }配置API Gateway的Lambda集成
创建一个使用{proxy+}路径的资源,选择Lambda集成类型,关联上面创建的函数。记得启用Lambda代理集成,这样请求参数会自动传递给Lambda。配置Lambda的IAM权限
给Lambda函数添加S3的GetObject权限,确保它能访问目标桶的对象。
方案三:使用S3静态网站托管的API Gateway集成
如果你的S3桶已经启用了静态网站托管,也可以通过API Gateway的HTTP集成指向S3的静态网站URL,这种方式天然支持多级路径。不过它更适合静态资源访问场景,灵活性不如前两种方案。
测试的时候可以用API Gateway的内置测试功能,查看路径变量的取值是否符合预期,能快速定位问题所在。
内容的提问来源于stack exchange,提问作者Johnny90

