Comparing version 9.0.0 to 10.0.0
90
index.js
@@ -8,10 +8,2 @@ /** | ||
var httpProxy = require("http-proxy"); | ||
var http = require("http"); | ||
var Immutable = require("immutable"); | ||
var conf = require("./lib/config"); | ||
var foxyServer = require("./lib/server"); | ||
var utils = require("./lib/utils"); | ||
/** | ||
@@ -25,84 +17,18 @@ * @param {String} target - a url such as http://www.bbc.co.uk or http://localhost:8181 | ||
/** | ||
* Merge/transform config with defaults | ||
* Merge user config with defaults | ||
* @type {Immutable.Map} | ||
*/ | ||
var config = conf(target, userConfig); | ||
var config = require("./lib/config")(target, userConfig); | ||
/** | ||
* Setup the connect-like app. | ||
* @type {{use: Function}} | ||
* Create a connect app | ||
*/ | ||
var app = { | ||
var app = require("./lib/server")(config); | ||
use: function (path, fn, opts) { | ||
opts = opts || {}; | ||
if (!opts.id) { | ||
opts.id = "foxy-mw-" + Math.random(); | ||
} | ||
if (!fn) { | ||
fn = path; | ||
path = ""; | ||
} | ||
if (path === "*") { | ||
path = ""; | ||
} | ||
app.stack.push({route: path, handle: fn, id: opts.id}); | ||
} | ||
}; | ||
/** | ||
* Start with empty stack | ||
* @type {Array} | ||
* Add any user-provided/default middlewares | ||
*/ | ||
app.stack = []; | ||
config.get("middleware").forEach(app.use); | ||
/** | ||
* Allow dynamic access to stack | ||
* @returns {{config: *, stack: Array}} | ||
*/ | ||
var userConfig = function () { | ||
return { | ||
config: config, | ||
stack: app.stack | ||
}; | ||
}; | ||
/** | ||
* Add any middlewares given in config | ||
*/ | ||
config.get("middleware").forEach(function (item) { | ||
app.stack.push(item); | ||
}); | ||
/** | ||
* Create basic httpProxy server | ||
*/ | ||
var proxy = httpProxy.createProxyServer(); | ||
/** | ||
* Create HTTP server & pass proxyServer for parsing | ||
*/ | ||
var server = http.createServer(foxyServer(proxy, userConfig)); | ||
/** | ||
* Attach connect-like app to server for exporting | ||
*/ | ||
server.app = app; | ||
/** | ||
* Handle proxy errors | ||
*/ | ||
proxy.on("error", config.get("errHandler")); | ||
server.on("error", config.get("errHandler")); | ||
/** | ||
* Modify Proxy responses | ||
*/ | ||
proxy.on("proxyRes", utils.proxyRes(config)); | ||
return server; | ||
return app; | ||
} | ||
@@ -109,0 +35,0 @@ |
@@ -31,2 +31,14 @@ var Immutable = require("immutable"); | ||
/** | ||
* Default req headers | ||
* @param config | ||
* @returns {{host: string, accept-encoding: string, agent: boolean}} | ||
*/ | ||
reqHeaders: function (config) { | ||
return { | ||
"host": config.urlObj.host, | ||
"accept-encoding": "identity", // disable any compression | ||
"agent": false | ||
}; | ||
}, | ||
/** | ||
* Serve any static files here | ||
@@ -73,17 +85,3 @@ */ | ||
if (typeof mw === "function") { | ||
item.set("middleware", Immutable.List([ | ||
{ | ||
route: "", | ||
handle: mw | ||
} | ||
])); | ||
} else { | ||
if (Immutable.List.isList(mw)) { | ||
item.set("middleware", mw.map(function (mwitem) { | ||
return { | ||
route: "", | ||
handle: mwitem | ||
}; | ||
})); | ||
} | ||
item.set("middleware", Immutable.List([mw])); | ||
} | ||
@@ -90,0 +88,0 @@ |
@@ -1,158 +0,87 @@ | ||
var respMod = require("resp-modifier"); | ||
var utils = require("./utils"); | ||
var parseUrl = require("parseurl"); | ||
var utils = require("./utils"); | ||
var respMod = require("resp-modifier"); | ||
var connect = require("connect"); | ||
var httpProxy = require("http-proxy"); | ||
/** | ||
* HTTP proxy server with resp modding | ||
* @param proxyServer | ||
* @param getOpts | ||
* @returns {Function} | ||
*/ | ||
module.exports = function (proxyServer, getOpts) { | ||
module.exports = function (config) { | ||
return function (req, res) { | ||
/** | ||
* Connect app for middleware stacking. | ||
*/ | ||
var app = connect(); | ||
var opts = getOpts(); | ||
var config = opts.config; | ||
var stack = opts.stack; | ||
/** | ||
* Proxy server for final requests | ||
*/ | ||
var proxy = httpProxy.createProxyServer({ | ||
target: config.get("target"), | ||
headers: config.get("reqHeaders")(config.toJS()) | ||
}); | ||
/** | ||
* Create middleware on the fly to match the host | ||
*/ | ||
var middleware = respMod({ | ||
rules: utils.getRules(config, req.headers.host), | ||
blacklist: config.get("blacklist").toJS(), | ||
whitelist: config.get("whitelist").toJS() | ||
}); | ||
/** | ||
* Proxy errors out to user errHandler | ||
*/ | ||
proxy.on("error", config.get("errHandler")); | ||
var finalHandler = function () { | ||
proxyServer.web(req, res, { | ||
target: config.get("target"), | ||
headers: { | ||
"host": config.get("hostHeader"), | ||
"accept-encoding": "identity", | ||
"agent": false | ||
} | ||
}); | ||
}; | ||
/** | ||
* Modify the proxy response | ||
*/ | ||
proxy.on("proxyRes", utils.proxyRes(config)); | ||
handle(stack, req, res, function () { | ||
middleware(req, res, finalHandler); | ||
}); | ||
}; | ||
}; | ||
/** | ||
* Push the final handler onto the mw stack | ||
*/ | ||
app.stack.push({route: "", id: "foxy-resp-mod", handle: finalhandler}); | ||
/** | ||
* @type {setImmediate} | ||
*/ | ||
var defer = typeof setImmediate === "function" ? setImmediate : function (fn) { | ||
process.nextTick(fn.bind.apply(fn, arguments)); | ||
}; | ||
/** | ||
* Intercept regular .use() calls to | ||
* ensure final handler is always called | ||
* @param path | ||
* @param fn | ||
* @param opts | ||
*/ | ||
var mwCount = 0; | ||
/** | ||
* Handle server requests, punting them down | ||
* the middleware stack. | ||
* | ||
* @api private | ||
*/ | ||
function handle(stack, req, res, out) { | ||
app.use = function (path, fn, opts) { | ||
var searchIndex = req.url.indexOf("?"); | ||
var pathlength = searchIndex !== -1 ? searchIndex : req.url.length; | ||
var fqdn = req.url[0] !== "/" && 1 + req.url.substr(0, pathlength).indexOf("://"); | ||
var protohost = fqdn ? req.url.substr(0, req.url.indexOf("/", 2 + fqdn)) : ""; | ||
var removed = ""; | ||
var slashAdded = false; | ||
var index = 0; | ||
opts = opts || {}; | ||
// final function handler | ||
var done = out; | ||
// store the original URL | ||
req.originalUrl = req.originalUrl || req.url; | ||
function next(err) { | ||
if (slashAdded) { | ||
req.url = req.url.substr(1); | ||
slashAdded = false; | ||
if (typeof path !== "string") { | ||
fn = path; | ||
path = ""; | ||
} | ||
if (removed.length !== 0) { | ||
req.url = protohost + removed + req.url.substr(protohost.length); | ||
removed = ""; | ||
if (path === "*") { | ||
path = ""; | ||
} | ||
// next callback | ||
var layer = stack[index++]; // jshint ignore:line | ||
// all done | ||
if (!layer) { | ||
defer(done, err); | ||
return; | ||
if (!opts.id) { | ||
opts.id = "foxy-mw-" + (mwCount += 1); | ||
} | ||
// route data | ||
var path = parseUrl(req).pathname || "/"; | ||
var route = layer.route; | ||
// Never override final handler | ||
app.stack.splice(app.stack.length - 1, 0, { | ||
route: path, | ||
handle: fn, | ||
id: opts.id | ||
}); | ||
}; | ||
// skip this layer if the route doesn't match | ||
if (path.toLowerCase().substr(0, route.length) !== route.toLowerCase()) { | ||
return next(err); | ||
} | ||
// skip if route match does not border "/", ".", or end | ||
var c = path[route.length]; | ||
if (c !== undefined && "/" !== c && "." !== c) { | ||
return next(err); | ||
} | ||
// trim off the part of the url that matches the route | ||
if (route.length !== 0 && route !== "/") { | ||
removed = route; | ||
req.url = protohost + req.url.substr(protohost.length + removed.length); | ||
// ensure leading slash | ||
if (!fqdn && req.url[0] !== "/") { | ||
req.url = "/" + req.url; | ||
slashAdded = true; | ||
} | ||
} | ||
// call the layer handle | ||
call(layer.handle, route, err, req, res, next); | ||
/** | ||
* Final handler - give the request to the proxy | ||
* and cope with link re-writing | ||
* @param req | ||
* @param res | ||
*/ | ||
function finalhandler (req, res) { | ||
respMod({ | ||
rules: utils.getRules(config, req.headers.host), | ||
blacklist: config.get("blacklist").toJS(), | ||
whitelist: config.get("whitelist").toJS() | ||
})(req, res, function () { | ||
proxy.web(req, res); | ||
}); | ||
} | ||
next(); | ||
} | ||
/** | ||
* Invoke a route handle. | ||
* | ||
* @api private | ||
*/ | ||
function call(handle, route, err, req, res, next) { | ||
var arity = handle.length; | ||
var hasError = Boolean(err); | ||
//console.log("%s %s : %s", handle.name || "<anonymous>", route, req.originalUrl); | ||
try { | ||
if (hasError && arity === 4) { | ||
// error-handling middleware | ||
handle(err, req, res, next); | ||
return; | ||
} else if (!hasError && arity < 4) { | ||
// request-handling middleware | ||
handle(req, res, next); | ||
return; | ||
} | ||
} catch (e) { | ||
// reset the error | ||
err = e; | ||
} | ||
// continue | ||
next(err); | ||
} | ||
return app; | ||
}; |
{ | ||
"name": "foxy", | ||
"version": "9.0.0", | ||
"version": "10.0.0", | ||
"description": "Proxy with response modding", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
15
16490
490