Forward requests to another server
PROXY(prefix, target) forwards every request below a URL prefix to another server and streams the answer back, so one Total.js app can sit in front of several services. It runs before the routes, so a prefix handled by PROXY() never reaches ROUTE(). The request is passed on with its method, headers and body; the headers x-forwarded-for, x-forwarded-url and x-forwarded-host tell the upstream about the original request. PROXY(prefix) without a target removes the proxy.
The object it returns configures the proxy: .copy(type) chooses which part of the path is sent upstream (see below), .timeout(ms) limits the wait, .check(fn) makes the proxy apply only when fn(ctrl) returns true and .before(uri, ctrl) can change the outgoing request, for example to add a header.
.copy() takes none (the default), extend or replace. With none the upstream only receives the path of the target plus the query string: /none/a/b/?q=1 becomes /base/?q=1 for the target http://host/base/. With extend the rest of the request path is appended to the target path: /extend/a/b/?q=1 becomes /base/a/b/?q=1, which is what you want for a gateway. replace behaves like extend when the target has a path of its own; when the target is just a host it sends the rest of the path without the query string, so prefer extend.
For a single route use $.proxy(url): it sends the current request (method, query string, body and headers) to url and returns the upstream answer with its status code.
const Http = require('http');
// A small upstream server that reports what it received
Http.createServer(function(req, res) {
res.writeHead(200, { 'content-type': 'application/json' });
res.end(JSON.stringify({ method: req.method, url: req.url, token: req.headers['x-token'] || null, forwarded: !!req.headers['x-forwarded-url'] }));
}).listen(9411, '127.0.0.1');
// One proxy per copy mode, to see the difference (the target has the path /base/)
PROXY('/none/', 'http://127.0.0.1:9411/base/');
PROXY('/extend/', 'http://127.0.0.1:9411/base/').copy('extend');
PROXY('/plain/', 'http://127.0.0.1:9411/base/').copy('replace');
// Everything below /service/ goes to the upstream, and a header is added on the way
PROXY('/service/', 'http://127.0.0.1:9411/').copy('extend').before(function(uri, ctrl) {
uri.headers['x-token'] = 'secret';
});
exports.install = function() {
ROUTE('GET /single/', single);
};
function single($) {
$.proxy('http://127.0.0.1:9411/from-route/');
}