# Anfragen an einen anderen Server weiterleiten

> Nutze PROXY(), um einem URL-Präfix einen Upstream-Server zuzuordnen, wähle, wie der Pfad kopiert wird, und leite mit $.proxy() eine einzelne Route weiter.

Framework: total5
Product: Total.js 5 (total5@0.0.19)
Language: de
Content-SHA256: 3a9b538bd5adfd99bea7f5cf782bb0d9123500d39ab56e058b382d9cc41799bc
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: total5-installed@total5@0.0.19
Review: not-recorded

`PROXY(prefix, target)` leitet jede Anfrage unterhalb eines URL-Präfixes an einen anderen Server weiter und streamt die Antwort zurück, sodass eine Total.js-Anwendung vor mehreren Diensten stehen kann. Es läuft vor den Routen, ein von `PROXY()` behandeltes Präfix erreicht also nie `ROUTE()`. Die Anfrage wird mit Methode, Headern und Body weitergereicht; die Header `x-forwarded-for`, `x-forwarded-url` und `x-forwarded-host` informieren den Upstream über die ursprüngliche Anfrage. `PROXY(prefix)` ohne Ziel entfernt den Proxy.

Das zurückgegebene Objekt konfiguriert den Proxy: `.copy(type)` wählt, welcher Teil des Pfads an den Upstream gesendet wird (siehe unten), `.timeout(ms)` begrenzt die Wartezeit, `.check(fn)` bewirkt, dass der Proxy nur greift, wenn `fn(ctrl)` true zurückgibt, und `.before(uri, ctrl)` kann die ausgehende Anfrage ändern, zum Beispiel um einen Header hinzuzufügen.

`.copy()` akzeptiert `none` (Standard), `extend` oder `replace`. Mit **`none`** erhält der Upstream nur den Pfad des Ziels plus den Query-String: `/none/a/b/?q=1` wird für das Ziel `http://host/base/` zu `/base/?q=1`. Mit **`extend`** wird der Rest des Anfragepfads an den Pfad des Ziels angehängt: `/extend/a/b/?q=1` wird zu `/base/a/b/?q=1`, was du für ein Gateway willst. `replace` verhält sich wie `extend`, wenn das Ziel einen eigenen Pfad hat; ist das Ziel nur ein Host, sendet es den Rest des Pfads **ohne den Query-String**, bevorzuge also `extend`.

Für eine einzelne Route verwende `$.proxy(url)`: Es sendet die aktuelle Anfrage (Methode, Query-String, Body und Header) an `url` und gibt die Antwort des Upstreams mit ihrem Statuscode zurück.

```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/');
}
```
