Sužinokite, kaip sukurti realiojo laiko pokalbių API, išnaudojant WebSockets galią naudojant NestJS.
NestJS yra populiari sistema, skirta serverio programoms kurti naudojant Node.js. Palaikydamas „WebSockets“, „NestJS“ puikiai tinka kurti realiojo laiko pokalbių programas.
Taigi, kas yra „WebSockets“ ir kaip „NestJS“ galite sukurti pokalbių programą realiuoju laiku?
Kas yra „WebSockets“?
WebSockets yra nuolatinio, realaus laiko ir dvipusio kliento ir serverio ryšio protokolas.
Skirtingai nuo HTTP, kai ryšys uždaromas, kai baigiamas užklausos ciklas tarp kliento ir serverio, „WebSocket“ ryšys yra atidarytas ir neužsijungia net po to, kai buvo grąžintas atsakymas į a prašymas.
Toliau pateiktame paveikslėlyje parodyta, kaip veikia „WebSocket“ ryšys tarp serverio ir kliento:
Norėdami užmegzti dvikryptį ryšį, klientas serveriui siunčia „WebSocket“ rankos paspaudimo užklausą. Užklausos antraštėse yra saugus WebSocket raktas (Sec-WebSocket-Key), ir an Atnaujinimas: WebSocket antraštė, kuri kartu su
Ryšys: Atnaujinkite antraštė nurodo serveriui atnaujinti protokolą iš HTTP į WebSocket ir palaikyti ryšį atvirą. Mokymasis apie WebSockets JavaScript padeda dar geriau suprasti sąvoką.Realiojo laiko pokalbių API kūrimas naudojant NestJS WebSocket modulį
Node.js pateikia du pagrindinius „WebSockets“ diegimus. Pirmasis yra ws kuri įgyvendina plikas WebSockets. O antrasis yra lizdas.io, kuri suteikia daugiau aukšto lygio funkcijų.
„NestJS“ turi abiejų modulių lizdas.io ir ws. Šiame straipsnyje naudojama lizdas.io pavyzdinės programos WebSocket funkcijų modulis.
Šiame projekte naudojamas kodas yra prieinamas a GitHub saugykla. Rekomenduojama jį klonuoti lokaliai, kad geriau suprastumėte katalogo struktūrą ir pamatytumėte, kaip visi kodai sąveikauja vienas su kitu.
Projekto sąranka ir diegimas
Atidarykite terminalą ir sugeneruokite naują „NestJS“ programą naudodami lizdas naujas komandą (pvz. Nest nauja pokalbių programa). Komanda sukuria naują katalogą, kuriame yra projekto failai. Dabar esate pasiruošę pradėti kūrimo procesą.
Nustatykite MongoDB ryšį
Norėdami išsaugoti pokalbių pranešimus programoje, jums reikia duomenų bazės. Šiame straipsnyje naudojami MongoDB duomenų bazė mūsų NestJS programai, o lengviausias būdas bėgti yra debesyje nustatykite MongoDB klasterį ir gaukite savo MongoDB URL. Nukopijuokite URL ir išsaugokite jį kaip MONGO_URI kintamasis jūsų .env failą.
Jums taip pat prireiks Mongoose vėliau, kai pateiksite užklausas MongoDB. Įdiekite jį paleisdami npm įdiegti mongoose savo terminale.
Viduje src aplanką, sukurkite failą pavadinimu mongo.config.ts ir įklijuokite į jį šį kodą.
importuoti {registruotis kaip } iš„@nestjs/config“;
/**
* Mongo duomenų bazės ryšio konfigūracija
*/
eksportuotinumatytas registerAs("mongodb", () => {
konst { MONGO_URI } = procesas.env; // iš .env failo
grąžinti {
uri:`${MONGO_URI}`,
};
});
Jūsų projektas pagrindinis.ts failas turėtų atrodyti taip:
importuoti { NestFactory } iš„@nestjs/core“;
importuoti { AppModule } iš„./app.module“;
importuoti * kaip cookieParser iš"slapukų analizatorius"
importuoti šalmas iš'šalmas'
importuoti { Logger, ValidationPipe } iš„@nestjs/common“;
importuoti { setupSwagger } iš„./utils/swagger“;
importuoti { HttpExceptionFilter } iš„./filters/http-exception.filter“;asyncfunkcijabootstrap() {
konst programa = laukti NestFactory.create (AppModule, { kors: tiesa });
app.enableCors({
kilmė: '*',
kredencialai: tiesa
})
app.use (cookieParser())
app.useGlobalPipes(
naujas ValidationPipe({
baltas sąrašas: tiesa
})
)
konst medkirtys = naujas Logger("Pagrindinis")app.setGlobalPrefix(„api/v1“)
app.useGlobalFilters(naujas HttpExceptionFilter());setupSwagger (programa)
app.use (helmet())laukti app.listen (AppModule.port)
// žurnalo dokumentai
konst baseUrl = AppModule.getBaseUrl (programa)
konst url = `http://${baseUrl}:${AppModule.port}`
logger.log(„API dokumentacija pasiekiama adresu ${url}/docs`);
}
bootstrap ();
Pokalbių modulio kūrimas
Norėdami pradėti naudotis realiojo laiko pokalbių funkcija, pirmiausia turite įdiegti „NestJS WebSockets“ paketus. Tai galima padaryti paleidus šią komandą terminale.
npm įdiegti @nestjs/websockets @nestjs/platform-socket.io @types/socket.io
Įdiegę paketus, turite sugeneruoti pokalbių modulį vykdydami šias komandas
Nest g modulio pokalbiai
nest g valdiklio pokalbiai
„Nest g“ paslaugų pokalbiai
Sukūrus modulį, kitas žingsnis yra sukurti „WebSockets“ ryšį „NestJS“. Sukurti chat.gateway.ts failas viduje pokalbiai aplanką, čia yra įdiegtas šliuzas, kuris siunčia ir gauna pranešimus.
Įklijuokite šį kodą į chat.gateway.ts.
importuoti {
Message Body,
Prenumeruoti pranešimą,
„WebSocketGateway“,
WebSocketServer,
} iš„@nestjs/websockets“;
importuoti { Serveris } iš„socket.io“;
@WebSocketGateway()
eksportuotiklasė„ChatGateway“.{
@WebSocketServer()
serveris: Serveris;
// klausykite send_message įvykių
@SubscribeMessage('Siųsti žinutę')
listenForMessages(@MessageBody() pranešimas: string) {
tai.server.sockets.emit('gauti_pranešimą', žinutė);
}
}
Prisijungusių vartotojų autentifikavimas
Autentifikavimas yra esminė žiniatinklio programų dalis, ji nesiskiria ir pokalbių programoms. Funkcija, skirta autentifikuoti kliento ryšius su lizdu, yra chats.service.ts kaip parodyta čia:
@Injekcinis()
eksportuotiklasėPokalbių paslauga{
konstruktorius(privati authService: AuthService) {}async getUserFromSocket (socket: Socket) {
leisti auth_token = socket.handshake.headers.authorization;
// gauti patį žetoną be "Nešėjo"
auth_token = auth_token.split(' ')[1];konst vartotojas = tai.authService.getUserFromAuthenticationToken(
auth_token
);
jeigu (!Vartotojas) {
mestinaujas WsException(„Netinkami kredencialai“.);
}
grąžinti Vartotojas;
}
}
The getUserFromSocket metodo naudojimo getUserFromAuthenticationToken Norėdami gauti šiuo metu prisijungusį vartotoją iš JWT prieigos rakto, ištraukdami nešiklio prieigos raktą. The getUserFromAuthenticationToken funkcija yra įdiegta auth.service.ts failas, kaip parodyta čia:
viešas async getUserFromAuthenticationToken (token: string) {
konst naudingoji apkrova: JwtPayload = tai.jwtService.verify (token, {
paslaptis: tai.configService.get(„JWT_ACCESS_TOKEN_SECRET“),
});konst userId = payload.sub
jeigu (Vartotojo ID) {
grąžintitai.usersService.findById (userId);
}
}
Dabartinis lizdas perduodamas kaip parametras getUserFromSocket kai rankenaPrijungimas metodas „ChatGateway“. įgyvendina OnGatewayConnection sąsaja. Tai leidžia gauti pranešimus ir informaciją apie šiuo metu prisijungusį vartotoją.
Žemiau pateiktas kodas parodo tai:
// chat.gateway.ts
@WebSocketGateway()
eksportuotiklasė„ChatGateway“.padargaiOnGatewayConnection{
@WebSocketServer()
serveris: Serveris;konstruktorius(privatūs pokalbiaiService: ChatsService) {}
async handConnection (socket: Socket) {
lauktitai.chatsService.getUserFromSocket (socket)
}@SubscribeMessage('Siųsti žinutę')
async listenForMessages(@MessageBody() pranešimas: eilutė, @ConnectedSocket() lizdas: Socket) {
konst vartotojas = lauktitai.chatsService.getUserFromSocket (socket)
tai.server.sockets.emit('gauti_pranešimą', {
žinutė,
Vartotojas
});
}
}
Galite nurodyti failus, susijusius su autentifikavimo sistema, aukščiau esančiame GitHub saugykla kad pamatytumėte visus kodus (įskaitant importus), kad geriau suprastumėte įgyvendinimą.
Nuolatiniai pokalbiai su duomenų baze
Kad vartotojai matytų savo pranešimų istoriją, jums reikia pranešimų saugojimo schemos. Sukurkite naują failą pavadinimu message.schema.ts ir įklijuokite žemiau esantį kodą (nepamirškite importuoti savo vartotojo schema arba patikrinkite saugyklą).
importuoti { Vartotojas } iš„./../users/schemas/user.schema“;
importuoti { Prop, Schema, SchemaFactory } iš„@nestjs/mongoose“;
importuoti mangustas, { dokumentas } iš"mangustas";eksportuoti tipo MessageDocument = Pranešimas ir dokumentas;
@Schema({
į JSON: {
gaudytojai: tiesa,
virtualiai: tiesa,
},
laiko žymos: tiesa,
})
eksportuotiklasėPranešimas{
@Prop({ reikalaujama: tiesa, Unikalus: tiesa })
žinutė: eilutė@Prop({ tipo: mangustas. Schema. Tipai. Objekto ID, ref: 'Vartotojas' })
vartotojas: Vartotojas
}konst MessageSchema = SchemaFactory.createForClass (pranešimas)
eksportuoti { MessageSchema };
Žemiau pateikiamos paslaugos, skirtos sukurti naują pranešimą ir gauti visus pranešimus chats.service.ts.
importuoti { Message, MessageDocument } iš'./message.schema';
importuoti { Lizdas } iš„socket.io“;
importuoti { AuthService } iš„./../auth/auth.service“;
importuoti { Injekcinis } iš„@nestjs/common“;
importuoti { WsException } iš„@nestjs/websockets“;
importuoti { InjectModel } iš„@nestjs/mangoose“;
importuoti { Modelis } iš"mangustas";
importuoti { MessageDto } iš„./dto/message.dto“;
@Injekcinis()
eksportuotiklasėPokalbių paslauga{
konstruktorius(privatus authService: AuthService, @InjectModel (Message.name) privatus pranešimasModelis: modelis) {}
...
async CreateMessage (pranešimas: MessageDto, Vartotojo ID: string) {
konst naujas pranešimas = naujastai.messageModel({...message, userId})
laukti naujas Pranešimas.išsaugoti
grąžinti nauja žinutė
}
async getAllMessages() {
grąžintitai.messageModel.find().populate('Vartotojas')
}
}
The MessageDto yra įgyvendinamas a message.dto.ts failą dto aplanke esančiame pokalbiai katalogas. Jį taip pat galite rasti saugykloje.
Turite pridėti žinutę modelį ir schemą į importuojamų prekių sąrašą chats.module.ts.
importuoti { Pranešimas, pranešimų schema } iš'./message.schema';
importuoti { Modulis } iš„@nestjs/common“;
importuoti { Chat Gateway } iš'./chats.gateway';
importuoti { Pokalbių paslauga } iš'./chats.service';
importuoti { MongooseModule } iš„@nestjs/mangoose“;
@Module({
importai: [MongooseModule.forFeature([
{ vardas: Message.name, schema: MessageSchema }
])],
valdikliai: [],
teikėjai: [ChatsService, ChatGateway]
})
eksportuotiklasėPokalbių modulis{}
Galiausiai, get_all_messages įvykių tvarkytuvas pridedamas prie „ChatGateway“. klasėje chat.gateway.ts kaip matyti šiame kode:
// importas...
@WebSocketGateway()
eksportuotiklasė„ChatGateway“.padargaiOnGatewayConnection{
...@SubscribeMessage(„gauti_visus_pranešimus“)
async getAllMessages(@ConnectedSocket() lizdas: Socket) {lauktitai.chatsService.getUserFromSocket (socket)
konst žinutės = lauktitai.chatsService.getAllMessages()tai.server.sockets.emit('gauti_pranešimą', žinutės);
grąžinti žinutes
}
}
Kai prijungtas klientas (vartotojas) skleidžia get_all_messages įvykį, visi jų pranešimai bus nuskaityti ir kada jie bus išsiųsti Siųsti žinutę, pranešimas sukuriamas ir saugomas duomenų bazėje, o tada siunčiamas visiems kitiems prijungtiems klientams.
Atlikę visus aukščiau nurodytus veiksmus, galite pradėti savo programą naudodami npm paleisties pradžia: dev, ir išbandykite jį naudodami „WebSocket“ klientą, pvz., „Postman“.
Realiųjų programų kūrimas naudojant „NestJS“.
Nors yra ir kitų realaus laiko sistemų kūrimo technologijų, „WebSockets“ yra labai populiarios ir daugeliu atvejų lengvai įdiegiamos, be to, jos yra geriausias pasirinkimas pokalbių programoms.
Realaus laiko programos neapsiriboja tik pokalbių programomis, kiti pavyzdžiai apima vaizdo transliaciją arba skambinimo programas ir tiesiogines orų programas, o „NestJS“ suteikia puikius įrankius kuriant realiuoju laiku programėlės.