http-proxy-middleware 0.19.2 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -3
- package/README.md +58 -51
- package/dist/config-factory.js +79 -0
- package/dist/context-matcher.js +81 -0
- package/dist/errors.js +9 -0
- package/dist/handlers.js +70 -0
- package/dist/http-proxy-middleware.js +140 -0
- package/dist/index.js +7 -0
- package/dist/logger.js +135 -0
- package/dist/path-rewriter.js +67 -0
- package/dist/router.js +45 -0
- package/package.json +43 -31
- package/index.js +0 -5
- package/lib/config-factory.js +0 -129
- package/lib/context-matcher.js +0 -94
- package/lib/errors.js +0 -12
- package/lib/handlers.js +0 -82
- package/lib/index.js +0 -182
- package/lib/logger.js +0 -172
- package/lib/path-rewriter.js +0 -79
- package/lib/router.js +0 -51
package/lib/context-matcher.js
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
var _ = require('lodash')
|
|
2
|
-
var url = require('url')
|
|
3
|
-
var isGlob = require('is-glob')
|
|
4
|
-
var micromatch = require('micromatch')
|
|
5
|
-
var ERRORS = require('./errors')
|
|
6
|
-
|
|
7
|
-
module.exports = {
|
|
8
|
-
match: matchContext
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function matchContext(context, uri, req) {
|
|
12
|
-
// single path
|
|
13
|
-
if (isStringPath(context)) {
|
|
14
|
-
return matchSingleStringPath(context, uri)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// single glob path
|
|
18
|
-
if (isGlobPath(context)) {
|
|
19
|
-
return matchSingleGlobPath(context, uri)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// multi path
|
|
23
|
-
if (Array.isArray(context)) {
|
|
24
|
-
if (context.every(isStringPath)) {
|
|
25
|
-
return matchMultiPath(context, uri)
|
|
26
|
-
}
|
|
27
|
-
if (context.every(isGlobPath)) {
|
|
28
|
-
return matchMultiGlobPath(context, uri)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
throw new Error(ERRORS.ERR_CONTEXT_MATCHER_INVALID_ARRAY)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// custom matching
|
|
35
|
-
if (_.isFunction(context)) {
|
|
36
|
-
var pathname = getUrlPathName(uri)
|
|
37
|
-
return context(pathname, req)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
throw new Error(ERRORS.ERR_CONTEXT_MATCHER_GENERIC)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* @param {String} context '/api'
|
|
45
|
-
* @param {String} uri 'http://example.org/api/b/c/d.html'
|
|
46
|
-
* @return {Boolean}
|
|
47
|
-
*/
|
|
48
|
-
function matchSingleStringPath(context, uri) {
|
|
49
|
-
var pathname = getUrlPathName(uri)
|
|
50
|
-
return pathname.indexOf(context) === 0
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function matchSingleGlobPath(pattern, uri) {
|
|
54
|
-
var pathname = getUrlPathName(uri)
|
|
55
|
-
var matches = micromatch(pathname, pattern)
|
|
56
|
-
return matches && matches.length > 0
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function matchMultiGlobPath(patternList, uri) {
|
|
60
|
-
return matchSingleGlobPath(patternList, uri)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* @param {String} contextList ['/api', '/ajax']
|
|
65
|
-
* @param {String} uri 'http://example.org/api/b/c/d.html'
|
|
66
|
-
* @return {Boolean}
|
|
67
|
-
*/
|
|
68
|
-
function matchMultiPath(contextList, uri) {
|
|
69
|
-
for (var i = 0; i < contextList.length; i++) {
|
|
70
|
-
var context = contextList[i]
|
|
71
|
-
if (matchSingleStringPath(context, uri)) {
|
|
72
|
-
return true
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return false
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Parses URI and returns RFC 3986 path
|
|
80
|
-
*
|
|
81
|
-
* @param {String} uri from req.url
|
|
82
|
-
* @return {String} RFC 3986 path
|
|
83
|
-
*/
|
|
84
|
-
function getUrlPathName(uri) {
|
|
85
|
-
return uri && url.parse(uri).pathname
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function isStringPath(context) {
|
|
89
|
-
return _.isString(context) && !isGlob(context)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function isGlobPath(context) {
|
|
93
|
-
return isGlob(context)
|
|
94
|
-
}
|
package/lib/errors.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-len */
|
|
2
|
-
|
|
3
|
-
module.exports = {
|
|
4
|
-
ERR_CONFIG_FACTORY_TARGET_MISSING:
|
|
5
|
-
'[HPM] Missing "target" option. Example: {target: "http://www.example.org"}',
|
|
6
|
-
ERR_CONTEXT_MATCHER_GENERIC:
|
|
7
|
-
'[HPM] Invalid context. Expecting something like: "/api" or ["/api", "/ajax"]',
|
|
8
|
-
ERR_CONTEXT_MATCHER_INVALID_ARRAY:
|
|
9
|
-
'[HPM] Invalid context. Expecting something like: ["/api", "/ajax"] or ["/api/**", "!**.html"]',
|
|
10
|
-
ERR_PATH_REWRITER_CONFIG:
|
|
11
|
-
'[HPM] Invalid pathRewrite config. Expecting object with pathRewrite config or a rewrite function'
|
|
12
|
-
}
|
package/lib/handlers.js
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
var _ = require('lodash')
|
|
2
|
-
var logger = require('./logger').getInstance()
|
|
3
|
-
|
|
4
|
-
module.exports = {
|
|
5
|
-
init: init,
|
|
6
|
-
getHandlers: getProxyEventHandlers
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function init(proxy, opts) {
|
|
10
|
-
var handlers = getProxyEventHandlers(opts)
|
|
11
|
-
|
|
12
|
-
_.forIn(handlers, function(handler, eventName) {
|
|
13
|
-
proxy.on(eventName, handlers[eventName])
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
logger.debug('[HPM] Subscribed to http-proxy events: ', _.keys(handlers))
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function getProxyEventHandlers(opts) {
|
|
20
|
-
// https://github.com/nodejitsu/node-http-proxy#listening-for-proxy-events
|
|
21
|
-
var proxyEvents = [
|
|
22
|
-
'error',
|
|
23
|
-
'proxyReq',
|
|
24
|
-
'proxyReqWs',
|
|
25
|
-
'proxyRes',
|
|
26
|
-
'open',
|
|
27
|
-
'close'
|
|
28
|
-
]
|
|
29
|
-
var handlers = {}
|
|
30
|
-
|
|
31
|
-
_.forEach(proxyEvents, function(event) {
|
|
32
|
-
// all handlers for the http-proxy events are prefixed with 'on'.
|
|
33
|
-
// loop through options and try to find these handlers
|
|
34
|
-
// and add them to the handlers object for subscription in init().
|
|
35
|
-
var eventName = _.camelCase('on ' + event)
|
|
36
|
-
var fnHandler = _.get(opts, eventName)
|
|
37
|
-
|
|
38
|
-
if (_.isFunction(fnHandler)) {
|
|
39
|
-
handlers[event] = fnHandler
|
|
40
|
-
}
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
// add default error handler in absence of error handler
|
|
44
|
-
if (!_.isFunction(handlers.error)) {
|
|
45
|
-
handlers.error = defaultErrorHandler
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// add default close handler in absence of close handler
|
|
49
|
-
if (!_.isFunction(handlers.close)) {
|
|
50
|
-
handlers.close = logClose
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return handlers
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function defaultErrorHandler(err, req, res) {
|
|
57
|
-
var host = req.headers && req.headers.host
|
|
58
|
-
var code = err.code
|
|
59
|
-
|
|
60
|
-
if (res.writeHead && !res.headersSent) {
|
|
61
|
-
if (/HPE_INVALID/.test(code)) {
|
|
62
|
-
res.writeHead(502)
|
|
63
|
-
} else {
|
|
64
|
-
switch (code) {
|
|
65
|
-
case 'ECONNRESET':
|
|
66
|
-
case 'ENOTFOUND':
|
|
67
|
-
case 'ECONNREFUSED':
|
|
68
|
-
res.writeHead(504)
|
|
69
|
-
break
|
|
70
|
-
default:
|
|
71
|
-
res.writeHead(500)
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
res.end('Error occured while trying to proxy to: ' + host + req.url)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function logClose(req, socket, head) {
|
|
80
|
-
// view disconnected websocket connections
|
|
81
|
-
logger.info('[HPM] Client disconnected')
|
|
82
|
-
}
|
package/lib/index.js
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
var _ = require('lodash')
|
|
2
|
-
var httpProxy = require('http-proxy')
|
|
3
|
-
var configFactory = require('./config-factory')
|
|
4
|
-
var handlers = require('./handlers')
|
|
5
|
-
var contextMatcher = require('./context-matcher')
|
|
6
|
-
var PathRewriter = require('./path-rewriter')
|
|
7
|
-
var Router = require('./router')
|
|
8
|
-
var logger = require('./logger').getInstance()
|
|
9
|
-
var getArrow = require('./logger').getArrow
|
|
10
|
-
|
|
11
|
-
module.exports = HttpProxyMiddleware
|
|
12
|
-
|
|
13
|
-
function HttpProxyMiddleware(context, opts) {
|
|
14
|
-
// https://github.com/chimurai/http-proxy-middleware/issues/57
|
|
15
|
-
var wsUpgradeDebounced = _.debounce(handleUpgrade)
|
|
16
|
-
var wsInitialized = false
|
|
17
|
-
var config = configFactory.createConfig(context, opts)
|
|
18
|
-
var proxyOptions = config.options
|
|
19
|
-
|
|
20
|
-
// create proxy
|
|
21
|
-
var proxy = httpProxy.createProxyServer({})
|
|
22
|
-
logger.info(
|
|
23
|
-
'[HPM] Proxy created:',
|
|
24
|
-
config.context,
|
|
25
|
-
' -> ',
|
|
26
|
-
proxyOptions.target
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
var pathRewriter = PathRewriter.create(proxyOptions.pathRewrite) // returns undefined when "pathRewrite" is not provided
|
|
30
|
-
|
|
31
|
-
// attach handler to http-proxy events
|
|
32
|
-
handlers.init(proxy, proxyOptions)
|
|
33
|
-
|
|
34
|
-
// log errors for debug purpose
|
|
35
|
-
proxy.on('error', logError)
|
|
36
|
-
|
|
37
|
-
// https://github.com/chimurai/http-proxy-middleware/issues/19
|
|
38
|
-
// expose function to upgrade externally
|
|
39
|
-
middleware.upgrade = wsUpgradeDebounced
|
|
40
|
-
|
|
41
|
-
return middleware
|
|
42
|
-
|
|
43
|
-
function middleware(req, res, next) {
|
|
44
|
-
if (shouldProxy(config.context, req)) {
|
|
45
|
-
var activeProxyOptions = prepareProxyRequest(req)
|
|
46
|
-
proxy.web(req, res, activeProxyOptions)
|
|
47
|
-
} else {
|
|
48
|
-
next()
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (proxyOptions.ws === true) {
|
|
52
|
-
// use initial request to access the server object to subscribe to http upgrade event
|
|
53
|
-
catchUpgradeRequest(req.connection.server)
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function catchUpgradeRequest(server) {
|
|
58
|
-
// subscribe once; don't subscribe on every request...
|
|
59
|
-
// https://github.com/chimurai/http-proxy-middleware/issues/113
|
|
60
|
-
if (!wsInitialized) {
|
|
61
|
-
server.on('upgrade', wsUpgradeDebounced)
|
|
62
|
-
wsInitialized = true
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function handleUpgrade(req, socket, head) {
|
|
67
|
-
// set to initialized when used externally
|
|
68
|
-
wsInitialized = true
|
|
69
|
-
|
|
70
|
-
if (shouldProxy(config.context, req)) {
|
|
71
|
-
var activeProxyOptions = prepareProxyRequest(req)
|
|
72
|
-
proxy.ws(req, socket, head, activeProxyOptions)
|
|
73
|
-
logger.info('[HPM] Upgrading to WebSocket')
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Determine whether request should be proxied.
|
|
79
|
-
*
|
|
80
|
-
* @private
|
|
81
|
-
* @param {String} context [description]
|
|
82
|
-
* @param {Object} req [description]
|
|
83
|
-
* @return {Boolean}
|
|
84
|
-
*/
|
|
85
|
-
function shouldProxy(context, req) {
|
|
86
|
-
var path = req.originalUrl || req.url
|
|
87
|
-
return contextMatcher.match(context, path, req)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Apply option.router and option.pathRewrite
|
|
92
|
-
* Order matters:
|
|
93
|
-
* Router uses original path for routing;
|
|
94
|
-
* NOT the modified path, after it has been rewritten by pathRewrite
|
|
95
|
-
* @param {Object} req
|
|
96
|
-
* @return {Object} proxy options
|
|
97
|
-
*/
|
|
98
|
-
function prepareProxyRequest(req) {
|
|
99
|
-
// https://github.com/chimurai/http-proxy-middleware/issues/17
|
|
100
|
-
// https://github.com/chimurai/http-proxy-middleware/issues/94
|
|
101
|
-
req.url = req.originalUrl || req.url
|
|
102
|
-
|
|
103
|
-
// store uri before it gets rewritten for logging
|
|
104
|
-
var originalPath = req.url
|
|
105
|
-
var newProxyOptions = _.assign({}, proxyOptions)
|
|
106
|
-
|
|
107
|
-
// Apply in order:
|
|
108
|
-
// 1. option.router
|
|
109
|
-
// 2. option.pathRewrite
|
|
110
|
-
__applyRouter(req, newProxyOptions)
|
|
111
|
-
__applyPathRewrite(req, pathRewriter)
|
|
112
|
-
|
|
113
|
-
// debug logging for both http(s) and websockets
|
|
114
|
-
if (proxyOptions.logLevel === 'debug') {
|
|
115
|
-
var arrow = getArrow(
|
|
116
|
-
originalPath,
|
|
117
|
-
req.url,
|
|
118
|
-
proxyOptions.target,
|
|
119
|
-
newProxyOptions.target
|
|
120
|
-
)
|
|
121
|
-
logger.debug(
|
|
122
|
-
'[HPM] %s %s %s %s',
|
|
123
|
-
req.method,
|
|
124
|
-
originalPath,
|
|
125
|
-
arrow,
|
|
126
|
-
newProxyOptions.target
|
|
127
|
-
)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return newProxyOptions
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Modify option.target when router present.
|
|
134
|
-
function __applyRouter(req, options) {
|
|
135
|
-
var newTarget
|
|
136
|
-
|
|
137
|
-
if (options.router) {
|
|
138
|
-
newTarget = Router.getTarget(req, options)
|
|
139
|
-
|
|
140
|
-
if (newTarget) {
|
|
141
|
-
logger.debug(
|
|
142
|
-
'[HPM] Router new target: %s -> "%s"',
|
|
143
|
-
options.target,
|
|
144
|
-
newTarget
|
|
145
|
-
)
|
|
146
|
-
options.target = newTarget
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// rewrite path
|
|
152
|
-
function __applyPathRewrite(req, pathRewriter) {
|
|
153
|
-
if (pathRewriter) {
|
|
154
|
-
var path = pathRewriter(req.url, req)
|
|
155
|
-
|
|
156
|
-
if (typeof path === 'string') {
|
|
157
|
-
req.url = path
|
|
158
|
-
} else {
|
|
159
|
-
logger.info('[HPM] pathRewrite: No rewritten path found. (%s)', req.url)
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function logError(err, req, res) {
|
|
165
|
-
var hostname =
|
|
166
|
-
(req.headers && req.headers.host) || (req.hostname || req.host) // (websocket) || (node0.10 || node 4/5)
|
|
167
|
-
var target = proxyOptions.target.host || proxyOptions.target
|
|
168
|
-
var errorMessage =
|
|
169
|
-
'[HPM] Error occurred while trying to proxy request %s from %s to %s (%s) (%s)'
|
|
170
|
-
var errReference =
|
|
171
|
-
'https://nodejs.org/api/errors.html#errors_common_system_errors' // link to Node Common Systems Errors page
|
|
172
|
-
|
|
173
|
-
logger.error(
|
|
174
|
-
errorMessage,
|
|
175
|
-
req.url,
|
|
176
|
-
hostname,
|
|
177
|
-
target,
|
|
178
|
-
err.code || err,
|
|
179
|
-
errReference
|
|
180
|
-
)
|
|
181
|
-
}
|
|
182
|
-
}
|
package/lib/logger.js
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
var util = require('util')
|
|
2
|
-
var _ = require('lodash')
|
|
3
|
-
|
|
4
|
-
var loggerInstance
|
|
5
|
-
|
|
6
|
-
var defaultProvider = {
|
|
7
|
-
log: console.log,
|
|
8
|
-
debug: console.log, // use .log(); since console does not have .debug()
|
|
9
|
-
info: console.info,
|
|
10
|
-
warn: console.warn,
|
|
11
|
-
error: console.error
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// log level 'weight'
|
|
15
|
-
var LEVELS = {
|
|
16
|
-
debug: 10,
|
|
17
|
-
info: 20,
|
|
18
|
-
warn: 30,
|
|
19
|
-
error: 50,
|
|
20
|
-
silent: 80
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
module.exports = {
|
|
24
|
-
// singleton
|
|
25
|
-
getInstance: function() {
|
|
26
|
-
if (!loggerInstance) {
|
|
27
|
-
loggerInstance = new Logger()
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return loggerInstance
|
|
31
|
-
},
|
|
32
|
-
getArrow: getArrow
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function Logger() {
|
|
36
|
-
var logLevel
|
|
37
|
-
var provider
|
|
38
|
-
|
|
39
|
-
var api = {
|
|
40
|
-
log: log,
|
|
41
|
-
debug: debug,
|
|
42
|
-
info: info,
|
|
43
|
-
warn: warn,
|
|
44
|
-
error: error,
|
|
45
|
-
setLevel: function(v) {
|
|
46
|
-
if (isValidLevel(v)) {
|
|
47
|
-
logLevel = v
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
setProvider: function(fn) {
|
|
51
|
-
if (fn && isValidProvider(fn)) {
|
|
52
|
-
provider = fn(defaultProvider)
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
init()
|
|
58
|
-
|
|
59
|
-
return api
|
|
60
|
-
|
|
61
|
-
function init() {
|
|
62
|
-
api.setLevel('info')
|
|
63
|
-
api.setProvider(function() {
|
|
64
|
-
return defaultProvider
|
|
65
|
-
})
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// log will log messages, regardless of logLevels
|
|
69
|
-
function log() {
|
|
70
|
-
provider.log(_interpolate.apply(null, arguments))
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function debug() {
|
|
74
|
-
if (_showLevel('debug')) {
|
|
75
|
-
provider.debug(_interpolate.apply(null, arguments))
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function info() {
|
|
80
|
-
if (_showLevel('info')) {
|
|
81
|
-
provider.info(_interpolate.apply(null, arguments))
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function warn() {
|
|
86
|
-
if (_showLevel('warn')) {
|
|
87
|
-
provider.warn(_interpolate.apply(null, arguments))
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function error() {
|
|
92
|
-
if (_showLevel('error')) {
|
|
93
|
-
provider.error(_interpolate.apply(null, arguments))
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Decide to log or not to log, based on the log levels 'weight'
|
|
99
|
-
* @param {String} showLevel [debug, info, warn, error, silent]
|
|
100
|
-
* @return {Boolean}
|
|
101
|
-
*/
|
|
102
|
-
function _showLevel(showLevel) {
|
|
103
|
-
var result = false
|
|
104
|
-
var currentLogLevel = LEVELS[logLevel]
|
|
105
|
-
|
|
106
|
-
if (currentLogLevel && currentLogLevel <= LEVELS[showLevel]) {
|
|
107
|
-
result = true
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return result
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// make sure logged messages and its data are return interpolated
|
|
114
|
-
// make it possible for additional log data, such date/time or custom prefix.
|
|
115
|
-
function _interpolate() {
|
|
116
|
-
var fn = _.spread(util.format)
|
|
117
|
-
var result = fn(_.slice(arguments))
|
|
118
|
-
|
|
119
|
-
return result
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function isValidProvider(fnProvider) {
|
|
123
|
-
var result = true
|
|
124
|
-
|
|
125
|
-
if (fnProvider && !_.isFunction(fnProvider)) {
|
|
126
|
-
throw new Error('[HPM] Log provider config error. Expecting a function.')
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return result
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function isValidLevel(levelName) {
|
|
133
|
-
var validLevels = _.keys(LEVELS)
|
|
134
|
-
var isValid = _.includes(validLevels, levelName)
|
|
135
|
-
|
|
136
|
-
if (!isValid) {
|
|
137
|
-
throw new Error('[HPM] Log level error. Invalid logLevel.')
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return isValid
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* -> normal proxy
|
|
146
|
-
* => router
|
|
147
|
-
* ~> pathRewrite
|
|
148
|
-
* ≈> router + pathRewrite
|
|
149
|
-
*
|
|
150
|
-
* @param {String} originalPath
|
|
151
|
-
* @param {String} newPath
|
|
152
|
-
* @param {String} originalTarget
|
|
153
|
-
* @param {String} newTarget
|
|
154
|
-
* @return {String}
|
|
155
|
-
*/
|
|
156
|
-
function getArrow(originalPath, newPath, originalTarget, newTarget) {
|
|
157
|
-
var arrow = ['>']
|
|
158
|
-
var isNewTarget = originalTarget !== newTarget // router
|
|
159
|
-
var isNewPath = originalPath !== newPath // pathRewrite
|
|
160
|
-
|
|
161
|
-
if (isNewPath && !isNewTarget) {
|
|
162
|
-
arrow.unshift('~')
|
|
163
|
-
} else if (!isNewPath && isNewTarget) {
|
|
164
|
-
arrow.unshift('=')
|
|
165
|
-
} else if (isNewPath && isNewTarget) {
|
|
166
|
-
arrow.unshift('≈')
|
|
167
|
-
} else {
|
|
168
|
-
arrow.unshift('-')
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return arrow.join('')
|
|
172
|
-
}
|
package/lib/path-rewriter.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
var _ = require('lodash')
|
|
2
|
-
var logger = require('./logger').getInstance()
|
|
3
|
-
var ERRORS = require('./errors')
|
|
4
|
-
|
|
5
|
-
module.exports = {
|
|
6
|
-
create: createPathRewriter
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Create rewrite function, to cache parsed rewrite rules.
|
|
11
|
-
*
|
|
12
|
-
* @param {Object} rewriteConfig
|
|
13
|
-
* @return {Function} Function to rewrite paths; This function should accept `path` (request.url) as parameter
|
|
14
|
-
*/
|
|
15
|
-
function createPathRewriter(rewriteConfig) {
|
|
16
|
-
var rulesCache
|
|
17
|
-
|
|
18
|
-
if (!isValidRewriteConfig(rewriteConfig)) {
|
|
19
|
-
return
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (_.isFunction(rewriteConfig)) {
|
|
23
|
-
var customRewriteFn = rewriteConfig
|
|
24
|
-
return customRewriteFn
|
|
25
|
-
} else {
|
|
26
|
-
rulesCache = parsePathRewriteRules(rewriteConfig)
|
|
27
|
-
return rewritePath
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function rewritePath(path) {
|
|
31
|
-
var result = path
|
|
32
|
-
|
|
33
|
-
_.forEach(rulesCache, function(rule) {
|
|
34
|
-
if (rule.regex.test(path)) {
|
|
35
|
-
result = result.replace(rule.regex, rule.value)
|
|
36
|
-
logger.debug('[HPM] Rewriting path from "%s" to "%s"', path, result)
|
|
37
|
-
return false
|
|
38
|
-
}
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
return result
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function isValidRewriteConfig(rewriteConfig) {
|
|
46
|
-
if (_.isFunction(rewriteConfig)) {
|
|
47
|
-
return true
|
|
48
|
-
} else if (!_.isEmpty(rewriteConfig) && _.isPlainObject(rewriteConfig)) {
|
|
49
|
-
return true
|
|
50
|
-
} else if (
|
|
51
|
-
_.isUndefined(rewriteConfig) ||
|
|
52
|
-
_.isNull(rewriteConfig) ||
|
|
53
|
-
_.isEqual(rewriteConfig, {})
|
|
54
|
-
) {
|
|
55
|
-
return false
|
|
56
|
-
} else {
|
|
57
|
-
throw new Error(ERRORS.ERR_PATH_REWRITER_CONFIG)
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function parsePathRewriteRules(rewriteConfig) {
|
|
62
|
-
var rules = []
|
|
63
|
-
|
|
64
|
-
if (_.isPlainObject(rewriteConfig)) {
|
|
65
|
-
_.forIn(rewriteConfig, function(value, key) {
|
|
66
|
-
rules.push({
|
|
67
|
-
regex: new RegExp(key),
|
|
68
|
-
value: rewriteConfig[key]
|
|
69
|
-
})
|
|
70
|
-
logger.info(
|
|
71
|
-
'[HPM] Proxy rewrite rule created: "%s" ~> "%s"',
|
|
72
|
-
key,
|
|
73
|
-
rewriteConfig[key]
|
|
74
|
-
)
|
|
75
|
-
})
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return rules
|
|
79
|
-
}
|
package/lib/router.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
var _ = require('lodash')
|
|
2
|
-
var logger = require('./logger.js').getInstance()
|
|
3
|
-
|
|
4
|
-
module.exports = {
|
|
5
|
-
getTarget: getTarget
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function getTarget(req, config) {
|
|
9
|
-
var newTarget
|
|
10
|
-
var router = config.router
|
|
11
|
-
|
|
12
|
-
if (_.isPlainObject(router)) {
|
|
13
|
-
newTarget = getTargetFromProxyTable(req, router)
|
|
14
|
-
} else if (_.isFunction(router)) {
|
|
15
|
-
newTarget = router(req)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return newTarget
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function getTargetFromProxyTable(req, table) {
|
|
22
|
-
var result
|
|
23
|
-
var host = req.headers.host
|
|
24
|
-
var path = req.url
|
|
25
|
-
|
|
26
|
-
var hostAndPath = host + path
|
|
27
|
-
|
|
28
|
-
_.forIn(table, function(value, key) {
|
|
29
|
-
if (containsPath(key)) {
|
|
30
|
-
if (hostAndPath.indexOf(key) > -1) {
|
|
31
|
-
// match 'localhost:3000/api'
|
|
32
|
-
result = table[key]
|
|
33
|
-
logger.debug('[HPM] Router table match: "%s"', key)
|
|
34
|
-
return false
|
|
35
|
-
}
|
|
36
|
-
} else {
|
|
37
|
-
if (key === host) {
|
|
38
|
-
// match 'localhost:3000'
|
|
39
|
-
result = table[key]
|
|
40
|
-
logger.debug('[HPM] Router table match: "%s"', host)
|
|
41
|
-
return false
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
return result
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function containsPath(v) {
|
|
50
|
-
return v.indexOf('/') > -1
|
|
51
|
-
}
|