【问题标题】:AWS API Gatewat WebSocket: Request Templates body of request after transformations is missing in integration backendAWS API Gateway WebSocket:集成后端中缺少转换后请求的请求模板正文
【发布时间】:2022-01-18 21:57:35
【问题描述】:

我正在 AWS 上构建我的应用程序,我的应用程序使用 websocket,如下所示:

前端 WebSocket 客户端 ---> AWS API Gateway Websocket API ----> EC2 实例中的后端。

现在,为了让我的后端 Express 代码知道如何向特定客户端发送消息,我让它知道 websocket 客户端/用户的connectionId。我正在关注这两个答案:

已经解释得很清楚了。

以下是我在 AWS API Gateway WebSocket API 中的配置:

我所做的是使用请求模板,匹配所有传入的请求,将内容转换为请求的主体发送到我的集成端点。 最终我想保留原始请求,同时在其上添加属性(如连接 ID)。 出于测试目的,我设置了以下模板:

{
    "myConnectionId": "$context.connectionId",
    "body": "$context"
}

这行得通,我可以在 AWS CloudWatch 中检查转换后的请求正文是

{
   "myConnectionId":"MFEdof95tjMCK0w=",
   "body":"{routeKey=$connect, disconnectStatusCode=null, messageId=null, eventType=CONNECT, extendedRequestId=MFEdoFJPtjMF64Q=, requestTime=17/Jan/2022:07:29:01 +0000, messageDirection=IN, disconnectReason=null, stage=production, connectedAt=1642404541417, requestTimeEpoch=1642404541418, identity={cognitoIdentityPoolId=null, cognitoIdentityId=null, principalOrgId=null, cognitoAuthenticationType=null, userArn=null, userAgent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36, accountId=null, caller=null, sourceIp=219.102.102.145, accessKey=null, cognitoAuthenticationProvider=null, user=null}, requestId=MFEdoFJPtjMF64Q=, domainName=123.execute-api.ap-northeast-1.amazonaws.com, connectionId=MFEdof95tjMCK0w=, apiId=hd5zymklr8}"
}

但是,在我运行在 EC2 实例中的 Express 后端中,即使触发了端点,请求正文也是空的,并且在其中找不到 myConnectionId 的地方。

后端:NodeJS / ExpressJS,在index.ts:

  app.get('/connect', function(_req, res) {
    logger.info(`/connect _req: ${Object.keys(_req)}`);
    logger.info(`/connect _req.query: ${JSON.stringify(_req.query)}`);
    logger.info(`/connect _req.params: ${JSON.stringify(_req.params)}`);
    logger.info(`/connect _req.body: ${JSON.stringify(_req.body)}`);
    logger.info(`/connect _req.headers: ${JSON.stringify(_req.headers)}`);
    res.send('/connect hahaha success');
  });

日志输出:

2022-Jan-17 05:05:00:50  info: /connect _req: _readableState,_events,_eventsCount,_maxListeners,socket,httpVersionMajor,httpVersionMinor,httpVersion,complete,rawHeaders,rawTrailers,aborted,upgrade,url,method,statusCode,statusMessage,client,_consuming,_dumped,next,baseUrl,originalUrl,_parsedUrl,params,query,res,_startAt,_startTime,_remoteAddress,body,_parsedOriginalUrl,route
2022-Jan-17 05:05:00:50  info: /connect _req.query: {}
2022-Jan-17 05:05:00:50  info: /connect _req.params: {}
2022-Jan-17 05:05:00:50  info: /connect _req.body: {}
2022-Jan-17 05:05:00:50  info: /connect _req.headers: {"x-amzn-apigateway-api-id":"hd5zymklr8","x-amzn-trace-id":"Root=1-61e5232c-626a05ff264650183a73c98a","user-agent":"AmazonAPIGateway_hd5zymklr8","content-type":"application/json","accept":"application/json","host":"NLB-docloud-internal-ea0692d1e2c8186c.elb.ap-northeast-1.amazonaws.com","connection":"Keep-Alive"}

请求确实发送到了endpoint,但是为什么请求体是空的?

内容是如何丢失的?

【问题讨论】:

标签: node.js amazon-web-services websocket aws-api-gateway


【解决方案1】:

我对此进行了一些研究。

正如本文所讨论的:AWS API Gateway Websockets -- where is the connectionID?,接受的答案(我在上面的问题中尝试的解决方案)假设您使用 Lambda 作为后端集成。

但是,我使用的是在 EC2 实例和 VPC Link 中运行的 Express JS。

在我的情况下,这个问题实际上是通过一个被赞成的答案(但不是被接受的答案)解决的:https://stackoverflow.com/a/65639742/3703783

官方文档在这里:Setting up data mapping for WebSocket APIs.

更新

上述方法会将connectionId添加到集成请求的头部,但只有connectionId是不够的-我们还需要用户名等信息,以便后端能够知道发送消息时使用哪个connectionId特定的用户。这样就可以了:

aws apigatewayv2 update-integration 
--integration-id xxx 
--api-id xxx 
--request-parameters 'integration.request.header.userinfo'='route.request.body' 

另外,我还发现在我原来的问题中,而不是这样做

{
    "myConnectionId": "$context.connectionId",
    "body": "$context"
}

我应该这样做:

{
  "integration.request.header.connectionId":"$context.connectionId",
}

这会将connectionId添加到请求标头中。

【讨论】:

    猜你喜欢
    • 2018-01-20
    • 2016-01-21
    • 1970-01-01
    • 2020-03-17
    • 2021-04-20
    • 2018-01-25
    • 2020-05-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多