diff --git a/config_sample.json b/config_sample.json index 5df5817..429d42f 100644 --- a/config_sample.json +++ b/config_sample.json @@ -114,5 +114,8 @@ "path" : "/api/profile", "methods" : ["GET", "PUT"] } + ], + "directProxyUrls": [ + "\/upload$" ] } diff --git a/config_schema.json b/config_schema.json index 0e79c67..b80a27e 100644 --- a/config_schema.json +++ b/config_schema.json @@ -177,5 +177,6 @@ "required": true } }, - "additionalProperties": false -} \ No newline at end of file + "additionalProperties": false, + "directProxyUrls": { "type": "array", "items": {"type": "string"} } +} diff --git a/package.json b/package.json index fc4eec5..65ff441 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "countries-info": "^1.0.6", "debug": "^2.1.0", "escape-regexp": "0.0.1", + "http-proxy": "^1.8.1", "jsonschema": "^1.0.0", "lodash": "^3.1.0", "mongodb": "^1.4.22", diff --git a/src/cipherlayer.js b/src/cipherlayer.js index 9098750..bb67970 100644 --- a/src/cipherlayer.js +++ b/src/cipherlayer.js @@ -19,6 +19,7 @@ var prepareOptions = require('./middlewares/prepareOptions.js'); var platformsSetUp = require('./middlewares/platformsSetUp.js'); var propagateRequest = require('./middlewares/propagateRequest.js'); var permissions = require('./middlewares/permissions.js'); +var bodyParserWrapper = require('./middlewares/bodyParserWrapper.js'); var versionControl = require('version-control'); @@ -59,7 +60,8 @@ function startListener(publicPort, privatePort, cbk){ }); server.use(restify.queryParser()); - server.use(restify.bodyParser({maxBodySize: 1024 * 1024 * 3})); + server.use(bodyParserWrapper(restify.bodyParser({maxBodySize: 1024 * 1024 * 3}))); + server.use(function(req,res,next){ debug('> ' + req.method + ' ' + req.url); next(); diff --git a/src/middlewares/bodyParserWrapper.js b/src/middlewares/bodyParserWrapper.js new file mode 100644 index 0000000..5afddee --- /dev/null +++ b/src/middlewares/bodyParserWrapper.js @@ -0,0 +1,28 @@ +var config = require('../../config.json'); +var _ = require('lodash'); + +var wrapper = module.exports = function(middleware) { + return function(req, res, next) { + + var useDirectProxy = _.some(config.directProxyUrls, function(pattern) { + return req.url.match(new RegExp(pattern, 'g')); + }); + + // if url is a proxy request, don't do anything and move to next middleware + if(useDirectProxy) { + next(); + } + // else invoke middleware + else { + // some middleware is an array (ex. bodyParser) + if(middleware instanceof Array) { + middleware[0](req, res, function() { + middleware[1](req, res, next); + }); + } + else { + middleware(req, res, next); + } + } + }; +}; diff --git a/src/middlewares/propagateRequest.js b/src/middlewares/propagateRequest.js index 81135c5..af335cd 100644 --- a/src/middlewares/propagateRequest.js +++ b/src/middlewares/propagateRequest.js @@ -1,31 +1,69 @@ +var config = require('../../config.json'); var debug = require('debug')('cipherlayer:service'); var request = require('request'); +var httpProxy = require('http-proxy'); +var _ = require('lodash'); + +var proxy = httpProxy.createProxyServer({}); + +proxy.on('proxyReq', function(proxyReq, req, res, options) { + debug('> http-proxy request received'); +}); + +proxy.on('proxyRes', function() { + debug('< http-proxy response received'); +}); + +proxy.on('error', function (err, req, res) { + debug('http-proxy error occurred', err); + res.send(500, {err:' auth_proxy_error', des: 'there was an internal error when redirecting the call to protected service'}); +}); + + + function propagateRequest(req, res, next){ var start = Date.now(); - request(req.options, function(err, private_res, body) { - var timing = Date.now() - start; - if(err) { - debug('<= ' + private_res.statusCode + ' ' + err + ' ' + timing + 'ms'); - res.send(500, {err:' auth_proxy_error', des: 'there was an internal error when redirecting the call to protected service'}); + var useDirectProxy = _.some(config.directProxyUrls, function(pattern) { + return req.url.match(new RegExp(pattern, 'g')); + }); + + // if url is a direct proxy request, use http-proxy + if (useDirectProxy) { + + proxy.web(req, res, { + target: 'http://'+ config.private_host + ':' + config.private_port + }); + return; + } else { - try{ - body = JSON.parse(body); - debug('<= ' + private_res.statusCode + ' json body' + ' ' + timing + 'ms'); - } catch(ex) { - debug('<= ' + private_res.statusCode + ' no json body' + ' ' + timing + 'ms'); - } - if(private_res.statusCode === 302){ - res.header('Location', private_res.headers.location); - res.send(302); - } else { - res.send(Number(private_res.statusCode), body); - } - } - return next(); - }); + // This are the normal requests + + request(req.options, function(err, private_res, body) { + var timing = Date.now() - start; + if(err) { + debug('<= ' + private_res.statusCode + ' ' + err + ' ' + timing + 'ms'); + res.send(500, {err:' auth_proxy_error', des: 'there was an internal error when redirecting the call to protected service'}); + } else { + try{ + body = JSON.parse(body); + debug('<= ' + private_res.statusCode + ' json body' + ' ' + timing + 'ms'); + } catch(ex) { + debug('<= ' + private_res.statusCode + ' no json body' + ' ' + timing + 'ms'); + } + if(private_res.statusCode === 302){ + res.header('Location', private_res.headers.location); + res.send(302); + } else { + res.send(Number(private_res.statusCode), body); + } + } + + return next(); + }); + } } module.exports = propagateRequest;