Handle serializers asynchronously (!428)

In combination with my other PR handle all the serializers asynchronously too, this should almost result in a fully asynchronous sending of responses.

Reviewed-on: https://dev.sp-tarkov.com/SPT/Server/pulls/428
Co-authored-by: Archangel <jesse@archangel.wtf>
Co-committed-by: Archangel <jesse@archangel.wtf>
This commit is contained in:
Archangel 2024-11-14 17:30:22 +00:00 committed by chomp
parent 9f8fbd181f
commit b841addd78
7 changed files with 17 additions and 18 deletions

View File

@ -1,7 +1,7 @@
import { IncomingMessage, ServerResponse } from "node:http";
export class Serializer {
public serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void {
public async serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): Promise<void> {
throw new Error("Should be extended and overrode");
}

View File

@ -16,13 +16,13 @@ export class ImageRouter {
this.imageRouteService.addRoute(key, valueToAdd);
}
public sendImage(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void {
public async sendImage(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): Promise<void> {
// remove file extension
const url = this.vfs.stripExtension(req.url);
// send image
if (this.imageRouteService.existsByKey(url)) {
this.httpFileUtil.sendFile(resp, this.imageRouteService.getByKey(url));
await this.httpFileUtil.sendFileAsync(resp, this.imageRouteService.getByKey(url));
}
}

View File

@ -15,7 +15,7 @@ export class BundleSerializer extends Serializer {
super();
}
public override serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void {
public override async serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): Promise<void> {
const key = decodeURI(req.url.split("/bundle/")[1]);
const bundle = this.bundleLoader.getBundle(key);
if (!bundle) {
@ -29,7 +29,7 @@ export class BundleSerializer extends Serializer {
return;
}
this.httpFileUtil.sendFile(resp, `${bundle.modpath}/bundles/${bundle.filename}`);
await this.httpFileUtil.sendFileAsync(resp, `${bundle.modpath}/bundles/${bundle.filename}`);
}
public override canHandle(route: string): boolean {

View File

@ -9,8 +9,8 @@ export class ImageSerializer extends Serializer {
super();
}
public override serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): void {
this.imageRouter.sendImage(sessionID, req, resp, body);
public override async serialize(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: any): Promise<void> {
await this.imageRouter.sendImage(sessionID, req, resp, body);
}
public override canHandle(route: string): boolean {

View File

@ -15,7 +15,7 @@ export class NotifySerializer extends Serializer {
super();
}
public override serialize(_sessionID: string, req: IncomingMessage, resp: ServerResponse, _: any): void {
public override async serialize(_sessionID: string, req: IncomingMessage, resp: ServerResponse, _: any): Promise<void> {
const splittedUrl = req.url.split("/");
const tmpSessionID = splittedUrl[splittedUrl.length - 1].split("?last_id")[0];
@ -23,7 +23,7 @@ export class NotifySerializer extends Serializer {
* Take our array of JSON message objects and cast them to JSON strings, so that they can then
* be sent to client as NEWLINE separated strings... yup.
*/
this.notifierController
await this.notifierController
.notifyAsync(tmpSessionID)
.then((messages: any) => messages.map((message: any) => this.jsonUtil.serialize(message)).join("\n"))
.then((text) => this.httpServerHelper.sendTextJson(resp, text));

View File

@ -107,7 +107,7 @@ export class SptHttpListener implements IHttpListener {
// Not debug, minority of requests need a serializer to do the job (IMAGE/BUNDLE/NOTIFY)
const serialiser = this.serializers.find((x) => x.canHandle(output));
if (serialiser) {
serialiser.serialize(sessionID, req, resp, bodyInfo);
await serialiser.serialize(sessionID, req, resp, bodyInfo);
} else {
// No serializer can handle the request (majority of requests dont), zlib the output and send response back
await this.sendZlibJson(resp, output, sessionID);

View File

@ -2,21 +2,20 @@ import fs from "node:fs";
import { ServerResponse } from "node:http";
import { HttpServerHelper } from "@spt/helpers/HttpServerHelper";
import { inject, injectable } from "tsyringe";
import { pipeline } from 'stream/promises';
@injectable()
export class HttpFileUtil {
constructor(@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper) {}
public sendFile(resp: ServerResponse, filePath: string): void {
const pathSlic = filePath.split("/");
public async sendFileAsync(resp: ServerResponse, filePath: string): Promise<void> {
const pathSlice = filePath.split("/");
const type =
this.httpServerHelper.getMimeText(pathSlic[pathSlic.length - 1].split(".").at(-1) ?? "") ||
this.httpServerHelper.getMimeText(pathSlice[pathSlice.length - 1].split(".").at(-1) ?? "") ||
this.httpServerHelper.getMimeText("txt");
const fileStream = fs.createReadStream(filePath);
fileStream.on("open", () => {
resp.setHeader("Content-Type", type);
fileStream.pipe(resp);
});
await pipeline(fs.createReadStream(filePath), resp);
}
}