所以我需要构建一个可以将URL路径映射到目标服务器的对象,如下所示:
/api : http://apiserver:8000
/api/v1 : http://apiv1server:8888
/api/v1/foo : http://foo:8080
/foo : http://foo:8080
和
function addRoute(path, server) {
setRoute(path, server)
}
addRoute('/api', 'http://apiserver:8000')
addRoute('/api/v1', 'http://apiv1server:8888')
每个查找都应该匹配最具体的路由,所以我最初的想法是这样的对象:
let map = {
api: {
v1: {
default: 'http://apiv1server:8000',
foo: 'http://foo:8080'
},
default: 'http://apiserver:8000'
},
foo: 'http://foo:8080'
}
这样您就可以使用一个简单的查找函数,如下所示:
function lookup(path) {
let result = null
path.split('/').forEach(key => {
result = map[key] || map[key].default
})
return result
}
但是尝试通过点(斜杠(符号设置对象已被证明非常困难,有什么想法吗?
还是有另一种更简单的方法可以做到这一点?
function lookup(path){
let arr = path.split("/").splice(1);
let m = {...map};
arr.forEach((e)=>{
m = m[e] || m.default;
})
return typeof(m) === "object" ? m.default : m;
}
你可以试试这个。
谢谢,由于我找不到设置路线的好方法,所以我转到了下面的递归方法:
let RouteMap = function (def) {
this.defaultRoute = def
this.map = {}
}
RouteMap.prototype = {
lookup: function (path) {
console.log('ROUTE MAP LOOKUP: ', path)
if (path) {
let parts = path.split('/')
let p = parts.shift()
if (this.map[p] instanceof RouteMap) {
return this.map[p].lookup(parts.join('/')) || this.defaultRoute
} else {
return this.map[p]
}
} else {
return this.defaultRoute
}
},
set: function (path, val) {
console.log('ROUTE SET: ', path, val)
if (path) {
let parts = path.split('/')
let p = parts.shift()
if (parts.length > 0) {
this.map[p] = this.map[p] || new RouteMap()
this.map[p].set(parts.join('/'), val)
} else {
this.map[p] = val
}
} else {
throw new Error('Path is', path)
}
},
addRoutesFromEnv: function (env) {
for (let key in process.env) {
if (key.startsWith('SERVICE_')) {
let val = process.env[key]
let parts = val.split('::')
if (parts.length === 2) {
this.set(parts[0], parts[1])
// this.add(parts[0], parts[1]) // /api/v1::http://v1host:8000
} else {
console.warn('Invalid SERVICE_NAME environment variable: should be SERVICE_NAME=/path/to/proxy::http://host:port, ', key)
}
}
}
console.log('ROUTE MAP: ', JSON.stringify(this.map, null, 2))
}
}
module.exports = RouteMap