Naučte se, jak vytvořit chatovací API v reálném čase využívající sílu WebSockets pomocí NestJS.
NestJS je populární framework pro vytváření aplikací na straně serveru pomocí Node.js. Díky podpoře WebSockets se NestJS dobře hodí pro vývoj chatovacích aplikací v reálném čase.
Co jsou tedy WebSockets a jak můžete v NestJS vytvořit chatovací aplikaci v reálném čase?
Co jsou WebSockets?
WebSockets jsou protokolem pro trvalou, v reálném čase a obousměrnou komunikaci mezi klientem a serverem.
Na rozdíl od HTTP, kde je spojení uzavřeno po dokončení cyklu požadavku mezi klientem a serverem, připojení WebSocket zůstává otevřené a neuzavře se ani poté, co byla vrácena odpověď na a žádost.
Obrázek níže je vizualizací toho, jak funguje komunikace WebSocket mezi serverem a klientem:
K navázání obousměrné komunikace odešle klient serveru požadavek na navázání spojení WebSocket. Hlavičky požadavků obsahují zabezpečený klíč WebSocket (Sec-WebSocket-Key), a an Upgrade: WebSocket záhlaví, které spolu s Připojení: Upgrade
hlavička říká serveru, aby upgradoval protokol z HTTP na WebSocket a ponechal připojení otevřené. Učit se o WebSockets v JavaScriptu pomáhá ještě lépe porozumět konceptu.Vytvoření rozhraní API pro chat v reálném čase pomocí modulu NestJS WebSocket
Node.js poskytuje dvě hlavní implementace WebSockets. První je ws který implementuje holé WebSockets. A ten druhý je socket.io, který poskytuje více funkcí na vysoké úrovni.
NestJS má moduly pro oba socket.io a ws. Tento článek používá socket.io modul pro funkce WebSocket ukázkové aplikace.
Kód použitý v tomto projektu je k dispozici v a úložiště GitHub. Doporučuje se, abyste jej naklonovali lokálně, abyste lépe porozuměli struktuře adresářů a viděli, jak se všechny kódy vzájemně ovlivňují.
Nastavení a instalace projektu
Otevřete svůj terminál a vygenerujte novou aplikaci NestJS pomocí hnízdo nové příkaz (např. vnořte novou chatovací aplikaci). Příkaz vygeneruje nový adresář, který obsahuje soubory projektu. Nyní jste připraveni zahájit proces vývoje.
Nastavte připojení MongoDB
Chcete-li zachovat chatové zprávy v aplikaci, potřebujete databázi. Tento článek používá databázi MongoDB pro naši aplikaci NestJS, a nejjednodušší způsob, jak začít běhat, je nastavit cluster MongoDB v cloudu a získejte svou adresu MongoDB. Zkopírujte adresu URL a uložte ji jako MONGO_URI proměnná ve vašem .env soubor.
Mongoose byste také potřebovali později, když budete zadávat dotazy na MongoDB. Nainstalujte jej spuštěním npm nainstalovat mongoose ve vašem terminálu.
V src složku, vytvořte soubor s názvem mongo.config.ts a vložte do něj následující kód.
import { zaregistrovat jako } z'@nestjs/config';
/**
* Konfigurace připojení databáze Mongo
*/
vývoznívýchozí registrovat jako('mongodb', () => {
konst { MONGO_URI } = process.env; // ze souboru .env
vrátit se {
uri:`${MONGO_URI}`,
};
});
Váš projekt main.ts soubor by měl vypadat takto:
import { NestFactory } z'@nestjs/core';
import { AppModule } z'./app.module';
import * tak jako cookieParser z'cookie-parser'
import helma z'helma'
import { Logger, ValidationPipe } z'@nestjs/common';
import { setupSwagger } z'./utils/swagger';
import { HttpExceptionFilter } z'./filters/http-exception.filter';asynchronnífunkcebootstrap() {
konst aplikace = čekat NestFactory.create (AppModule, { kor: skutečný });
app.enableCors({
původ: '*',
pověření: skutečný
})
app.use (cookieParser())
app.useGlobalPipes(
Nový ValidationPipe({
whitelist: skutečný
})
)
konst záznamník = Nový Logger('Hlavní')app.setGlobalPrefix('api/v1')
app.useGlobalFilters(Nový HttpExceptionFilter());setupSwagger (aplikace)
app.use (helma())čekat app.listen (AppModule.port)
// protokolovat dokumenty
konst baseUrl = AppModule.getBaseUrl (aplikace)
konst url = `http://${baseUrl}:${AppModule.port}`
logger.log(`Dokumentace API dostupná na ${url}/docs`);
}
bootstrap();
Vytvoření modulu chatu
Chcete-li začít s funkcí chatu v reálném čase, prvním krokem je instalace balíčků NestJS WebSockets. To lze provést spuštěním následujícího příkazu v terminálu.
npm install @nestjs/websockets @nestjs/platform-socket.io @types/socket.io
Po instalaci balíčků musíte vygenerovat modul chatů spuštěním následujících příkazů
chaty nest g modulu
chaty nest g controller
chaty služby nest g
Po dokončení generování modulu je dalším krokem vytvoření připojení WebSockets v NestJS. Vytvořit chat.gateway.ts soubor uvnitř chaty je zde implementována brána, která odesílá a přijímá zprávy.
Vložte následující kód do chat.gateway.ts.
import {
MessageBody,
Odebírat zprávu,
WebSocketGateway,
WebSocketServer,
} z'@nestjs/websockets';
import { Server } z'socket.io';
@WebSocketGateway()
vývoznítřídaChatová brána{
@WebSocketServer()
server: Server;
// poslech událostí send_message
@Správa k odběru('poslat zprávu')
listenForMessages(@MessageBody() zpráva: řetězec) {
tento.server.sockets.emit('receive_message', zpráva);
}
}
Ověřování připojených uživatelů
Autentizace je nezbytnou součástí webových aplikací a nejinak je tomu u chatovací aplikace. Funkce pro ověřování klientských připojení k soketu se nachází v chats.service.ts jak je ukázáno zde:
@Injekční()
vývoznítřídaChatsService{
konstruktér(soukromá authService: AuthService) {}asynchronní getUserFromSocket (socket: Socket) {
nechat auth_token = socket.handshake.headers.authorization;
// získejte samotný token bez "nosiče"
auth_token = auth_token.split(' ')[1];konst uživatel = tento.authService.getUserFromAuthenticationToken(
auth_token
);
-li (!user) {
házetNový WsException("Neplatné přihlašovací údaje.");
}
vrátit se uživatel;
}
}
The getUserFromSocket metoda používá getUserFromAuthenticationToken získat aktuálně přihlášeného uživatele z tokenu JWT extrahováním tokenu nositele. The getUserFromAuthenticationToken funkce je implementována v auth.service.ts soubor, jak je znázorněno zde:
veřejnost asynchronní getUserFromAuthenticationToken (token: string) {
konst užitečné zatížení: JwtPayload = tento.jwtService.verify (token, {
tajný: tento.configService.get(„JWT_ACCESS_TOKEN_SECRET“),
});konst userId = payload.sub
-li (uživatelské ID) {
vrátit setento.usersService.findById (userId);
}
}
Aktuální soket je předán jako parametr getUserFromSocket když rukojeťPřipojení metoda Chatová brána implementuje OnGatewayConnection rozhraní. To umožňuje přijímat zprávy a informace o aktuálně připojeném uživateli.
Níže uvedený kód to ukazuje:
// chat.gateway.ts
@WebSocketGateway()
vývoznítřídaChatová bránanářadíOnGatewayConnection{
@WebSocketServer()
server: Server;konstruktér(soukromá služba chatu: služba chatu) {}
asynchronní handleConnection (zásuvka: Socket) {
čekattento.chatsService.getUserFromSocket (socket)
}@Správa k odběru('poslat zprávu')
asynchronní listenForMessages(@MessageBody() message: string, @ConnectedSocket() socket: Socket) {
konst uživatel = čekattento.chatsService.getUserFromSocket (socket)
tento.server.sockets.emit('receive_message', {
zpráva,
uživatel
});
}
}
Můžete odkazovat na soubory zapojené do autentizačního systému výše v úložiště GitHub zobrazit kompletní kódy (včetně importů), abyste lépe porozuměli implementaci.
Trvalé chaty do databáze
Aby uživatelé viděli svou historii zpráv, potřebujete schéma pro ukládání zpráv. Vytvořte nový soubor s názvem message.schema.ts a vložte do něj níže uvedený kód (nezapomeňte importovat svůj uživatelské schéma nebo se podívejte na úložiště).
import { Uživatel } z'./../users/schemas/user.schema';
import { Prop, Schema, SchemaFactory } z"@nestjs/mongoose";
import mongoose, { dokument } z"mangusta";vývozní zadejte MessageDocument = Zpráva a dokument;
@Schéma({
toJSON: {
getry: skutečný,
virtuály: skutečný,
},
časová razítka: skutečný,
})
vývoznítřídaZpráva{
@Podpěra({ Požadované: skutečný, unikátní: skutečný })
zpráva: řetězec@Podpěra({ typ: mangusta. Schéma. Typy. ObjectId, ref: 'Uživatel' })
uživatel: Uživatel
}konst MessageSchema = SchemaFactory.createForClass (zpráva)
vývozní { MessageSchema };
Níže je implementace služeb pro vytvoření nové zprávy a získání všech zpráv chats.service.ts.
import { Message, MessageDocument } z'./message.schema';
import { Zásuvka } z'socket.io';
import { AuthService } z'./../auth/auth.service';
import { Injekční } z'@nestjs/common';
import { WsException } z'@nestjs/websockets';
import { InjectModel } z'@nestjs/mongoose';
import { Modelka } z'mangusta';
import { MessageDto } z'./dto/message.dto';
@Injekční()
vývoznítřídaChatsService{
konstruktér(soukromá authService: AuthService, @InjectModel (Message.name) soukromá zprávaModel: Model) {}
...
asynchronní createMessage (zpráva: MessageDto, uživatelské ID: tětiva) {
konst nová zpráva = Novýtento.messageModel({...zpráva, userId})
čekat newMessage.save
vrátit se nová zpráva
}
asynchronní getAllMessages() {
vrátit setento.messageModel.find().populate('uživatel')
}
}
The ZprávaDto je implementován v a message.dto.ts soubor v dto složku v chaty adresář. Najdete ho také v úložišti.
Musíte přidat zpráva model a schéma do seznamu importů v chats.module.ts.
import { Message, MessageSchema } z'./message.schema';
import { Modul } z'@nestjs/common';
import { Chat Gateway } z'./chats.gateway';
import { ChatsService } z'./chats.service';
import { MongooseModule } z'@nestjs/mongoose';
@Modul({
importuje: [MongooseModule.forFeature([
{ název: Message.name, schéma: MessageSchema }
])],
ovladače: [],
poskytovatelé: [ChatsService, ChatGateway]
})
vývoznítřídaChatsModule{}
Konečně, get_all_messages obsluha událostí je přidána do Chatová brána třída v chat.gateway.ts jak je vidět v následujícím kódu:
// import...
@WebSocketGateway()
vývoznítřídaChatová bránanářadíOnGatewayConnection{
...@Správa k odběru('get_all_messages')
asynchronní getAllMessages(@ConnectedSocket() socket: Socket) {čekattento.chatsService.getUserFromSocket (socket)
konst zprávy = čekattento.chatsService.getAllMessages()tento.server.sockets.emit('receive_message', zprávy);
vrátit se zprávy
}
}
Když připojený klient (uživatel) vysílá get_all_messages všechny jejich zprávy budou načteny, a když se vysílají poslat zprávu, vytvoří se zpráva a uloží se do databáze a poté se odešle všem ostatním připojeným klientům.
Jakmile provedete všechny výše uvedené kroky, můžete aplikaci začít používat npm spuštění spuštění: deva otestujte jej pomocí klienta WebSocket, jako je Postman.
Vytváření aplikací v reálném čase pomocí NestJS
Přestože existují i jiné technologie pro budování systémů v reálném čase, WebSockets jsou velmi oblíbené a v mnoha případech snadno implementovatelné a jsou tou nejlepší volbou pro chatovací aplikace.
Aplikace v reálném čase se neomezují pouze na chatovací aplikace, další příklady zahrnují streamování videa nebo aplikace pro volání a živé aplikace počasí a NestJS poskytuje skvělé nástroje pro vytváření v reálném čase aplikace.