UNPKG

@tririga/tri-proxy

Version:

A development HTTP proxy for IBM TRIRIGA UX views.

195 lines (178 loc) 5.19 kB
"use strict"; const bs = require("browser-sync"); const path = require("path"); const url = require("url"); const fs = require("fs"); const http = require("http"); const https = require("https"); const proxyUtils = require("./proxy-utils"); class TriProxy { constructor(target, port, views, dirs, browser) { this.target = target; this.port = port; this.views = views; this.dirs = this.stripTrailingSlash(dirs); this.browser = browser; this.contextPath = this.getContextPath(); this._started = false; } start() { if (!this.started) { this.server = bs.create("tri-proxy"); this.server.init(this.getServerOptions()); this.started = true; } } getServerOptions() { let serverOptions = { proxy: { target: this.target, proxyRes: [ proxyUtils.checkCookies ], cookies: { stripDomain: false }, }, port: this.port, ui: false, snippetOptions: { rule: { match: /<\/body>/i, fn: function (snippet, match) { return snippet + match; } } }, serveStatic: this.getServeStaticOption(), files: this.getFiles(), middleware: this.getMiddleware(), ghostMode: { clicks: false, scroll: false, forms: false }, notify:false, } if (this.browser && this.browser.length > 0) { serverOptions.browser = this.browser; } return serverOptions; } getContextPath() { if (!this.target) { return null; } var matches = this.target.match(/https?:\/\/[^\/]*(\/[^\/]*)/); return (matches && matches.length > 1 && matches[1].length > 1 && matches[1] != "/p") ? matches[1] : ""; } getServeStaticOption() { var serveStaticList = []; this.views.forEach((view, index) => Array.prototype.push.apply(serveStaticList, this._createViewStaticRoutes(view, this.dirs[index]))); return serveStaticList; } _createViewStaticRoutes(view, dir) { let viewStaticRoutes = []; viewStaticRoutes.push({ route: `${this.contextPath}/p/components/r/en-US/l/${view}`, dir: dir }); viewStaticRoutes.push({ route: `${this.contextPath}/p/components/r/1/v/en-US/l/${view}`, dir: dir }); viewStaticRoutes.push({ route: `${this.contextPath}/p/components/r/3/v/en-US/l/${view}`, dir: dir }); return viewStaticRoutes; } getMiddleware() { return [this.processTranslatedFiles.bind(this)]; } processTranslatedFiles(req, res, next) { if (req.headers["authorization"]) { this.authorization = req.headers["authorization"]; } let parsedUrl = url.parse(req.url); let componentRegExp = new RegExp("/p/components/r/(?:([1,3])/v/)?([^/]+)/l/([^/]+)/(.+/)?([^/]+)$"); var matches = parsedUrl.pathname.match(componentRegExp); if (matches != null) { let polymerVersion = matches[1]; polymerVersion = !polymerVersion ? "1" : polymerVersion; let language = matches[2]; let view = matches[3]; let pathInsideView = matches[4]; pathInsideView = !pathInsideView ? "" : pathInsideView.replace(/[\/\\]/g, path.sep); let fileName = matches[5]; let viewIndex = this.views.indexOf(view); if (language != "en-US" && viewIndex >= 0) { try { this.translateFile(req, res, polymerVersion, pathInsideView, fileName, this.dirs[viewIndex]); } catch(e) { next(); } } else { next(); } } else { next(); } } translateFile(req, res, polymerVersion, pathInsideView, fileName, dir) { let filePath = `${dir}${path.sep}${pathInsideView}${fileName}`; if(!fs.existsSync(filePath)) { throw new Error("File not found"); } let fileStream = fs.createReadStream(filePath); let options = this.createTranslateFileRequestOptions(req, polymerVersion, fileName); let parsedTarget = url.parse(this.target); let protocol = parsedTarget.protocol === "https:" ? https : http; let translatioReq = protocol.request(options, (translationResp) => { const contentType = translationResp.headers['content-type']; res.setHeader('Content-Type', contentType); res.statusCode = translationResp.statusCode; translationResp.pipe(res); }); fileStream.pipe(translatioReq); translatioReq.on('error', function(e){ console.error(e); }); } createTranslateFileRequestOptions(req, polymerVersion, fileName) { let parsedTarget = url.parse(this.target); var options = { hostname: parsedTarget.hostname, port: parsedTarget.port, path: `${this.contextPath}/p/components/translate_tri_view/${polymerVersion}/${fileName}`, method: "POST", headers: { "Cookie": req.headers["cookie"] } }; if (req.headers["authorization"]) { options.headers["Authorization"] = req.headers["authorization"]; } else if (this.authorization) { options.headers["Authorization"] = this.authorization; } return options; } getFiles() { var files = []; for (var i = 0, j = 0; i < this.dirs.length; ++i) { files[j++] = this.dirs[i] + "/**/*.html"; files[j++] = this.dirs[i] + "/**/*.js"; } return files; } stripTrailingSlash(dirs) { if (!dirs) { return null; } for (var index = 0; index < dirs.length; index++) { dirs[index] = dirs[index] ? path.resolve(dirs[index]).replace(/[\\\/]+$/, "") : ""; } return dirs; } }; module.exports = TriProxy;