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

无需Postman:如何用AWS Signature认证调用Lambda函数并解决签名异常?

解决方案

一、HTTP请求方法选择

用POST请求,因为需要传递请求体(包含text参数),PUT多用于资源更新,POST更适合提交数据触发Lambda执行。

二、Cloudshell签名不匹配问题解决

  1. 改用AWS签名工具生成请求
    Postman导出的cURL可能包含临时凭证(如用了IAM临时会话),Cloudshell中环境凭证如果不匹配就会报错。直接用awscurl生成带正确签名的请求更可靠:

    • 安装awscurl:
      pip install awscurl
      
    • 执行请求(替换占位符为你的实际信息):
      awscurl --service lambda --region us-east-1 -X POST -H "Content-Type: application/json" -d '{"text": "Test text to speech"}' https://<API_GATEWAY_ID>.execute-api.us-east-1.amazonaws.com/<STAGE>/<FUNCTION_NAME>
      
  2. 校验凭证与签名版本
    确认Cloudshell中的AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_SESSION_TOKEN(临时凭证时)正确,执行echo $AWS_ACCESS_KEY_ID查看。Lambda API要求使用Signature Version 4,awscurl默认会用该版本,避免签名格式错误。

三、Make.com请求体识别问题解决

  1. 配置原始JSON请求体
    Make.com的Lambda模块默认可能将请求体解析为键值对,而你的代码期望event['body']是JSON字符串。在Make中设置请求体为原始JSON格式,粘贴{"text": "Test text to speech"},同时指定Content-Type为application/json。

  2. 兼容多格式输入
    修改Lambda代码,同时支持API Gateway的body字符串格式和Make.com直接传递的JSON对象:

    import json
    import boto3
    import uuid
    
    def lambda_handler(event, context):
        polly = boto3.client('polly')
        s3 = boto3.client('s3')
        
        # 兼容两种输入格式
        if isinstance(event, dict) and 'text' in event:
            text = event['text']
        elif 'body' in event:
            try:
                body = json.loads(event['body'])
                if 'text' not in body:
                    return {
                        'statusCode': 400,
                        'body': json.dumps('Error: text field is required')
                    }
                text = body['text']
            except json.JSONDecodeError:
                return {
                    'statusCode': 400,
                    'body': json.dumps('Error: Invalid JSON in request body')
                }
        else:
            return {
                'statusCode': 400,
                'body': json.dumps('Error: Request body missing or text field not found')
            }
        
        bucket_name = 'pollytts--use1-az6--x-s3'
        # 生成唯一文件名避免覆盖
        object_key = f'converted-speech-{uuid.uuid4()}.mp3'
        
        try:
            response = polly.synthesize_speech(
                Text=text,
                OutputFormat='mp3',
                VoiceId='Joanna'
            )
            audio_stream = response['AudioStream'].read()
            s3.put_object(
                Bucket=bucket_name,
                Key=object_key,
                Body=audio_stream,
                ContentType='audio/mpeg'
            )
            # 生成预签名URL(私有桶也能访问)
            file_url = s3.generate_presigned_url('get_object',
                                                Params={'Bucket': bucket_name, 'Key': object_key},
                                                ExpiresIn=3600)
            return {
                'statusCode': 200,
                'body': json.dumps({'url': file_url})
            }
        except Exception as e:
            return {
                'statusCode': 500,
                'body': json.dumps(f'Error: {str(e)}')
            }
    

四、优化实时性与可靠性

  1. 避免文件覆盖
    用UUID生成唯一的S3对象键,防止多个请求同时执行时覆盖MP3文件,确保返回的URL对应最新转换的内容。

  2. 使用预签名URL
    如果S3桶不是公开可读的,直接生成的公共URL会无法访问。预签名URL可设置有效期(如1小时),无需公开桶即可让用户访问文件,更安全。

  3. 添加调试日志
    在Lambda函数开头添加日志打印,方便排查输入问题:

    print("Received event:", json.dumps(event))
    

    可在CloudWatch Logs中查看完整的event内容,确认请求体是否正确传递。


内容的提问来源于stack exchange,提问作者Talib Kareem

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 22:42:02