使用 AWS Lambda 和 API Gateway NodeJs 的格式错误的 Lambda 代理响应

Posted

技术标签:

【中文标题】使用 AWS Lambda 和 API Gateway NodeJs 的格式错误的 Lambda 代理响应【英文标题】:Malformed Lambda proxy response with AWS Lambda and API Gateway NodeJs 【发布时间】:2021-01-08 07:11:33 【问题描述】:

我正在使用 API Gateway 和 AWS Lambda 与另一个 AWS Lambda 函数进行交换。

我应该在初始请求插入数据后发送响应,无论是成功还是失败。我正在使用 API 网关的特定路由。

结构如下:

现在我不断收到 502 Malformed Lambda 代理响应,这在我的 API 测试日志中:

Tue Sep 22 06:56:10 UTC 2020 : Endpoint response headers: Date=Tue, 22 Sep 2020 06:56:10 GMT, Content-Type=application/json, Content-Length=4, Connection=keep-alive, x-amzn-RequestId=xxxxxxxx, x-amzn-Remapped-Content-Length=0, X-Amz-Executed-Version=$LATEST, X-Amzn-Trace-Id=xxxxxxx
Tue Sep 22 06:56:10 UTC 2020 : Endpoint response body before transformations: null
Tue Sep 22 06:56:10 UTC 2020 : Execution failed due to configuration error: Malformed Lambda proxy response
Tue Sep 22 06:56:10 UTC 2020 : Method completed with status: 502

问题是我正在返回一个真实的响应。正如我之前所说,我将 API Gateway 与 lambda-api 一起使用,这是一个处理 API 网关路由的包,例如 Express,这就是我正在做的事情:

api.post('/database-manager/create-request', async (lambdaRequest, lambdaResponse, callback) => 
    await provideConnectionInfo()
    let connection = mysql.createConnection(
            host: mySQLHost,
            user: mySQLUser,
            password: mySQLPassword,
            database: mySQLDatabase
        
    )
    requestNb = lambdaRequest.headers["request-id"]
    pipelineId = lambdaRequest.headers["pipeline-id"]

    connection.connect(function (err) 
            if (err) throw err
            let query = "INSERT INTO ec2_request(request_id, pipeline_id) VALUES (?,?)"
            connection.query(query,[requestNb,pipelineId], function (err, result) 
                    if (err) 
                        connection.end()
                        console.log("insertion did not work : " + err)
                        let response = 
                            "statusCode": 404,
                            "headers": ,
                            "isBase64Encoded": false,
                            "body": JSON.stringify(message: "Record not inserted")
                        
                         return response
                        )

                     else 
                        connection.end()
                        console.log("1 record inserted")
                        let response = 
                            "statusCode": 200,
                            "headers": ,
                            "isBase64Encoded": false,
                            "body": JSON.stringify(message: "tired of this bs")
                        
                        return response

                    
                
            )
        
    )

)

最糟糕的是我的日志没有显示任何错误:

1600758637213   START RequestId: f804577b-c0a2-4d11-8822-52363fa41c7d Version: $LATEST
1600758639189   2020-09-22T07:10:39.188Z    f804577b-c0a2-4d11-8822-52363fa41c7d    INFO    1 record inserted
1600758639348   END RequestId: f804577b-c0a2-4d11-8822-52363fa41c7d
1600758639348   REPORT RequestId: f804577b-c0a2-4d11-8822-52363fa41c7d  Duration: 2134.45 ms    Billed Duration: 2200 ms    Memory Size: 128 MB Max Memory Used: 94 MB  Init Duration: 555.23 ms

如果有人看到我可能犯了错误,我会给他们买一个甜甜圈。

想知道是不是状态不对...

非常感谢,

票价

【问题讨论】:

【参考方案1】:

您正在async 内部使用回调函数,无需等待。

这里有几个选项

    api.post('/database-manager/create-request', async (lambdaRequest, lambdaResponse, callback) => 中删除async

    保持异步并将query function 包装为Promise 并使用await

    api.post('/database-manager/create-request', async (lambdaRequest, lambdaResponse, callback) => 
     await provideConnectionInfo()
     let connection = mysql.createConnection(
             host: mySQLHost,
             user: mySQLUser,
             password: mySQLPassword,
             database: mySQLDatabase
         
     )
     requestNb = lambdaRequest.headers["request-id"]
     pipelineId = lambdaRequest.headers["pipeline-id"]
    
    
     const res = await new Promise(function(resolve, reject) 
         connection.connect();
         let query = "INSERT INTO ec2_request(request_id, pipeline_id) VALUES (?,?)"
    
         connection.query(query,[requestNb,pipelineId], function (err, result) 
             if (err) 
                 connection.end()
                 console.log("insertion did not work : " + err)
                 let response = 
                     "statusCode": 404,
                     "headers": ,
                     "isBase64Encoded": false,
                     "body": JSON.stringify(message: "Record not inserted")
                 
                 reject(response)
    
              else 
                 connection.end()
                 console.log("1 record inserted")
                 let response = 
                     "statusCode": 200,
                     "headers": ,
                     "isBase64Encoded": false,
                     "body": JSON.stringify(message: "tired of this bs")
                 
                 resolve(response)
    
             
         )
     );
    
     return res;   
    )
    

注意:代码未经测试。

【讨论】:

以上是关于使用 AWS Lambda 和 API Gateway NodeJs 的格式错误的 Lambda 代理响应的主要内容,如果未能解决你的问题,请参考以下文章

使用 AWS Lambda 和 API Gateway NodeJs 的格式错误的 Lambda 代理响应

使用 Lambda 授权方的 AWS Cognito 和 API 网关

使用 AWS api 网关 + lambda + Nodejs 的私有和公共 ip

如何调试 AWS Api Gateway 和 Lambda 的“AWS/ApiGateway 5XXError”

AWS API Gateway 默认响应和触发 AWS Lambda

使用代理通过 AWS API Gateway 的 Lambda 错误