# Reencaminhar pedidos para outro servidor

> Use PROXY() para associar um prefixo de URL a um servidor de destino, escolha como o caminho é copiado e $.proxy() para reencaminhar uma única rota.

Framework: total5
Product: Total.js 5 (total5@0.0.19)
Language: pt
Content-SHA256: 7cfab0a3687a1cdfd93c9784b6ebaf8e1101df029d252eb84db6ccf4f901356f
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: total5-installed@total5@0.0.19
Review: not-recorded

`PROXY(prefix, target)` reencaminha para outro servidor todos os pedidos sob um prefixo de URL e devolve a resposta em streaming, de modo que uma aplicação Total.js pode ficar à frente de vários serviços. Corre antes das rotas, por isso um prefixo tratado por `PROXY()` nunca chega a `ROUTE()`. O pedido é passado com o seu método, cabeçalhos e corpo; os cabeçalhos `x-forwarded-for`, `x-forwarded-url` e `x-forwarded-host` informam o servidor de destino sobre o pedido original. `PROXY(prefix)` sem destino remove o proxy.

O objeto que devolve configura o proxy: `.copy(type)` escolhe que parte do caminho é enviada para o destino (ver abaixo), `.timeout(ms)` limita a espera, `.check(fn)` faz com que o proxy só se aplique quando `fn(ctrl)` devolve true e `.before(uri, ctrl)` pode alterar o pedido de saída, por exemplo para acrescentar um cabeçalho.

`.copy()` aceita `none` (por omissão), `extend` ou `replace`. Com **`none`** o destino só recebe o caminho do destino mais a query string: `/none/a/b/?q=1` torna-se `/base/?q=1` para o destino `http://host/base/`. Com **`extend`** o resto do caminho do pedido é acrescentado ao caminho do destino: `/extend/a/b/?q=1` torna-se `/base/a/b/?q=1`, que é o que se quer para um gateway. `replace` comporta-se como `extend` quando o destino tem um caminho próprio; quando o destino é apenas um host, envia o resto do caminho **sem a query string**, por isso prefira `extend`.

Para uma única rota use `$.proxy(url)`: envia o pedido atual (método, query string, corpo e cabeçalhos) para `url` e devolve a resposta do destino com o seu código de estado.

```js controllers/proxy.js
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/');
}
```
