Formatting for servers.
This commit is contained in:
parent
b90fb8c8b9
commit
ca9ab9bcc8
@ -7,7 +7,7 @@ import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { VFS } from "@spt-aki/utils/VFS";
|
||||
|
||||
@injectable()
|
||||
export class ConfigServer
|
||||
export class ConfigServer
|
||||
{
|
||||
protected configs: Record<string, any> = {};
|
||||
protected readonly acceptableFileExtensions: string[] = ["json", "jsonc"];
|
||||
@ -15,7 +15,7 @@ export class ConfigServer
|
||||
constructor(
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
@inject("VFS") protected vfs: VFS,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
)
|
||||
{
|
||||
this.initialize();
|
||||
@ -36,9 +36,9 @@ export class ConfigServer
|
||||
this.logger.debug("Importing configs...");
|
||||
|
||||
// Get all filepaths
|
||||
const filepath = (globalThis.G_RELEASE_CONFIGURATION)
|
||||
? "Aki_Data/Server/configs/"
|
||||
: "./assets/configs/";
|
||||
const filepath = (globalThis.G_RELEASE_CONFIGURATION) ?
|
||||
"Aki_Data/Server/configs/" :
|
||||
"./assets/configs/";
|
||||
const files = this.vfs.getFiles(filepath);
|
||||
|
||||
// Add file content to result
|
||||
@ -48,10 +48,13 @@ export class ConfigServer
|
||||
{
|
||||
const fileName = this.vfs.stripExtension(file);
|
||||
const filePathAndName = `${filepath}${file}`;
|
||||
this.configs[`aki-${fileName}`] = this.jsonUtil.deserializeJsonC<any>(this.vfs.readFile(filePathAndName), filePathAndName);
|
||||
this.configs[`aki-${fileName}`] = this.jsonUtil.deserializeJsonC<any>(
|
||||
this.vfs.readFile(filePathAndName),
|
||||
filePathAndName,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.logger.info(`Commit hash: ${(this.configs[ConfigTypes.CORE] as ICoreConfig).commit || "DEBUG"}`);
|
||||
this.logger.info(`Build date: ${(this.configs[ConfigTypes.CORE] as ICoreConfig).buildTime || "DEBUG"}`);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ export class DatabaseServer
|
||||
traders: undefined,
|
||||
globals: undefined,
|
||||
server: undefined,
|
||||
settings: undefined
|
||||
settings: undefined,
|
||||
};
|
||||
|
||||
public getTables(): IDatabaseTables
|
||||
|
@ -1,5 +1,5 @@
|
||||
import http, { IncomingMessage, ServerResponse } from "node:http";
|
||||
import { inject, injectAll, injectable } from "tsyringe";
|
||||
import { inject, injectable, injectAll } from "tsyringe";
|
||||
|
||||
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
|
||||
import { ContextVariableType } from "@spt-aki/context/ContextVariableType";
|
||||
@ -9,8 +9,8 @@ import { IHttpConfig } from "@spt-aki/models/spt/config/IHttpConfig";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { WebSocketServer } from "@spt-aki/servers/WebSocketServer";
|
||||
import { IHttpListener } from "@spt-aki/servers/http/IHttpListener";
|
||||
import { WebSocketServer } from "@spt-aki/servers/WebSocketServer";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
|
||||
@injectable()
|
||||
@ -26,7 +26,7 @@ export class HttpServer
|
||||
@injectAll("HttpListener") protected httpListeners: IHttpListener[],
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("ApplicationContext") protected applicationContext: ApplicationContext,
|
||||
@inject("WebSocketServer") protected webSocketServer: WebSocketServer
|
||||
@inject("WebSocketServer") protected webSocketServer: WebSocketServer,
|
||||
)
|
||||
{
|
||||
this.httpConfig = this.configServer.getConfig(ConfigTypes.HTTP);
|
||||
@ -49,7 +49,9 @@ export class HttpServer
|
||||
/* Config server to listen on a port */
|
||||
httpServer.listen(this.httpConfig.port, this.httpConfig.ip, () =>
|
||||
{
|
||||
this.logger.success(this.localisationService.getText("started_webserver_success", this.httpServerHelper.getBackendUrl()));
|
||||
this.logger.success(
|
||||
this.localisationService.getText("started_webserver_success", this.httpServerHelper.getBackendUrl()),
|
||||
);
|
||||
});
|
||||
|
||||
httpServer.on("error", (e: any) =>
|
||||
@ -76,11 +78,11 @@ export class HttpServer
|
||||
this.applicationContext.addValue(ContextVariableType.SESSION_ID, sessionId);
|
||||
|
||||
// http.json logRequests boolean option to allow the user/server to choose to not log requests
|
||||
if (this.httpConfig.logRequests)
|
||||
if (this.httpConfig.logRequests)
|
||||
{
|
||||
this.logger.info(this.localisationService.getText("client_request", req.url));
|
||||
}
|
||||
|
||||
|
||||
for (const listener of this.httpListeners)
|
||||
{
|
||||
if (listener.canHandle(sessionId, req))
|
||||
@ -108,4 +110,4 @@ export class HttpServer
|
||||
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ export class RagfairServer
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("TraderHelper") protected traderHelper: TraderHelper,
|
||||
@inject("TraderAssortHelper") protected traderAssortHelper: TraderAssortHelper,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
)
|
||||
{
|
||||
this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR);
|
||||
@ -79,7 +79,7 @@ export class RagfairServer
|
||||
*/
|
||||
protected getUpdateableTraders(): string[]
|
||||
{
|
||||
return Object.keys(this.ragfairConfig.traders).filter(x => this.ragfairConfig.traders[x]);
|
||||
return Object.keys(this.ragfairConfig.traders).filter((x) => this.ragfairConfig.traders[x]);
|
||||
}
|
||||
|
||||
public getAllCategories(): Record<string, number>
|
||||
@ -99,7 +99,7 @@ export class RagfairServer
|
||||
public hideOffer(offerId: string): void
|
||||
{
|
||||
const offers = this.ragfairOfferService.getOffers();
|
||||
const offer = offers.find(x => x._id === offerId);
|
||||
const offer = offers.find((x) => x._id === offerId);
|
||||
|
||||
if (!offer)
|
||||
{
|
||||
@ -135,4 +135,4 @@ export class RagfairServer
|
||||
{
|
||||
this.ragfairOfferService.addPlayerOffers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,9 +23,9 @@ export class SaveServer
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("HashUtil") protected hashUtil: HashUtil,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("WinstonLogger") protected logger: ILogger
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
)
|
||||
{ }
|
||||
{}
|
||||
|
||||
/**
|
||||
* Add callback to occur prior to saving profile changes
|
||||
@ -144,7 +144,7 @@ export class SaveServer
|
||||
|
||||
this.profiles[profileInfo.id] = {
|
||||
info: profileInfo,
|
||||
characters: { pmc: {}, scav: {}}
|
||||
characters: {pmc: {}, scav: {}},
|
||||
};
|
||||
}
|
||||
|
||||
@ -180,14 +180,14 @@ export class SaveServer
|
||||
}
|
||||
|
||||
/**
|
||||
* Save changes from in-memory profile to user/profiles json
|
||||
* Save changes from in-memory profile to user/profiles json
|
||||
* Execute onBeforeSaveCallbacks callbacks prior to being saved to json
|
||||
* @param sessionID profile id (user/profiles/id.json)
|
||||
*/
|
||||
public saveProfile(sessionID: string): void
|
||||
{
|
||||
const filePath = `${this.profileFilepath}${sessionID}.json`;
|
||||
|
||||
|
||||
// run callbacks
|
||||
for (const callback in this.onBeforeSaveCallbacks)
|
||||
{
|
||||
@ -198,14 +198,14 @@ export class SaveServer
|
||||
}
|
||||
catch (error)
|
||||
{
|
||||
this.logger.error(this.localisationService.getText("profile_save_callback_error", { callback, error }));
|
||||
this.logger.error(this.localisationService.getText("profile_save_callback_error", {callback, error}));
|
||||
this.profiles[sessionID] = previous;
|
||||
}
|
||||
}
|
||||
|
||||
const jsonProfile = this.jsonUtil.serialize(this.profiles[sessionID], true);
|
||||
const fmd5 = this.hashUtil.generateMd5ForData(jsonProfile);
|
||||
if (typeof(this.saveMd5[sessionID]) !== "string" || this.saveMd5[sessionID] !== fmd5)
|
||||
if (typeof (this.saveMd5[sessionID]) !== "string" || this.saveMd5[sessionID] !== fmd5)
|
||||
{
|
||||
this.saveMd5[sessionID] = String(fmd5);
|
||||
// save profile to disk
|
||||
|
@ -13,17 +13,16 @@ import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
|
||||
@injectable()
|
||||
export class WebSocketServer
|
||||
export class WebSocketServer
|
||||
{
|
||||
|
||||
constructor(
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
@inject("RandomUtil") protected randomUtil: RandomUtil,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper
|
||||
)
|
||||
@inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper,
|
||||
)
|
||||
{
|
||||
this.httpConfig = this.configServer.getConfig(ConfigTypes.HTTP);
|
||||
}
|
||||
@ -31,22 +30,26 @@ export class WebSocketServer
|
||||
protected httpConfig: IHttpConfig;
|
||||
protected defaultNotification: INotification = {
|
||||
type: NotificationType.PING,
|
||||
eventId: "ping"
|
||||
eventId: "ping",
|
||||
};
|
||||
|
||||
protected webSockets: Record<string, WebSocket.WebSocket> = {};
|
||||
protected websocketPingHandler = null;
|
||||
|
||||
public setupWebSocket(httpServer: http.Server): void
|
||||
public setupWebSocket(httpServer: http.Server): void
|
||||
{
|
||||
const webSocketServer = new WebSocket.Server({
|
||||
server: httpServer
|
||||
server: httpServer,
|
||||
});
|
||||
|
||||
webSocketServer.addListener("listening", () =>
|
||||
webSocketServer.addListener("listening", () =>
|
||||
{
|
||||
this.logger.success(this.localisationService.getText("websocket-started", this.httpServerHelper.getWebsocketUrl()));
|
||||
this.logger.success(`${this.localisationService.getText("server_running")}, ${this.getRandomisedMessage()}!`);
|
||||
this.logger.success(
|
||||
this.localisationService.getText("websocket-started", this.httpServerHelper.getWebsocketUrl()),
|
||||
);
|
||||
this.logger.success(
|
||||
`${this.localisationService.getText("server_running")}, ${this.getRandomisedMessage()}!`,
|
||||
);
|
||||
});
|
||||
|
||||
webSocketServer.addListener("connection", this.wsOnConnection.bind(this));
|
||||
@ -72,24 +75,24 @@ export class WebSocketServer
|
||||
}
|
||||
}
|
||||
|
||||
protected getRandomisedMessage(): string
|
||||
protected getRandomisedMessage(): string
|
||||
{
|
||||
if (this.randomUtil.getInt(1, 1000) > 999)
|
||||
if (this.randomUtil.getInt(1, 1000) > 999)
|
||||
{
|
||||
return this.localisationService.getRandomTextThatMatchesPartialKey("server_start_meme_");
|
||||
}
|
||||
|
||||
return (globalThis.G_RELEASE_CONFIGURATION)
|
||||
? `${this.localisationService.getText("server_start_success")}!`
|
||||
: this.localisationService.getText("server_start_success");
|
||||
return (globalThis.G_RELEASE_CONFIGURATION) ?
|
||||
`${this.localisationService.getText("server_start_success")}!` :
|
||||
this.localisationService.getText("server_start_success");
|
||||
}
|
||||
|
||||
public isConnectionWebSocket(sessionID: string): boolean
|
||||
public isConnectionWebSocket(sessionID: string): boolean
|
||||
{
|
||||
return this.webSockets[sessionID] !== undefined && this.webSockets[sessionID].readyState === WebSocket.OPEN;
|
||||
}
|
||||
|
||||
protected wsOnConnection(ws: WebSocket.WebSocket, req: IncomingMessage): void
|
||||
protected wsOnConnection(ws: WebSocket.WebSocket, req: IncomingMessage): void
|
||||
{
|
||||
// Strip request and break it into sections
|
||||
const splitUrl = req.url.substring(0, req.url.indexOf("?")).split("/");
|
||||
@ -99,27 +102,27 @@ export class WebSocketServer
|
||||
|
||||
const logger = this.logger;
|
||||
const msgToLog = this.localisationService.getText("websocket-received_message", sessionID);
|
||||
ws.on("message", function message(msg)
|
||||
ws.on("message", function message(msg)
|
||||
{
|
||||
logger.info(`${msgToLog} ${msg}`);
|
||||
});
|
||||
|
||||
this.webSockets[sessionID] = ws;
|
||||
|
||||
if (this.websocketPingHandler)
|
||||
if (this.websocketPingHandler)
|
||||
{
|
||||
clearInterval(this.websocketPingHandler);
|
||||
}
|
||||
|
||||
this.websocketPingHandler = setInterval(() =>
|
||||
this.websocketPingHandler = setInterval(() =>
|
||||
{
|
||||
this.logger.debug(this.localisationService.getText("websocket-pinging_player", sessionID));
|
||||
|
||||
if (ws.readyState === WebSocket.OPEN)
|
||||
if (ws.readyState === WebSocket.OPEN)
|
||||
{
|
||||
ws.send(this.jsonUtil.serialize(this.defaultNotification));
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
this.logger.debug(this.localisationService.getText("websocket-socket_lost_deleting_handle"));
|
||||
clearInterval(this.websocketPingHandler);
|
||||
@ -127,4 +130,4 @@ export class WebSocketServer
|
||||
}
|
||||
}, this.httpConfig.webSocketPingDelayMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from "node:http";
|
||||
import zlib from "node:zlib";
|
||||
import { inject, injectAll, injectable } from "tsyringe";
|
||||
import { inject, injectable, injectAll } from "tsyringe";
|
||||
|
||||
import { Serializer } from "@spt-aki/di/Serializer";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
@ -13,7 +13,6 @@ import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
@injectable()
|
||||
export class AkiHttpListener implements IHttpListener
|
||||
{
|
||||
|
||||
constructor(
|
||||
@inject("HttpRouter") protected httpRouter: HttpRouter, // TODO: delay required
|
||||
@injectAll("Serializer") protected serializers: Serializer[],
|
||||
@ -21,7 +20,7 @@ export class AkiHttpListener implements IHttpListener
|
||||
@inject("RequestsLogger") protected requestsLogger: ILogger,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
)
|
||||
{
|
||||
}
|
||||
@ -53,7 +52,7 @@ export class AkiHttpListener implements IHttpListener
|
||||
const buffer = Buffer.alloc(requestLength);
|
||||
let written = 0;
|
||||
|
||||
req.on("data", (data: any) =>
|
||||
req.on("data", (data: any) =>
|
||||
{
|
||||
data.copy(buffer, written, 0);
|
||||
written += data.length;
|
||||
@ -96,7 +95,13 @@ export class AkiHttpListener implements IHttpListener
|
||||
* @param body Buffer
|
||||
* @param output Server generated response data
|
||||
*/
|
||||
public sendResponse(sessionID: string, req: IncomingMessage, resp: ServerResponse, body: Buffer, output: string): void
|
||||
public sendResponse(
|
||||
sessionID: string,
|
||||
req: IncomingMessage,
|
||||
resp: ServerResponse,
|
||||
body: Buffer,
|
||||
output: string,
|
||||
): void
|
||||
{
|
||||
const info = this.getBodyInfo(body);
|
||||
let handled = false;
|
||||
@ -136,9 +141,9 @@ export class AkiHttpListener implements IHttpListener
|
||||
if (globalThis.G_LOG_REQUESTS)
|
||||
{
|
||||
// Parse quest info into object
|
||||
const data = (typeof info === "object")
|
||||
? info
|
||||
: this.jsonUtil.deserialize(info);
|
||||
const data = (typeof info === "object") ?
|
||||
info :
|
||||
this.jsonUtil.deserialize(info);
|
||||
|
||||
const log = new Request(req.method, new RequestData(req.url, req.headers, data));
|
||||
this.requestsLogger.info(`REQUEST=${this.jsonUtil.serialize(log)}`);
|
||||
@ -150,32 +155,31 @@ export class AkiHttpListener implements IHttpListener
|
||||
{
|
||||
this.logger.error(this.localisationService.getText("unhandled_response", req.url));
|
||||
this.logger.info(info);
|
||||
output = <string><unknown> this.httpResponse.getBody(null, 404, `UNHANDLED RESPONSE: ${req.url}`);
|
||||
output = <string><unknown>this.httpResponse.getBody(null, 404, `UNHANDLED RESPONSE: ${req.url}`);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
protected getBodyInfo(body: Buffer, requestUrl = null): any
|
||||
protected getBodyInfo(body: Buffer, requestUrl = null): any
|
||||
{
|
||||
const text = (body) ? body.toString() : "{}";
|
||||
const info = (text) ? this.jsonUtil.deserialize<any>(text, requestUrl) : {};
|
||||
const text = body ? body.toString() : "{}";
|
||||
const info = text ? this.jsonUtil.deserialize<any>(text, requestUrl) : {};
|
||||
return info;
|
||||
}
|
||||
|
||||
public sendJson(resp: ServerResponse, output: string, sessionID: string): void
|
||||
{
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
resp.writeHead(200, "OK", { "Content-Type": "application/json", "Set-Cookie": `PHPSESSID=${sessionID}` });
|
||||
resp.writeHead(200, "OK", {"Content-Type": "application/json", "Set-Cookie": `PHPSESSID=${sessionID}`});
|
||||
resp.end(output);
|
||||
}
|
||||
|
||||
public sendZlibJson(resp: ServerResponse, output: string, sessionID: string): void
|
||||
{
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
resp.writeHead(200, "OK", { "Content-Type": "application/json", "Set-Cookie": `PHPSESSID=${sessionID}` });
|
||||
resp.writeHead(200, "OK", {"Content-Type": "application/json", "Set-Cookie": `PHPSESSID=${sessionID}`});
|
||||
zlib.deflate(output, (_, buf) => resp.end(buf));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RequestData
|
||||
@ -183,7 +187,7 @@ class RequestData
|
||||
constructor(
|
||||
public url: string,
|
||||
public headers: IncomingHttpHeaders,
|
||||
public data?: any
|
||||
public data?: any,
|
||||
)
|
||||
{}
|
||||
}
|
||||
@ -192,7 +196,7 @@ class Request
|
||||
{
|
||||
constructor(
|
||||
public type: string,
|
||||
public req: RequestData
|
||||
public req: RequestData,
|
||||
)
|
||||
{}
|
||||
}
|
||||
@ -201,7 +205,7 @@ class Response
|
||||
{
|
||||
constructor(
|
||||
public type: string,
|
||||
public response: any
|
||||
public response: any,
|
||||
)
|
||||
{}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
export enum HttpMethods
|
||||
{
|
||||
export enum HttpMethods
|
||||
{
|
||||
OPTIONS = "OPTIONS",
|
||||
GET = "GET",
|
||||
POST = "POST",
|
||||
PUT = "PUT",
|
||||
PATCH = "PATCH",
|
||||
DELETE = "DELETE"
|
||||
}
|
||||
DELETE = "DELETE",
|
||||
}
|
||||
|
@ -2,6 +2,6 @@ import { IncomingMessage, ServerResponse } from "node:http";
|
||||
|
||||
export interface IHttpListener
|
||||
{
|
||||
canHandle(sessionId: string, req: IncomingMessage): boolean
|
||||
handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void
|
||||
}
|
||||
canHandle(sessionId: string, req: IncomingMessage): boolean;
|
||||
handle(sessionId: string, req: IncomingMessage, resp: ServerResponse): void;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user