UNPKG

@hapiness/proxy

Version:
155 lines 6.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const core_1 = require("@hapiness/core"); const rxjs_1 = require("rxjs"); const biim_1 = require("@hapiness/biim"); const Hapi = require("hapi"); const H2o2 = require("h2o2"); // import * as Wreck from 'wreck'; class ProxyManager { constructor(module, config) { this.server = new Hapi.Server(config); } start(module) { return rxjs_1.Observable .fromPromise(this.server.register({ plugin: H2o2 })) .flatMap(() => this.server.start()) .flatMap(() => this.instantiateHandler(module).do(_ => this.handler = _)) .flatMap(() => this.instantiateProxyResponse(module).do(_ => this.response = _)) .flatMap(() => this.instantiateProxyAuth(module).do(_ => this.auth = _)) .do(() => { if (this.auth) { const meta = core_1.extractMetadataByDecorator(this.auth.token, 'ProxyAuth'); const scheme = (server, options) => { return { authenticate: (request, h) => { // const authorization = request.headers.authorization; // if (!authorization) { // throw Biim.unauthorized(null, 'Custom'); // } // return h.authenticated({ credentials: { user: 'john' } }); return this.triggerHook('onAuthenticate', this.auth.token, this.auth.instance, [request, h]); } }; }; this.server.auth.scheme(meta.schemeName, scheme); this.server.auth.strategy('default', meta.schemeName); this.server.auth.default('default'); } this.server.route({ method: '*', path: '/{p*}', handler: { proxy: { passThrough: true, mapUri: request => this.requestHandler(request), onResponse: (err, res, req, reply) => { if (err) { return reply.response(biim_1.Biim.wrap(err)); } const result = this.responseHandler(null, res, req, reply); if (result === true) { return reply.response(res) .code(res.statusCode) .passThrough(true); } else { return result; } } } } }); }); } shutdown() { return rxjs_1.Observable.fromPromise(this.server.stop()); } instantiateHandler(module) { const handler = this.getProxyHandler(module.declarations); return core_1.DependencyInjection .instantiateComponent(handler, module.di) .map(_ => ({ token: handler, instance: _ })); } instantiateProxyResponse(module) { const handler = this.getProxyResponse(module.declarations); return core_1.DependencyInjection .instantiateComponent(handler, module.di) .map(_ => ({ token: handler, instance: _ })); } instantiateProxyAuth(module) { const handler = this.getProxyAuth(module.declarations); if (handler) { return core_1.DependencyInjection .instantiateComponent(handler, module.di) .map(_ => ({ token: handler, instance: _ })); } else { return rxjs_1.Observable.of(null); } } requestHandler(request) { const res = this.triggerHook('onMapUri', this.handler.token, this.handler.instance, [request]); return this.mapUri(res.uri, res.headers)(request); } responseHandler(payload, req, res, reply) { return this.triggerHook('onResponse', this.response.token, this.response.instance, [payload, req, res, reply]); } getProxyHandler(declarations) { const res = [] .concat(declarations) .filter(_ => !!_ && !!core_1.extractMetadataByDecorator(_, 'ProxyHandler')); if (res.length !== 1) { throw new Error('ProxyHandler need to have one definition'); } return res.shift(); } getProxyResponse(declarations) { const res = [] .concat(declarations) .filter(_ => !!_ && !!core_1.extractMetadataByDecorator(_, 'ProxyResponse')); if (res.length !== 1) { throw new Error('ProxyResponse need to have one definition'); } return res.shift(); } getProxyAuth(declarations) { const res = [] .concat(declarations) .filter(_ => !!_ && !!core_1.extractMetadataByDecorator(_, 'ProxyAuth')); if (res.length > 1) { throw new Error('ProxyAuth cannot have more than one definition'); } return res.shift(); } hasLifecycleHook(hook, token) { return token instanceof core_1.Type && hook in token.prototype; } triggerHook(hook, token, instance, args) { if (this.hasLifecycleHook(hook, token)) { return Reflect.apply(instance[hook], instance, args || []); } throw new Error(`${hook} is not implemented on ${token.name}`); } mapUri(uri, headers) { return function (request) { if (uri.indexOf('{') === -1) { return { uri }; } let address = uri.replace(/{protocol}/g, request.server.info.protocol) .replace(/{host}/g, request.server.info.host) .replace(/{port}/g, request.server.info.port) .replace(/{path}/g, request.url.path); Object.keys(request.params).forEach((key) => { const re = new RegExp(`{${key}}`, 'g'); address = address.replace(re, request.params[key]); }); return { uri: address, headers }; }; } } exports.ProxyManager = ProxyManager; //# sourceMappingURL=manager.js.map