redbird
redbird copied to clipboard
Custom resolver, host and url rewriting
Hello,
I would like to defined a custom resolver to wildcard domain routing and do some redirection.
Configuration
{
"proxy": {
"redirections": [
{"from":"/foo","to":"something:9100"},
{"from":"/bar","to":"anotherapi:9102"},
]
}
}
Code
function custom_resolver(host, url)
{
var redirections = conf.proxy.redirections
for (var i in redirections)
{
var red = redirections[i];
var start = new RegExp("^"+ red.from)
if (start.test(url))
{
var rhost = "http://"+ red.to;
var rurl = url.replace(start, "")
return rhost + rurl;
}
}
};
But custom revoler only return host i guess ? So I can not "rewrite" the url.
The above code does not work as expected:
10.0.0.42/foo/folder -> http://something:9100/folder/foo/folder
Because I it return http://something:9100/folder and the original url is added at the end /foo/folder
However it is possible to "rewrite" the url with proxy.register, but not the host.
proxy.register("10.0.0.42/foo", "http://something:9100")
It do the url "rewriting" but only works when we access to 10.0.0.42, if there is another ip to connect the server, like 172.17.0.5, it does not works.
Is there any way to do this ? Did I miss something ? May be I have to return from custom_resolver another type, like an object, (an array does not works) ? Is there a maner to combine the both solution ?
King regards, Arnaud
Did you try to return an object with url (the target host), and path 'folder' ?
Hi, Actually, no, I didn't.
original return rhost + rurl
new return {url:rhost, path:rurl}
request url 10.0.0.60/foo/collections
resolved url (by my custom resolver)
host http://something:9100
url /collections
I getting the following message from the proxy
{"name":"redbird","hostname":"38b1c9cc8e81","pid":1,"level":40,"src":"10.0.0.60","url":"/foo/collections","msg":"no valid route found for given source","time":"2016-08-04T13:42:11.543Z","v":0}
- I m not sure if the url field (the target host), must start with protocol, such "http://". I tried with and without, it changed nothing.
- Same for the path, I tried, starting by / and not, it changed nothing as well.
After a quick look to the code: https://github.com/OptimalBits/redbird/blob/master/lib/proxy.js
The error came from _getTarget, line 448:
this.log && this.log.warn({src: src, url: req.url}, 'no valid route found for given source');
Which is due, I think, of the return condition from resolve, line 401:
startsWith(url, route.path)
I don't really understand this condition, the request url must start with the routing path ?
There is also in line 472 and 475 from _getTarget function:
// Fix request url if targetname specified.
req.url = path.join(target.pathname, req.url);
Which I think, does not allow to do what I want any way, rewrite the url and the path in the same time ?
I will have to look deeper into it, but if it is not possible to do it then we need to rethink the custom resolvers design.
Is this limitation still valid? I'm evaluating reverse proxies and that's something I would need. Overall, GREAT project!
https://github.com/backrunner/redbird/commit/7ae14a95ddf131dc6ce369e2446d7d669e2f5219 ↑ I just made this commit in my fork.
In the _getTarget method, req.url will always be added after target.pathname when req.url exists, so if you want to rewrite a URL, you can add a specific flag to the route object (i.e. the object returned in the buildRoute method) like my modification.
In my modification, if the custom resolver return a object that contains a property named rewriteTo, in the buildRoute method, the value will be passed to route.url, and a flag named isRewrite will be added to the routeObject. Then in the _getTarget method, when the flag exists, I use the target.pathname directly. The modification can perform a URL Rewriting well.