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:
parent
9f8fbd181f
commit
b841addd78
@ -1,7 +1,7 @@
|
|||||||
import { IncomingMessage, ServerResponse } from "node:http";
|
import { IncomingMessage, ServerResponse } from "node:http";
|
||||||
|
|
||||||
export class Serializer {
|
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");
|
throw new Error("Should be extended and overrode");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,13 +16,13 @@ export class ImageRouter {
|
|||||||
this.imageRouteService.addRoute(key, valueToAdd);
|
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
|
// remove file extension
|
||||||
const url = this.vfs.stripExtension(req.url);
|
const url = this.vfs.stripExtension(req.url);
|
||||||
|
|
||||||
// send image
|
// send image
|
||||||
if (this.imageRouteService.existsByKey(url)) {
|
if (this.imageRouteService.existsByKey(url)) {
|
||||||
this.httpFileUtil.sendFile(resp, this.imageRouteService.getByKey(url));
|
await this.httpFileUtil.sendFileAsync(resp, this.imageRouteService.getByKey(url));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ export class BundleSerializer extends Serializer {
|
|||||||
super();
|
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 key = decodeURI(req.url.split("/bundle/")[1]);
|
||||||
const bundle = this.bundleLoader.getBundle(key);
|
const bundle = this.bundleLoader.getBundle(key);
|
||||||
if (!bundle) {
|
if (!bundle) {
|
||||||
@ -29,7 +29,7 @@ export class BundleSerializer extends Serializer {
|
|||||||
return;
|
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 {
|
public override canHandle(route: string): boolean {
|
||||||
|
@ -9,8 +9,8 @@ export class ImageSerializer extends Serializer {
|
|||||||
super();
|
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> {
|
||||||
this.imageRouter.sendImage(sessionID, req, resp, body);
|
await this.imageRouter.sendImage(sessionID, req, resp, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override canHandle(route: string): boolean {
|
public override canHandle(route: string): boolean {
|
||||||
|
@ -15,7 +15,7 @@ export class NotifySerializer extends Serializer {
|
|||||||
super();
|
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 splittedUrl = req.url.split("/");
|
||||||
const tmpSessionID = splittedUrl[splittedUrl.length - 1].split("?last_id")[0];
|
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
|
* 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.
|
* be sent to client as NEWLINE separated strings... yup.
|
||||||
*/
|
*/
|
||||||
this.notifierController
|
await this.notifierController
|
||||||
.notifyAsync(tmpSessionID)
|
.notifyAsync(tmpSessionID)
|
||||||
.then((messages: any) => messages.map((message: any) => this.jsonUtil.serialize(message)).join("\n"))
|
.then((messages: any) => messages.map((message: any) => this.jsonUtil.serialize(message)).join("\n"))
|
||||||
.then((text) => this.httpServerHelper.sendTextJson(resp, text));
|
.then((text) => this.httpServerHelper.sendTextJson(resp, text));
|
||||||
|
@ -107,7 +107,7 @@ export class SptHttpListener implements IHttpListener {
|
|||||||
// Not debug, minority of requests need a serializer to do the job (IMAGE/BUNDLE/NOTIFY)
|
// Not debug, minority of requests need a serializer to do the job (IMAGE/BUNDLE/NOTIFY)
|
||||||
const serialiser = this.serializers.find((x) => x.canHandle(output));
|
const serialiser = this.serializers.find((x) => x.canHandle(output));
|
||||||
if (serialiser) {
|
if (serialiser) {
|
||||||
serialiser.serialize(sessionID, req, resp, bodyInfo);
|
await serialiser.serialize(sessionID, req, resp, bodyInfo);
|
||||||
} else {
|
} else {
|
||||||
// No serializer can handle the request (majority of requests dont), zlib the output and send response back
|
// No serializer can handle the request (majority of requests dont), zlib the output and send response back
|
||||||
await this.sendZlibJson(resp, output, sessionID);
|
await this.sendZlibJson(resp, output, sessionID);
|
||||||
|
@ -2,21 +2,20 @@ import fs from "node:fs";
|
|||||||
import { ServerResponse } from "node:http";
|
import { ServerResponse } from "node:http";
|
||||||
import { HttpServerHelper } from "@spt/helpers/HttpServerHelper";
|
import { HttpServerHelper } from "@spt/helpers/HttpServerHelper";
|
||||||
import { inject, injectable } from "tsyringe";
|
import { inject, injectable } from "tsyringe";
|
||||||
|
import { pipeline } from 'stream/promises';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class HttpFileUtil {
|
export class HttpFileUtil {
|
||||||
constructor(@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper) {}
|
constructor(@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper) {}
|
||||||
|
|
||||||
public sendFile(resp: ServerResponse, filePath: string): void {
|
public async sendFileAsync(resp: ServerResponse, filePath: string): Promise<void> {
|
||||||
const pathSlic = filePath.split("/");
|
const pathSlice = filePath.split("/");
|
||||||
const type =
|
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");
|
this.httpServerHelper.getMimeText("txt");
|
||||||
const fileStream = fs.createReadStream(filePath);
|
|
||||||
|
|
||||||
fileStream.on("open", () => {
|
resp.setHeader("Content-Type", type);
|
||||||
resp.setHeader("Content-Type", type);
|
|
||||||
fileStream.pipe(resp);
|
await pipeline(fs.createReadStream(filePath), resp);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user