如何在NestJS中将动态端口传递给Websockets-gateway?

qxsslcnc  于 2022-11-11  发布在  其他
关注(0)|答案(3)|浏览(156)

我想在NestJS的config中动态设置Websockets-gateway端口。下面是我的websockets-gateway代码。

import { WebSocketGateway } from '@nestjs/websockets';

const WS_PORT = parseInt(process.env.WS_PORT);

@WebSocketGateway(WS_PORT)
export class WsGateway {
  constructor() {
    console.log(WS_PORT);
  }
}

但WS_PORT始终为NaN。
这是我的引导函数indie main.ts:

async function bootstrap() {
  const app = await NestFactory.create(AppModule, { cors: false });
  const configService = app.get(ConfigService);
  initAdapters(app);
  await app.listen(configService.get(HTTP_PORT), () => {
    console.log('Listening on port ' + configService.get(HTTP_PORT));
  });
}

下面是我的app.module.ts

@Module({
  imports: [
    ConfigModule.forRoot({
      envFilePath: './src/config/dev.env',
      isGlobal: true,
    }),
    RedisModule,
    SocketStateModule,
    RedisPropagatorModule,
    JwtModule.registerAsync({
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => ({
        secret: configService.get<string>(JWT_SECRET_KEY),
      }),
      inject: [ConfigService],
    }),
  ],
  controllers: [AppController],
  providers: [WsGateway, AppService],
})
export class AppModule {}

我在网关构造函数中放置了一个控制台日志来打印'WS_PORT'的值,但它始终是NaN。

[Nest] 13252  - 10/04/2021, 5:05:34 PM     LOG [NestFactory] Starting Nest application...
NaN

先谢谢你。

wvt8vs2t

wvt8vs2t1#

我找不到一种方法来添加动态数据到装饰器。所以为了能够动态地选择端口和其他配置,我必须:

  • 为socket-io创建适配器:
  • 告诉NestJs使用新的适配器

SocketIoAdapter.ts

import { INestApplicationContext } from '@nestjs/common';
import { IoAdapter } from '@nestjs/platform-socket.io';
import { ServerOptions } from 'socket.io';
import { ConfigService } from '@nestjs/config';

export class SocketIoAdapter extends IoAdapter {
constructor(
  private app: INestApplicationContext,
  private configService: ConfigService,
) {
  super(app);
}

createIOServer(port: number, options?: ServerOptions) {
  port = this.configService.get<number>('SOCKETIO.SERVER.PORT');
  const path = this.configService.get<string>('SOCKETIO.SERVER.PATH');
  const origins = this.configService.get<string>(
    'SOCKETIO.SERVER.CORS.ORIGIN',
  );
  const origin = origins.split(',');
  options.path = path;
  options.cors = { origin };
  const server = super.createIOServer(port, options);
  return server;
}
}

现在,您需要编辑main.ts以使用该适配器

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ConfigService } from '@nestjs/config';
import { SocketIoAdapter } from './socket-io/socket-io.adapter';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  const configService = app.get(ConfigService);
  const hosts = configService.get<string>('CORS.HOST');
  const hostsArray = hosts.split(',');
  app.enableCors({
    origin: hostsArray,
    credentials: true,
  });
//Here you use the adapter and sent the config service
  app.useWebSocketAdapter(new SocketIoAdapter(app, configService));
  await app.listen(4300);
}
bootstrap();

在本例中,我设置了端口和cors原点,这里是conf文件(使用.env)env.local的示例

SOCKETIO.SERVER.PORT=4101
SOCKETIO.SERVER.PATH=
SOCKETIO.SERVER.CORS.ORIGIN=http://localhost:4200,http://localhost.com:8080

这里是指向配置服务的链接配置服务NestJs

qco9c6ql

qco9c6ql2#

如果在调用app.init之前对Gateway进行修饰,则可以相对简单地完成此操作:
1.导入main.ts中的类
1.获取ConfigurationService的示例
1.使用配置数据在类上手动调用装饰器

function decorateGateway(class_, config) {
  // Just calling the decorator as a function with the class
  // as argument does the same as `@WebSocketGateway`
  WebSocketGateway({
    cors: {
      origin: config.get("websocket.cors.origin"),
    }
  })(class_)
}

async function bootstrap() {
  const app = await NestFactory.create(AppModule, {});
  const config = app.get(ConfigService);
  decorateGateway(ChatGateway, config);
  ...
  app.init();
}

Gateway的棘手之处在于,它与服务器一起启动,装饰器元数据需要比其他组件更早地应用到类中。您可以在app.init之前在main.ts中执行此操作。

2skhul33

2skhul333#

port = this.configService.get<number>('SOCKETIO.SERVER.PORT');

在我的例子中,我找到了它的返回字符串(来自.env),port得到的是'string'而不是'number',
但如果输入parseInt(this.configService.get<number>('SOCKETIO.SERVER.PORT'), 10);,则可以
请注意,服务器端和客户端的socket-io端口必须相同

相关问题