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

实现S3跨桶复制的Python3 Lambda无法向CloudFormation返回响应

问题根因

错误出在send_response函数的请求构造逻辑,两个兼容性问题导致urllib无法正确识别请求体类型:

  • 手动指定Content-Length请求头时,取值为未编码的JSON字符串长度,而实际发送的是UTF-8编码后的字节流,二者长度可能不一致,干扰urllib的请求校验逻辑
  • 采用重写Request对象get_method属性的方式修改请求方法为PUT,该写法是Python 2/3.6之前版本的兼容写法,在你使用的Python 3.9运行环境中存在兼容性问题,导致urllib误判请求体类型

修正后的send_response函数代码

def send_response(event, context, response_status, response_data):
  '''Send a resource manipulation status response to CloudFormation'''
  response_body = json.dumps({
      "Status": response_status,
      "Reason": "See the details in CloudWatch Log Stream: " + context.log_stream_name,
      "PhysicalResourceId": context.log_stream_name,
      "StackId": event['StackId'],
      "RequestId": event['RequestId'],
      "LogicalResourceId": event['LogicalResourceId'],
      "Data": response_data
  })
  # 编码为字节流
  response_bdy = response_body.encode('utf-8')
  LOGGER.info('ResponseURL: %s', event['ResponseURL'])
  LOGGER.info('ResponseBody: %s', response_body)
  opener = build_opener(HTTPHandler)
  # Python3 直接通过method参数指定PUT请求,无需重写get_method
  request = Request(event['ResponseURL'], data=response_bdy, method='PUT')
  request.add_header('Content-Type', '')
  # 无需手动设置Content-Length,urllib会自动根据字节流长度计算正确值
  response = opener.open(request)
  LOGGER.info("Status code: %s", response.getcode())
  LOGGER.info("Status message: %s", response.msg)

额外优化建议

当前代码中调用s3client.list_objects仅返回最多1000个对象,如果源桶对象超过1000个会出现复制不全的问题,建议替换为list_objects_v2结合分页逻辑处理全量对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 13:15:03