UNPKG

@x5e/gink

Version:

an eventually consistent database

73 lines 3.27 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RoutingServer = void 0; const Database_1 = require("./Database"); const RoutingServerInstance_1 = require("./RoutingServerInstance"); const utils_1 = require("./utils"); const fs_1 = require("fs"); const path_1 = require("path"); const Listener_1 = require("./Listener"); /** * A class that listens on a port, and then serves either static content over HTTP(S) * or opens websocket connections and hands it off to the appropriate RoutingServerInstance. * * The user passes in a dataFilesRoot, which should be a writable directory on the local system. * The RoutingServer will create a RoutingServerInstance for each file/requested resource. */ class RoutingServer { constructor(args) { this.instances = new Map(); const logger = (this.logger = args.logger || (() => null)); this.authFunc = args.authFunc || (() => true); this.identity = args.identity; this.dataFilesRoot = args.dataFilesRoot; (0, utils_1.ensure)((0, fs_1.existsSync)(this.dataFilesRoot), "data root not there"); this.listener = new Listener_1.Listener(Object.assign({ requestHandler: this.onRequest.bind(this), logger }, args)); this.ready = this.listener.ready.then(() => logger(`RoutingServer ready`)); } /** * * @param path absolute path to the args.data_file * @returns a promise of an instance that will manage that file */ getInstance(path) { // Note: can't afford to await for the instance to be ready, or you'll miss the greeting. let instance = this.instances.get(path); if (!instance) { instance = new RoutingServerInstance_1.RoutingServerInstance(path, this.identity, this.logger); this.instances.set(path, instance); } return instance; } /** * Decides whether to accept the request, and if it does, hands it off * to a database instance to manage that connection to the specified resource. * @param request contains information passed from the websocket server */ async onRequest(request) { let protocol = null; let token = null; if (request.requestedProtocols.length) { for (const protocol of request.requestedProtocols) { if (protocol.match(/0x.*/)) { token = (0, utils_1.decodeToken)(protocol); } } if (request.requestedProtocols.includes(Database_1.Database.PROTOCOL)) protocol = Database_1.Database.PROTOCOL; else return request.reject(400, "bad protocol"); } if ((0, utils_1.isPathDangerous)(request.resource)) return request.reject(400, "bad path"); if (!this.authFunc(token)) { return request.reject(401, "authentication failed"); } const connection = request.accept(protocol, request.origin); const instanceKey = (0, path_1.join)(this.dataFilesRoot, request.resource); const instance = this.getInstance(instanceKey); await instance.onConnection(connection); } } exports.RoutingServer = RoutingServer; //# sourceMappingURL=RoutingServer.js.map