node.js - AWS API网关WebSocket API : how to use it with React/NodeJS/native WebSocket?

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

我正在构建我的应用程序:

前端:ReactJS/Javascript native Websocket: 在我使用 websocket 的组件中:

  useEffect(() => {  
    const orgId = localData.get('currentOrganizationId');
    const username = localData.get('username');

    let socket = new WebSocket(process.env.REACT_APP_WEBSOCKET_URL); // this is the AWS WebSocket URL after I have deployed it. 
    // let socket = new WebSocket("ws://127.0.0.1:3001");
    socket.onopen = function(e) {
      console.log('socket on onopen'); 
      const info = JSON.stringify({orgId:orgId, username: username, action: "message"});
      socket.send(info);
    };

    socket.onmessage = function(event) {
      console.log(`[message] Data received from server: ${event.data}`);
    };
    
    socket.onclose = function(event) {
      if (event.wasClean) {
        console.log(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
      } else {
        console.log(`[close] Connection died; code=${event.code}`);
      }
    };
    
    socket.onerror = function(error) {
      console.log(`[error] ${error.message}`);
    };

  }, [])

后端:NodeJS/ExpressJS/ws websocket 库:

./utils/websocket:

import WebSocket from "ws";
import queryString from "query-string";
import { StateManager } from '../state';
import logger from '../logger';


export default async (expressServer) => {

  StateManager.addToState('sockets', {});

  const websocketServer = new WebSocket.Server({
    noServer: true,
    // path: "/websockets",
    path: "/",
  });

  expressServer.on("upgrade", (request, socket, head) => {
    logger.info(`on upgrade: ${JSON.stringify(head)}`);
    websocketServer.handleUpgrade(request, socket, head, (websocket) => {
      websocketServer.emit("connection", websocket, request);
    });
  });

  websocketServer.on("connection", function connection(websocketConnection, connectionRequest) {
      logger.info(`on connection`);

      websocketConnection.on("message", (message) => {
        const info = JSON.parse(message);
        logger.info(`info: ${typeof info}  ${info}`);
        const sockets = StateManager.readFromState('sockets');
        sockets[info.username] = websocketConnection;
      });

  });

  return websocketServer;
};

index.ts中:

  import websocket from './utils/websocket';

  ...other code

  const app = express();

  ...other code

  const server = app.listen(parseInt(process.env.PORT) || 3001);  

  websocket(server);

虽然这在本地开发环境中运行良好,但我对如何将其移动到 AWS 感到非常困惑,如下所示:

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

我的配置是这样的: enter image description here

enter image description here

我已经阅读了该文档,但我仍然对从哪里开始感到困惑。我应该如何配置 $connect$disconnect$default 路由? 它们与我当前在 EC2 中运行的 websocket 客户端和 Nodejs 服务器有何关系?

我应该如何更改代码以将其与 AWS API Gateway Websocket API 集成?

目前根本没有任何回应: enter image description here

我提供的 Websocket URL 确实是正确的。

即使读完文档后,我仍然对从哪里开始解决这个问题感到困惑。

最佳答案

连接 Websocket 时没有响应的原因是您的后端 Express 应用中没有设置 HTTP 端点。

当您连接到 AWS API Gateway WebSocket API 时,WebSocket API 会执行 $connect 集成设置的操作。在当前配置中,您已在目标 URL 上设置 VPC 链接与 HTTP 方法 Any 的集成。因此,为了调用您的后端端点,您需要创建一个 HTTP 端点并将端点地址设置为“端点 URL”。

例如,假设您设置了以下路由。

app.get('/connect', function(req, res) {
    res.send('success');
});

如果您将“端点 URL”设置为“/connect”,则在连接到 WebSocket 时将会收到“成功”消息。

简而言之,您不需要在后端运行 websocket 服务器,因为 WebSocket API 会处理它。通过路由集成,您只需设置如何根据通过 WebSocket 发送的消息调用不同的方法(由后端 Node.js 服务器的 HTTP 端点提供)。

作为旁注,我建议使用以下选项之一。

  1. 如果您需要运行自己的后端,请不要使用 AWS API Gateway WebSocket API,因为没有必要。您可以改用 AWS ALB。
  2. 如果您不必运行自己的后端并且功能不太复杂,请使用 AWS Lambda 与 WebSocket API 集成并采用无服务器实时功能。 -- 编辑(根据评论提出另一个建议) --
  3. 如果您需要使用 API Gateway,您可以在 Node.js 后端设置 HTTP 端点,并将其集成到 WebSocket API $connect 集成中。然后,您集成的 HTTP 端点将在连接时被调用。

关于node.js - AWS API网关WebSocket API : how to use it with React/NodeJS/native WebSocket?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70679996/

相关文章:

javascript - 如何创建按钮来显示/隐藏 Docusaurus 项目中所有细节标签的状态?

amazon-web-services - 还原未版本控制的 Amazon S3 文件

amazon-web-services - AWS CloudFormation 中的嵌套参数组?

node.js - Mongoose:如何使用与数组中的一项匹配的数组值更新文档?

node.js - 错误 : Ident authentication failed for user

javascript - Mongoose/MongoDB 创建集合(如果不存在则基于架构)

hadoop - 在 Amazon EC2 上将 HDFS 与 Apache Spark 结合使用

javascript - 即使我仅在 'fs/promises' 内使用 fs 代码,也找不到模块 "getStaticProps()"- next js

ajax - Axios 放置请求和 symfony Controller

javascript - 在 React 中更新数组索引的状态