Python 3.X Lambda中Boto3生成S3预签名URL的区域异常问题
问题分析与解决方法
这不是Boto3的Bug,而是S3 URL格式的路由逻辑导致的问题:
- Boto3默认生成虚拟主机风格URL(
https://BUCKET_NAME.s3.amazonaws.com/...),这种格式对于非us-east-1区域的Bucket,部分场景下会出现路由异常,导致PUT请求无响应; - Node.js SDK默认生成带区域标识的URL(
https://s3.eu-west-1.amazonaws.com/BUCKET_NAME/...),路由逻辑更明确,所以能正常工作。
即使你在代码中指定了region_name,Boto3也不会自动给虚拟主机风格的URL添加区域标识,需要手动配置强制生成带区域的URL,有两种解决方式:
方式1:指定带区域的Endpoint URL
初始化S3客户端时,显式传入带区域的endpoint_url,强制生成带区域的虚拟主机风格URL:
import boto3 s3_client = boto3.client( 's3', region_name='eu-west-1', endpoint_url='https://s3.eu-west-1.amazonaws.com' ) # 生成预签名PUT URL presigned_url = s3_client.generate_presigned_url( 'put_object', Params={'Bucket': '你的Bucket名称', 'Key': 'testimage.jpg'}, ExpiresIn=3600 )
方式2:切换为路径风格URL
通过botocore.config.Config设置S3的寻址风格为path,生成的URL会把Bucket名称放在路径中,同时域名带区域标识:
import boto3 from botocore.config import Config # 配置路径风格寻址 s3_config = Config( region_name='eu-west-1', s3={'addressing_style': 'path'} ) s3_client = boto3.client('s3', config=s3_config) # 生成预签名PUT URL presigned_url = s3_client.generate_presigned_url( 'put_object', Params={'Bucket': '你的Bucket名称', 'Key': 'testimage.jpg'}, ExpiresIn=3600 )
两种方式生成的URL都会包含区域标识,解决PUT请求无响应的问题。
内容的提问来源于stack exchange,提问作者leos
相关产品推荐
相关产品推荐

