WebSocket ориентированое Api на Nest.js

от автора

В этой статье я расскажу как написал модуль под Nest.js позволяющий писать классическое RESTFull API со swagger’ом но клиент будет полностью на WebSocket’ах, звучит странно не так ли? Но зато очень быстро и удобно по итогу)

Идея состоит в том, что вы пишите классическое документированное апи, со всеми типами и плюшками.

  @Get(':id')   @WsAction('user')   getUser(@Param('id', ParseIntPipe) id: number): UserDto {     return this.appService.getUser(id);   }

Так же при настройка модуля в nest.js можно добавить валидацию сокетов, чтобы всё было под авторизацией. Вот небольшой пример из проекта:

@Module({     imports: [       ConfigModule.forRoot(),       WsModule.registerAsync({         useFactory: (): IWsApiConfig => {           return {             // тут указывается та же валидация что была             // использована для app.useGlobalPipes(new ValidationPipe(validationConfig));             validationConfig,             async validate(socket: Socket) {               try {                 const authGuard = new (AuthGuard('jwt'))();                 const isAuth = await (authGuard.canActivate(new ExecutionContextHost([socket])) as Promise<boolean>);                  if (!isAuth) {                   return HttpStatus.UNAUTHORIZED;                 }               } catch (e) {                 return HttpStatus.UNAUTHORIZED;               }               return HttpStatus.OK;             },           };         },       }),     ],   })

Далее на клиенте с помощью пакета swagger-typescript-api к примеру автоматически генерите полноценного HTTP клиента под ts. В котором описаны все типы и методы для http запросов. Но нам от него нужны только типы, впрочем вы можете сделать еще и fallback в случае проблем с сокетами.

Плюс можно сделать логику что при SSR делать запрос по HTTP и далее уже на WS.

export interface UserDto {   id: number;   firstName: string;   email: string; }

Идем дальше)

Что происходит на сервере:

  1. Собирается приложение, при компиляции декоратора WsAction он собирает всю инфу о методе контроллера, и кладет в свою коллекцию.

  2. Далее приложение запускается и собранная коллекция ожидает подключения по сокетам клиента, далее подписывается на евенты, названия которых совпадает с названием метода.

  3. Клиенту отправляется информация с конфигом с сервера если надо + статус подключения, когда можно уже дергать АПИ.

  4. И все это гуляет по одному каналу, что увеличивает скорость в ~10 раз.

[Nest] LOG [InstanceLoader] AppModule dependencies initialized +0ms [Nest] LOG [WsGateway] Add WS action: AppController => app:getUser [Nest] LOG [WsGateway] Add WS action: BusinessController => business:createUser [Nest] LOG [RoutesResolver] AppController {/api}: +2ms [Nest] LOG [RouterExplorer] Mapped {/api/:id, GET} route +3ms [Nest] LOG [RoutesResolver] BusinessController {/api/business}: +1ms [Nest] LOG [RouterExplorer] Mapped {/api/business/create, POST} route +0ms [Nest] LOG [NestApplication] Nest application successfully started +6ms

Можно заметить что сгенерились экшены на основе неймпейска указанного в контроллере, и названия метода к которому применили декоратор business:createUser и app:getUser

По сути это и есть название евента которое отправляется с клиента:

ws.emit('business:createUser', { payload });

Я бы на этом закончил, но мне не было достаточно асинхронного WS, я хотел чтобы было всё синхронно как все привыкли:

await fetch('api/create-user', { payload })

Для этого я написал небольшой клиент который промисофицирует асинхронные сокеты и получается по итогу:

const result = await webSocket.emit<ResultDto>('business:createUser', { payload });

Не хочется много кода сюда писать)

Модуль я опубликовал в npm, репа https://github.com/gustoase/nestjs-ws-api
Демо проекта чтобы запустить потыкать накидал на коленке https://github.com/gustoase/nestjs-ws-api-demo

Как запустить:

  1. npm i

  2. npm run start:dev

  3. cd client

  4. npm i

  5. npm run dev

  6. http://localhost:3001/

Что по итогу хочу сказать, проект на работе который был успешно запущен летает очень быстро, проблем с ним нет, авторизация имеется, валидация тоже.
Так же за счет своевременного оповещения с сервера о состоянии АПИ можно показывать красивые уведомления)


ссылка на оригинал статьи https://habr.com/ru/post/696252/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *