Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,33 @@ var server = app.listen(3000);
}
```

* **option.logLevel**: string, ['debug', 'info', 'warn', 'error', 'silent']. Default: 'info'

* **option.logProvider**: function, modify or replace log provider. Default: `console`.
```javascript
// simple replace
function logProvider(provider) {
// replace the default console log provider.
return require('winston');
}
```

```javascript
// verbose replacement
function logProvider(provider) {
var logger = new (require('winston').Logger)();

var myCustomProvider = {
log: logger.log,
debug: logger.debug,
info: logger.info,
warn: logger.warn,
error: logger.error
}
return myCustomProvider;
}
```

* **option.onError**: function, subscribe to http-proxy's error event for custom error handling.
```javascript
function onError(err, req, res) {
Expand Down Expand Up @@ -222,10 +249,10 @@ $ node examples/connect
```

Or just explore the proxy examples' sources:
* `examples/connect` - [connect proxy example](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/connect/index.js)
* `examples/express` - [express proxy example](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/express/index.js)
* `examples/browser-sync` - [browser-sync proxy example](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/browser-sync/index.js)
* `examples/websocket` - [websocket proxy example](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/websocket/index.js) with express
* `examples/connect` - [connect proxy example](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/connect/index.js)
* `examples/express` - [express proxy example](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/express/index.js)
* `examples/browser-sync` - [browser-sync proxy example](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/browser-sync/index.js)
* `examples/websocket` - [websocket proxy example](https://github.com/chimurai/http-proxy-middleware/tree/master/examples/websocket/index.js) with express

## Compatible servers

Expand Down
17 changes: 11 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var handlers = require('./lib/handlers');
var contextMatcher = require('./lib/context-matcher');
var PathRewriter = require('./lib/path-rewriter');
var ProxyTable = require('./lib/proxy-table');
var logger = require('./lib/logger').getInstance();

var httpProxyMiddleware = function (context, opts) {
var isWsUpgradeListened = false;
Expand All @@ -13,7 +14,7 @@ var httpProxyMiddleware = function (context, opts) {

// create proxy
var proxy = httpProxy.createProxyServer(proxyOptions);
console.log('[HPM] Proxy created:', config.context, ' -> ', proxyOptions.target);
logger.info('[HPM] Proxy created:', config.context, ' -> ', proxyOptions.target);

var pathRewriter = PathRewriter.create(proxyOptions.pathRewrite); // returns undefined when "pathRewrite" is not provided

Expand All @@ -31,7 +32,7 @@ var httpProxyMiddleware = function (context, opts) {
// Listen for the `close` event on `proxy`.
proxy.on('close', function (req, socket, head) {
// view disconnected websocket connections
console.log('[HPM] Client disconnected');
logger.info('[HPM] Client disconnected');
});

// https://github.com/chimurai/http-proxy-middleware/issues/19
Expand All @@ -50,15 +51,19 @@ var httpProxyMiddleware = function (context, opts) {
}

if (contextMatcher.match(config.context, req.url)) {
logger.debug('[HPM] Context match: "%s" -> "%s"', config.context, req.url);

// handle option.pathRewrite
if (pathRewriter) {
req.url = pathRewriter(req.url);
}

if (proxyOptions.proxyTable) {
// change option.target when proxyTable present.
proxy.web(req, res, ProxyTable.createProxyOptions(req, proxyOptions));
var altOpts = ProxyTable.createProxyOptions(req, proxyOptions);
logger.debug('[HPM] Proxying "%s": "%s" -> "%s"', req.url, req.hostname, altOpts.target);
proxy.web(req, res, altOpts);
} else {
logger.debug('[HPM] Proxying "%s": "%s" -> "%s"', req.url, req.hostname, proxyOptions.target);
proxy.web(req, res);
}

Expand Down Expand Up @@ -87,7 +92,7 @@ var httpProxyMiddleware = function (context, opts) {
req.url = pathRewriter(req.url);
}
proxy.ws(req, socket, head);
console.log('[HPM] Upgrading to WebSocket');
logger.info('[HPM] Upgrading to WebSocket');
}
}

Expand All @@ -101,7 +106,7 @@ var httpProxyMiddleware = function (context, opts) {

function proxyErrorLogger (err, req, res) {
var targetUri = proxyOptions.target.host + req.url;
console.log('[HPM] Proxy error:', err.code, targetUri);
logger.error('[HPM] Proxy error: %s. %s -> "%s"', err.code, req.hostname, targetUri);
}

};
Expand Down
31 changes: 22 additions & 9 deletions lib/config-factory.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var _ = require('lodash');
var url = require('url');
var _ = require('lodash');
var url = require('url');
var logger = require('./logger').getInstance();

module.exports = {
createConfig : createConfig
Expand Down Expand Up @@ -30,13 +31,15 @@ function createConfig (context, opts) {
config.options = _.assign(config.options, opts);
}

// Legacy option.proxyHost
config.options = mapLegacyProxyHostOption(config.options);
configureLogger(config.options);

if (!config.options.target) {
throw new Error('[HPM] Missing "target" option. Example: {target: "http://www.example.org"}');
}

// Legacy option.proxyHost
config.options = mapLegacyProxyHostOption(config.options);

return config;
};

Expand All @@ -49,15 +52,25 @@ function isShortHand (context) {
function mapLegacyProxyHostOption (options) {
// set options.headers.host when option.proxyHost is provided
if (options.proxyHost) {
console.log('*************************************');
console.log('[HPM] Deprecated "option.proxyHost"');
console.log(' Use "option.changeOrigin" or "option.headers.host" instead');
console.log(' "option.proxyHost" will be removed in future release.');
console.log('*************************************');
logger.warn('*************************************');
logger.warn('[HPM] Deprecated "option.proxyHost"');
logger.warn(' Use "option.changeOrigin" or "option.headers.host" instead');
logger.warn(' "option.proxyHost" will be removed in future release.');
logger.warn('*************************************');

options.headers = options.headers || {};
options.headers.host = options.proxyHost;
}

return options;
}

function configureLogger (options) {
if (options.logLevel) {
logger.setLevel(options.logLevel);
}

if (options.logProvider) {
logger.setProvider(options.logProvider);
}
}
143 changes: 143 additions & 0 deletions lib/logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
var util = require('util');
var _ = require('lodash');

var loggerInstance;

var defaultProvider = {
log : console.log,
debug : console.log, // use .log(); since console does not have .debug()
info : console.info,
warn : console.warn,
error : console.error
}

// log level 'weight'
var LEVELS = {
debug : 10,
info : 20,
warn : 30,
error : 50,
silent : 80
}

module.exports = {
// singleton
getInstance : function () {
if (!loggerInstance) {
loggerInstance = new Logger();
}

return loggerInstance;
}
};

function Logger () {
var logLevel;
var provider;

var api = {
log : log,
debug : debug,
info : info,
warn : warn,
error : error,
setLevel : function (v) {
if (isValidLevel(v)) {
logLevel = v;
}
},
setProvider : function (fn) {
if (fn && isValidProvider(fn)) {
provider = fn(defaultProvider);
}
}
};


init();

return api;

function init () {
api.setLevel('info');
api.setProvider(function () {
return defaultProvider;
});
}

// log will log messages, regardless of logLevels
function log () {
provider.log(_interpolate.apply(null, arguments));
}

function debug () {
if (_showLevel('debug')) {
provider.debug(_interpolate.apply(null, arguments));
}
}

function info () {
if (_showLevel('info')) {
provider.info(_interpolate.apply(null, arguments));
}
}

function warn () {
if (_showLevel('warn')) {
provider.warn(_interpolate.apply(null, arguments));
}
}

function error () {
if (_showLevel('error')) {
provider.error(_interpolate.apply(null, arguments));
}
}

/**
* Decide to log or not to log, based on the log levels 'weight'
* @param {String} showLevel [debug, info, warn, error, silent]
* @return {Boolean}
*/
function _showLevel (showLevel) {
var result = false;
var currentLogLevel = LEVELS[logLevel];

if (currentLogLevel && (currentLogLevel <= LEVELS[showLevel])) {
result = true;
}

return result;
}

// make sure logged messages and its data are return interpolated
// make it possible for additional log data, such date/time or custom prefix.
function _interpolate () {
var fn = _.spread(util.format);
var result = fn(_.slice(arguments));

return result;
}

function isValidProvider (fnProvider) {
var result = true;

if (fnProvider && !_.isFunction(fnProvider)) {
throw new Error('[HPM] Log provider config error. Expecting a function.');
}

return result;
}

function isValidLevel (levelName) {
var validLevels = _.keys(LEVELS);
var isValid = _.includes(validLevels, levelName);

if (!isValid) {
throw new Error('[HPM] Log level error. Invalid logLevel.');
}

return isValid;
}
}

6 changes: 4 additions & 2 deletions lib/path-rewriter.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var _ = require('lodash');
var _ = require('lodash');
var logger = require('./logger').getInstance();

module.exports = {
create : createPathRewriter
Expand All @@ -23,6 +24,7 @@ function createPathRewriter (config) {
_.forEach(rules,function (rule) {
if (rule.regex.test(path)) {
result = result.replace(rule.regex, rule.value);
logger.debug('[HPM] Rewriting path from "%s" to "%s"', path, result);
return false;
}
});
Expand All @@ -43,7 +45,7 @@ function parsePathRewriteRules (config) {
regex : new RegExp(key),
value : config[key]
});
console.log('[HPM] Proxy rewrite rule created: "' + key + '" -> "' + config[key] + '"');
logger.info('[HPM] Proxy rewrite rule created: "%s" -> "%s"', key, config[key]);
});

}
Expand Down
8 changes: 6 additions & 2 deletions lib/proxy-table.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var url = require('url');
var _ = require('lodash');
var url = require('url');
var _ = require('lodash');
var logger = require('./logger.js').getInstance();

module.exports = {
createProxyOptions : createProxyOptions
Expand All @@ -12,6 +13,7 @@ function createProxyOptions (req, config) {
if (proxyTable) {
var newTarget = getTargetFromProxyTable(req, proxyTable);
if (newTarget) {
logger.debug('[HPM] proxyTable new target: %s -> "%s"', config.target, newTarget);
result = _.assign(result, {target : newTarget}); // override option.target
}
}
Expand All @@ -31,12 +33,14 @@ function getTargetFromProxyTable (req, proxyTable) {

if (hostAndPath.indexOf(key) > -1) { // match 'localhost:3000/api'
result = proxyTable[key];
logger.debug('[HPM] proxyTable match: %s -> "%s"', hostAndPath, result);
return false;
}
} else {

if (key === host) { // match 'localhost:3000'
result = proxyTable[key];
logger.debug('[HPM] proxyTable match: %s -> "%s"', host, result);
return false;
}

Expand Down
Loading