Skip to content

新建页面,建立websocket连接

更新日期 2022-5-9
  • 2022-5-9 创建文档

开发环境

  • macOS 12.3.1
  • nest 8.1.5
  • postman 9.17.1

本文目标

  • 新建网页,nestjs提供静态资源支持
  • Web建立websocket连接
  • 简单处理跨域问题

静态页面

首先我们让NestJS提供静态页面支持

在工程中新建一个web/index.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title>Chat - an.rustfisher.com</title>

    <link rel="stylesheet" href="/css/main.css" />

</head>

<body>

    <h1>测试连接</h1>

    <div>
        <button id="connect">Connect</button>
        <button id="leave">Leave</button>
        <button id="send">Send</button>
    </div>

    <script src="https://cdn.socket.io/4.5.0/socket.io.min.js"
        integrity="sha384-7EyYLQZgWBi67fBtVxw60/OWl1kjsfrPFcaU0pp0nAh+i8FD068QogUvg85Ewy1k"
        crossorigin="anonymous"></script>
    <script src="/js/index.js"></script>

</body>

</html>
现在网页上的控件都没有用。只是展示。

回到项目中,首先我们需要安装@nestjs/serve-static包。

在工程路径下

$ npm install --save @nestjs/serve-static

安装完成后,工程的package.json里会多出

"dependencies": {
  "@nestjs/serve-static": "^2.2.2",
}

app.module.ts里,给imports加入配置,指定网页所在的目录

// app.module.ts
import { Module } from '@nestjs/common';
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { Chat1Gateway } from './gateway/chat1.gateway';
import { Chat2Gateway } from './gateway/chat2.gateway';

@Module({
  imports: [ServeStaticModule.forRoot({
    rootPath: join(__dirname, '..', 'web'),
    exclude: ['/api*'],
  }),],
  controllers: [AppController],
  providers: [AppService, Chat1Gateway, Chat2Gateway],
})
export class AppModule { }
工程使用的是3000端口。

运行工程,浏览器打开 http://localhost:3000/web 可以看到我们新建的页面

至此我们的工程可以提供静态资源。

建立连接

先改造一下Chat1Gateway,让它返回客户端发来的payload,原封不动传回去

@WebSocketGateway({ path: "/chat1" })
export class Chat1Gateway {
  @SubscribeMessage('message')
  handleMessage(client: any, payload: any): any {
    return {
      event: 'message',
      data: {
        code: 1,
        from: "https://an.rustfisher.com",
        msg: "[chat1]服务器发回来的消息",
        p: payload
      }
    };
  }
}

index.html里增加socket.io

    <script src="https://cdn.socket.io/4.5.0/socket.io.min.js"
        integrity="sha384-7EyYLQZgWBi67fBtVxw60/OWl1kjsfrPFcaU0pp0nAh+i8FD068QogUvg85Ewy1k"
        crossorigin="anonymous"></script>
    <script src="js/index.js"></script>

新建文件web/js/index.js

// index.js
'use strict';

var btnConn = document.querySelector('button#connect');
var btnLeave = document.querySelector('button#leave');
var btnSend = document.querySelector('button#send');

var socket = null; // 连接

// 发起连接
function conn() {
    console.log('try connect');

    const wssUrl = "http://localhost:3000"; // localhost debug

    socket = io(wssUrl, {path: '/chat1'});

    socket.on('connect', function () {
        console.log('链接成功');
    });

    socket.on('disconnect', (socket) => {
        console.log('socket已断开', socket);
    });

    socket.on('message', (data) => {
        console.log('[服务器消息], ', data);
    });

    socket.emit('message', {msg: "web连接测试"});
    return true;
}

function disconnect() {
    if(socket) {
        socket.disconnect();
    }
}

function sendMsg() {
    if(socket) {
        socket.emit('message', '目前是web的测试数据');
    }
}

btnConn.onclick = conn;
btnLeave.onclick = disconnect;
btnSend.onclick = sendMsg;

建立连接 socket = io(wssUrl, {path: '/chat1'});

发送消息 socket.emit('message', '目前是web的测试数据');

在本地运行服务,打开浏览器访问 http://localhost:3000/web ,打开console观察发送和接收的消息

如果直接双击打开html文件,连接时会报跨域问题

跨域问题

index.html:1 
Access to XMLHttpRequest at 'http://localhost:3000/chat1/?EIO=4&transport=polling&t=O2cxPNv' 
from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header 
is present on the requested resource.

简单处理跨域问题

我们来给Chat1Gateway添加配置,设置cors

// chat1.gateway.ts
import { SubscribeMessage, WebSocketGateway } from '@nestjs/websockets';

const opt1 = {
  path: '/chat1',
  allowEIO3: true,
  cors: {
      origin: /.*/,
      credentials: true
  }
};

@WebSocketGateway(opt1)
export class Chat1Gateway {
  @SubscribeMessage('message')
  handleMessage(client: any, payload: any): any {
    return {
      event: 'message',
      data: {
        code: 1,
        from: "https://an.rustfisher.com",
        msg: "[chat1]服务器发回来的消息",
        p: payload
      }
    };
  }
}
重新运行服务,从磁盘上打开index.html,点击连接。此时会看到websocket连接成功。

参考

作者: rustfisher.com | rf.cs@foxmail.com
示例: AndroidTutorial Gitee, Tutorial Github
本文链接: https://www.an.rustfisher.com/nestjs/simple-chat/web-connect-local/
一家之言,仅当抛砖引玉。如有错漏,还请指出。如果喜欢本站的内容,还请支持作者。也可点击1次下方的链接(链接内容与本站无关),谢谢支持服务器