python3(lambda 函数)无法将响应发送回云形成模板

python3(lambda function) failing to send response back to cloud formation template

我已经使用lambda创建了一个用于跨s3-bucket对象复制的云形成模板,它是用python编写的,下面是lambda代码。

import json
import logging
import signal
import boto3
from urllib.request import *
s3 = boto3.resource('s3')
s3client = boto3.client('s3')
LOGGER = logging.getLogger()
LOGGER.setLevel(logging.INFO)
def lambda_handler(event, context):
  sourcebucketname = event['ResourceProperties']['SourceBucketName']
  destinationbucketname = event['ResourceProperties']['DestinationBucketName']
 
  accountid = boto3.client('sts').get_caller_identity()['Account']
  try:
      LOGGER.info('REQUEST RECEIVED:\n %s', event)
      LOGGER.info('REQUEST RECEIVED:\n %s', context)
      if event['RequestType'] == 'Create':
          LOGGER.info('CREATE!')
          response = s3client.list_objects(Bucket=sourcebucketname)
          print(response)
          for record in response['Contents']:
              key = record['Key']
              dest_key = key
              copy_source = {'Bucket': sourcebucketname, 'Key': key}
              destbucket = s3.Bucket(destinationbucketname)
              response = destbucket.copy(copy_source, dest_key, ExtraArgs={'ACL':'bucket-owner-full-control'})
              print(response)
              print('{} transferred to destination bucket'.format(key))
          send_response(event, context, "SUCCESS",
                        {"Message": "Resource creation successful!"})
      elif event['RequestType'] == 'Update':
          LOGGER.info('UPDATE!')
         
          send_response(event, context, "SUCCESS",
                        {"Message": "Resource update successful!"})
      elif event['RequestType'] == 'Delete':
          LOGGER.info('DELETE!')
          send_response(event, context, "SUCCESS",
                        {"Message": "Resource deletion successful!"})
      else:
          LOGGER.info('FAILED!')
          send_response(event, context, "FAILED",
                        {"Message": "Unexpected event received from CloudFormation"})
  except: #pylint: disable=W0702
      LOGGER.info('FAILED!')
      send_response(event, context, "FAILED", {
          "Message": "Exception during processing"})
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)
  request = Request(event['ResponseURL'], data=response_bdy)
  request.add_header('Content-Type', '')
  request.add_header('Content-Length', len(response_body))
  request.get_method = lambda: 'PUT'
  response = opener.open(request)
  LOGGER.info("Status code: %s", response.getcode())
  LOGGER.info("Status message: %s", response.msg)

s3 对象已成功复制到目标存储桶,但 lambda 函数无法将事件响应发送回云形成。下面是我得到的错误。

[ERROR] TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.
Traceback (most recent call last):
  File "/var/task/index.py", line 47, in lambda_handler
    send_response(event, context, "FAILED", {
  File "/var/task/index.py", line 69, in send_response
    response = opener.open(request)
  File "/var/lang/lib/python3.9/urllib/request.py", line 514, in open
    req = meth(req)
  File "/var/lang/lib/python3.9/urllib/request.py", line 1277, in do_request_
    raise TypeError(msg)
[ERROR] TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str. Traceback (most recent call last):   File "/var/task/index.py", line 47, in lambda_handler     send_response(event, context, "FAILED", {   File "/var/task/index.py", line 69, in send_response     response = opener.open(request)   File "/var/lang/lib/python3.9/urllib/request.py", line 514, in open     req = meth(req)   File "/var/lang/lib/python3.9/urllib/request.py", line 1277, in do_request_     raise TypeError(msg)

send_response 函数因上述错误而失败,请帮助哪里出错了。

错误消息告诉你出了什么问题。

[ERROR] TypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.

在您的代码中,response_body 是一个 str。您可以通过 response_body.encode('utf-8').

将其转换为 bytes