UNPKG

@selfage/service_handler

Version:

Http-based service handlers on top of expressjs.

81 lines 12.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ServiceHandler = exports.HandlerRegister = void 0; const express = require("express"); const promClient = require("prom-client"); const base_remote_call_handler_1 = require("./base_remote_call_handler"); const cors_allowed_preflight_handler_1 = require("./cors_allowed_preflight_handler"); class HandlerRegister { constructor(app, baseHandler, serviceDescriptor) { this.baseHandler = baseHandler; this.serviceDescriptor = serviceDescriptor; this.router = express.Router(); this.addedPaths = new Set(); app.use(this.serviceDescriptor.path, this.router); } add(remoteCallHandler) { if (remoteCallHandler.descriptor.service !== this.serviceDescriptor) { throw new Error(`The remote call handler ${remoteCallHandler.descriptor.name} is defined in service ${remoteCallHandler.descriptor.service.name} but being added to service ${this.serviceDescriptor.name}.`); } if (this.addedPaths.has(remoteCallHandler.descriptor.path)) { throw new Error(`The remote call handler ${remoteCallHandler.descriptor.name} is defined with a path path ${remoteCallHandler.descriptor.path} that's already registered.`); } this.addedPaths.add(remoteCallHandler.descriptor.path); this.router.post(remoteCallHandler.descriptor.path, (req, res) => this.baseHandler.handle(remoteCallHandler, req, res)); return this; } } exports.HandlerRegister = HandlerRegister; class ServiceHandler { static create(server, allowOrigin = "*") { return new ServiceHandler(server, base_remote_call_handler_1.BaseRemoteCallHandler.create(allowOrigin), cors_allowed_preflight_handler_1.CorsAllowedPreflightHandler.create(allowOrigin)); } constructor(server, baseHandler, corsAllowedPreflightHandler) { this.server = server; this.baseHandler = baseHandler; this.corsAllowedPreflightHandler = corsAllowedPreflightHandler; this.app = express(); this.server.on("request", this.app); } addCorsAllowedPreflightHandler() { this.app.options("/*", (req, res) => this.corsAllowedPreflightHandler.handle(res)); return this; } addMetricsHandler() { this.app.get("/metricsz", async (req, res) => { res.setHeader("Content-Type", "text/plain"); res.end(await promClient.register.metrics()); }); return this; } addHealthCheckHandler() { this.app.get("/healthz", (req, res) => { res.end("OK"); }); return this; } addReadinessHandler() { this.app.get("/readiness", (req, res) => { res.end("OK"); }); return this; } addHandlerRegister(serviceDescriptor) { return new HandlerRegister(this.app, this.baseHandler, serviceDescriptor); } async start(port) { await new Promise((resolve) => { this.server.listen(port, () => resolve()); }); console.log(`Server is listening on port ${port}.`); return this; } async stop() { await new Promise((resolve) => this.server.close(() => resolve())); console.log(`Server has stopped.`); // Wait for the server to close all connections. await new Promise((resolve) => setTimeout(resolve, 1000)); } } exports.ServiceHandler = ServiceHandler; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZV9oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic2VydmljZV9oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1DQUFvQztBQUdwQywwQ0FBMkM7QUFDM0MseUVBQW1FO0FBQ25FLHFGQUErRTtBQUkvRSxNQUFhLGVBQWU7SUFJMUIsWUFDRSxHQUF3QixFQUNoQixXQUFrQyxFQUNsQyxpQkFBb0M7UUFEcEMsZ0JBQVcsR0FBWCxXQUFXLENBQXVCO1FBQ2xDLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFOdEMsV0FBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUMxQixlQUFVLEdBQWdCLElBQUksR0FBRyxFQUFFLENBQUM7UUFPMUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRU0sR0FBRyxDQUFDLGlCQUE2QztRQUN0RCxJQUFJLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxPQUFPLEtBQUssSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7WUFDcEUsTUFBTSxJQUFJLEtBQUssQ0FDYiwyQkFBMkIsaUJBQWlCLENBQUMsVUFBVSxDQUFDLElBQUksMEJBQTBCLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsSUFBSSwrQkFBK0IsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksR0FBRyxDQUM3TCxDQUFDO1FBQ0osQ0FBQztRQUNELElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDM0QsTUFBTSxJQUFJLEtBQUssQ0FDYiwyQkFBMkIsaUJBQWlCLENBQUMsVUFBVSxDQUFDLElBQUksZ0NBQWdDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxJQUFJLDZCQUE2QixDQUMz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RSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDNUMsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPLENBQUMsR0FBRyxDQUFDLCtCQUErQixJQUFJLEdBQUcsQ0FBQyxDQUFDO1FBQ3BELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVNLEtBQUssQ0FBQyxJQUFJO1FBQ2YsTUFBTSxJQUFJLE9BQU8sQ0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3pFLE9BQU8sQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsQ0FBQztRQUNuQyxnREFBZ0Q7UUFDaEQsTUFBTSxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzVELENBQUM7Q0FDRjtBQXZFRCx3Q0F1RUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZXhwcmVzcyA9IHJlcXVpcmUoXCJleHByZXNzXCIpO1xuaW1wb3J0IGh0dHAgPSByZXF1aXJlKFwiaHR0cFwiKTtcbmltcG9ydCBodHRwcyA9IHJlcXVpcmUoXCJodHRwc1wiKTtcbmltcG9ydCBwcm9tQ2xpZW50ID0gcmVxdWlyZShcInByb20tY2xpZW50XCIpO1xuaW1wb3J0IHsgQmFzZVJlbW90ZUNhbGxIYW5kbGVyIH0gZnJvbSBcIi4vYmFzZV9yZW1vdGVfY2FsbF9oYW5kbGVyXCI7XG5pbXBvcnQgeyBDb3JzQWxsb3dlZFByZWZsaWdodEhhbmRsZXIgfSBmcm9tIFwiLi9jb3JzX2FsbG93ZWRfcHJlZmxpZ2h0X2hhbmRsZXJcIjtcbmltcG9ydCB7IFNlcnZpY2VEZXNjcmlwdG9yIH0gZnJvbSBcIkBzZWxmYWdlL3NlcnZpY2VfZGVzY3JpcHRvclwiO1xuaW1wb3J0IHsgUmVtb3RlQ2FsbEhhbmRsZXJJbnRlcmZhY2UgfSBmcm9tIFwiQHNlbGZhZ2Uvc2VydmljZV9kZXNjcmlwdG9yL3JlbW90ZV9jYWxsX2hhbmRsZXJfaW50ZXJmYWNlXCI7XG5cbmV4cG9ydCBjbGFzcyBIYW5kbGVyUmVnaXN0ZXIge1xuICBwcml2YXRlIHJvdXRlciA9IGV4cHJlc3MuUm91dGVyKCk7XG4gIHByaXZhdGUgYWRkZWRQYXRoczogU2V0PHN0cmluZz4gPSBuZXcgU2V0KCk7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICAgIGFwcDogZXhwcmVzcy5BcHBsaWNhdGlvbixcbiAgICBwcml2YXRlIGJhc2VIYW5kbGVyOiBCYXNlUmVtb3RlQ2FsbEhhbmRsZXIsXG4gICAgcHJpdmF0ZSBzZXJ2aWNlRGVzY3JpcHRvcjogU2VydmljZURlc2NyaXB0b3IsXG4gICkge1xuICAgIGFwcC51c2UodGhpcy5zZXJ2aWNlRGVzY3JpcHRvci5wYXRoLCB0aGlzLnJvdXRlcik7XG4gIH1cblxuICBwdWJsaWMgYWRkKHJlbW90ZUNhbGxIYW5kbGVyOiBSZW1vdGVDYWxsSGFuZGxlckludGVyZmFjZSk6IHRoaXMge1xuICAgIGlmIChyZW1vdGVDYWxsSGFuZGxlci5kZXNjcmlwdG9yLnNlcnZpY2UgIT09IHRoaXMuc2VydmljZURlc2NyaXB0b3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFRoZSByZW1vdGUgY2FsbCBoYW5kbGVyICR7cmVtb3RlQ2FsbEhhbmRsZXIuZGVzY3JpcHRvci5uYW1lfSBpcyBkZWZpbmVkIGluIHNlcnZpY2UgJHtyZW1vdGVDYWxsSGFuZGxlci5kZXNjcmlwdG9yLnNlcnZpY2UubmFtZX0gYnV0IGJlaW5nIGFkZGVkIHRvIHNlcnZpY2UgJHt0aGlzLnNlcnZpY2VEZXNjcmlwdG9yLm5hbWV9LmAsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAodGhpcy5hZGRlZFBhdGhzLmhhcyhyZW1vdGVDYWxsSGFuZGxlci5kZXNjcmlwdG9yLnBhdGgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBUaGUgcmVtb3RlIGNhbGwgaGFuZGxlciAke3JlbW90ZUNhbGxIYW5kbGVyLmRlc2NyaXB0b3IubmFtZX0gaXMgZGVmaW5lZCB3aXRoIGEgcGF0aCBwYXRoICR7cmVtb3RlQ2FsbEhhbmRsZXIuZGVzY3JpcHRvci5wYXRofSB0aGF0J3MgYWxyZWFkeSByZWdpc3RlcmVkLmAsXG4gICAgICApO1xuICAgIH1cbiAgICB0aGlzLmFkZGVkUGF0aHMuYWRkKHJlbW90ZUNhbGxIYW5kbGVyLmRlc2NyaXB0b3IucGF0aCk7XG5cbiAgICB0aGlzLnJvdXRlci5wb3N0KHJlbW90ZUNhbGxIYW5kbGVyLmRlc2NyaXB0b3IucGF0aCwgKHJlcSwgcmVzKSA9PlxuICAgICAgdGhpcy5iYXNlSGFuZGxlci5oYW5kbGUocmVtb3RlQ2FsbEhhbmRsZXIsIHJlcSwgcmVzKSxcbiAgICApO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBTZXJ2aWNlSGFuZGxlciB7XG4gIHB1YmxpYyBzdGF0aWMgY3JlYXRlKFxuICAgIHNlcnZlcjogaHR0cC5TZXJ2ZXIgfCBodHRwcy5TZXJ2ZXIsXG4gICAgYWxsb3dPcmlnaW46IHN0cmluZyA9IFwiKlwiLFxuICApOiBTZXJ2aWNlSGFuZGxlciB7XG4gICAgcmV0dXJuIG5ldyBTZXJ2aWNlSGFuZGxlcihcbiAgICAgIHNlcnZlcixcbiAgICAgIEJhc2VSZW1vdGVDYWxsSGFuZGxlci5jcmVhdGUoYWxsb3dPcmlnaW4pLFxuICAgICAgQ29yc0FsbG93ZWRQcmVmbGlnaHRIYW5kbGVyLmNyZWF0ZShhbGxvd09yaWdpbiksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYXBwID0gZXhwcmVzcygpO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHNlcnZlcjogaHR0cC5TZXJ2ZXIgfCBodHRwcy5TZXJ2ZXIsXG4gICAgcHJpdmF0ZSBiYXNlSGFuZGxlcjogQmFzZVJlbW90ZUNhbGxIYW5kbGVyLFxuICAgIHByaXZhdGUgY29yc0FsbG93ZWRQcmVmbGlnaHRIYW5kbGVyOiBDb3JzQWxsb3dlZFByZWZsaWdodEhhbmRsZXIsXG4gICkge1xuICAgIHRoaXMuc2VydmVyLm9uKFwicmVxdWVzdFwiLCB0aGlzLmFwcCk7XG4gIH1cblxuICBwdWJsaWMgYWRkQ29yc0FsbG93ZWRQcmVmbGlnaHRIYW5kbGVyKCk6IHRoaXMge1xuICAgIHRoaXMuYXBwLm9wdGlvbnMoXCIvKlwiLCAocmVxLCByZXMpID0+XG4gICAgICB0aGlzLmNvcnNBbGxvd2VkUHJlZmxpZ2h0SGFuZGxlci5oYW5kbGUocmVzKSxcbiAgICApO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcHVibGljIGFkZE1ldHJpY3NIYW5kbGVyKCk6IHRoaXMge1xuICAgIHRoaXMuYXBwLmdldChcIi9tZXRyaWNzelwiLCBhc3luYyAocmVxLCByZXMpID0+IHtcbiAgICAgIHJlcy5zZXRIZWFkZXIoXCJDb250ZW50LVR5cGVcIiwgXCJ0ZXh0L3BsYWluXCIpO1xuICAgICAgcmVzLmVuZChhd2FpdCBwcm9tQ2xpZW50LnJlZ2lzdGVyLm1ldHJpY3MoKSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBwdWJsaWMgYWRkSGVhbHRoQ2hlY2tIYW5kbGVyKCk6IHRoaXMge1xuICAgIHRoaXMuYXBwLmdldChcIi9oZWFsdGh6XCIsIChyZXEsIHJlcykgPT4ge1xuICAgICAgcmVzLmVuZChcIk9LXCIpO1xuICAgIH0pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcHVibGljIGFkZFJlYWRpbmVzc0hhbmRsZXIoKTogdGhpcyB7XG4gICAgdGhpcy5hcHAuZ2V0KFwiL3JlYWRpbmVzc1wiLCAocmVxLCByZXMpID0+IHtcbiAgICAgIHJlcy5lbmQoXCJPS1wiKTtcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHB1YmxpYyBhZGRIYW5kbGVyUmVnaXN0ZXIoXG4gICAgc2VydmljZURlc2NyaXB0b3I6IFNlcnZpY2VEZXNjcmlwdG9yLFxuICApOiBIYW5kbGVyUmVnaXN0ZXIge1xuICAgIHJldHVybiBuZXcgSGFuZGxlclJlZ2lzdGVyKHRoaXMuYXBwLCB0aGlzLmJhc2VIYW5kbGVyLCBzZXJ2aWNlRGVzY3JpcHRvcik7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgc3RhcnQocG9ydDogbnVtYmVyKTogUHJvbWlzZTx0aGlzPiB7XG4gICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICAgIHRoaXMuc2VydmVyLmxpc3Rlbihwb3J0LCAoKSA9PiByZXNvbHZlKCkpO1xuICAgIH0pO1xuICAgIGNvbnNvbGUubG9nKGBTZXJ2ZXIgaXMgbGlzdGVuaW5nIG9uIHBvcnQgJHtwb3J0fS5gKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBzdG9wKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiB0aGlzLnNlcnZlci5jbG9zZSgoKSA9PiByZXNvbHZlKCkpKTtcbiAgICBjb25zb2xlLmxvZyhgU2VydmVyIGhhcyBzdG9wcGVkLmApO1xuICAgIC8vIFdhaXQgZm9yIHRoZSBzZXJ2ZXIgdG8gY2xvc2UgYWxsIGNvbm5lY3Rpb25zLlxuICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDEwMDApKTtcbiAgfVxufVxuIl19