UNPKG

openhim-core

Version:

The OpenHIM core application that provides logging and routing of http requests

163 lines (146 loc) 5.84 kB
var Channel, Q, config, invertPathTransform, rewriteUrls, router, routerConf, url, utils, winston; url = require('url'); winston = require('winston'); Q = require('q'); Channel = (require('../../lib/model/channels')).Channel; config = require('../config/config'); routerConf = config.get('router'); utils = require('../../lib/utils'); router = require('../../lib/middleware/router'); invertPathTransform = function(pathTransform) { return pathTransform.replace(/s\/(.*?)\/(.*?)(?:$|\/(.*)$)/, 's/$2/$1/$3'); }; exports.fetchRewriteConfig = function(channel, authType, callback) { var rwConfig; rwConfig = []; if (channel.rewriteUrlsConfig != null) { rwConfig = rwConfig.concat(channel.rewriteUrlsConfig); } if (channel.addAutoRewriteRules) { /* * Add in default (virtual) rewrite rules for hosts we proxy * * For example if the SHR for some reason sent back a link to a patient in the CR * (using a direct link to the CR), then if we have a channel that points to the * CR on a primary route we are able to rewrite the link to point to us instead * because we know that host. */ return utils.getAllChannelsInPriorityOrder(function(err, channels) { var fn, i, j, len, len1, ref, route; if (err != null) { return callback(err); } for (i = 0, len = channels.length; i < len; i++) { channel = channels[i]; ref = channel.routes; fn = function() { var inverseTransform, toPort; if (route.primary) { /* * if this channel has a pathTranform on its primary route then * invert the path transform so that links that point to this route * have the path transform reversed when they are rewritten * * For example, say we have a channel with urlPattern=/CSD/ and a * pathTransform on the primary route as follows pathTransform=s/CSD/ihris/ * (ie. the actual server we are proxying is running on http://<host>:<port>/ihirs/). * If we get links back from this server it will be something like * http://<host>:<port>/ihirs/something/123 but we need it to be * http://<him_host>:<him_port>/CSD/something/123. To do this we can reverse * the pathTransform on the route (s/ihris/CSD/) and apply it while doing the * rewrite. */ if (route.pathTransform) { inverseTransform = invertPathTransform(route.pathTransform); } if ((authType != null) === 'tls') { toPort = routerConf.httpsPort; } else { toPort = routerConf.httpPort; } return rwConfig.push({ 'fromHost': route.host, 'toHost': routerConf.externalHostname, 'fromPort': route.port, 'toPort': toPort, 'pathTransform': inverseTransform ? inverseTransform : null }); } }; for (j = 0, len1 = ref.length; j < len1; j++) { route = ref[j]; fn(); } } return callback(null, rwConfig); }); } else { return callback(null, rwConfig); } }; rewriteUrls = function(body, channel, authType, callback) { return exports.fetchRewriteConfig(channel, authType, function(err, rwConfig) { var newBody; if (err != null) { return callback(err); } newBody = body.replace(/["|']?(?:href|src|fullUrl)["|']?[:|=]\s?["|'](\S*?)["|']/g, function(match, hrefUrl) { var hrefUrlObj, i, j, len, len1, ref, relativePath, replacement, rewriteRule, route; hrefUrlObj = url.parse(hrefUrl); if (hrefUrlObj.host == null) { ref = channel.routes; for (i = 0, len = ref.length; i < len; i++) { route = ref[i]; if (route.primary) { hrefUrlObj.hostname = route.host; hrefUrlObj.port = route.port.toString(); relativePath = true; break; } } } for (j = 0, len1 = rwConfig.length; j < len1; j++) { rewriteRule = rwConfig[j]; if (rewriteRule.fromHost.toLowerCase() === hrefUrlObj.hostname && (rewriteRule.fromPort.toString() === hrefUrlObj.port || (rewriteRule.fromPort === 80 && hrefUrlObj.port === null))) { hrefUrlObj.host = null; hrefUrlObj.hostname = rewriteRule.toHost; hrefUrlObj.port = rewriteRule.toPort; if (hrefUrlObj.protocol) { if (rewriteRule.toPort === routerConf.httpsPort) { hrefUrlObj.protocol = 'https'; } else { hrefUrlObj.protocol = 'http'; } } if (rewriteRule.pathTransform) { hrefUrlObj.pathname = router.transformPath(hrefUrlObj.pathname, rewriteRule.pathTransform); } break; } } if (relativePath) { hrefUrlObj.host = null; hrefUrlObj.hostname = null; hrefUrlObj.port = null; } replacement = url.format(hrefUrlObj); winston.debug("Rewriting url " + hrefUrl + " as " + replacement); return match.replace(hrefUrl, replacement); }); return callback(null, newBody); }); }; if (process.env.NODE_ENV === 'test') { exports.invertPathTransform = invertPathTransform; exports.rewriteUrls = rewriteUrls; } exports.koaMiddleware = function*(next) { var rewrite; (yield next); if (this.authorisedChannel.rewriteUrls) { rewrite = Q.denodeify(rewriteUrls); this.response.body = (yield rewrite(this.response.body.toString(), this.authorisedChannel, this.authenticationType)); return winston.info("Rewrote url in the response of transaction: " + this.transactionId); } }; //# sourceMappingURL=rewriteUrls.js.map