# Einen lokalen Server über einen Tunnel mit PROXYSERVER() und PROXYCLIENT() veröffentlichen

> Lass einen Total.js-Server mit öffentlicher Adresse Anfragen an ein Programm weiterleiten, das nur auf einem privaten Rechner läuft, über einen WebSocket-Tunnel, den die private Seite öffnet.

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

`PROXY()` leitet eine Anfrage an einen Server weiter, den der Proxy erreichen kann. Ein Tunnel ist für den umgekehrten Fall: Das Programm läuft auf einem Laptop oder hinter einer Firewall, sodass niemand sich damit verbinden kann, es selbst aber nach außen verbinden kann. `PROXYSERVER()` und `PROXYCLIENT()` erledigen das mit einem WebSocket, den die private Seite öffnet:

- `PROXYSERVER([endpoint], [socketendpoint], [logger])` läuft auf dem öffentlichen Server. Jede Anfrage unterhalb von `endpoint` (Standard `/`) wird durch den Tunnel geschickt; `socketendpoint` (Standard `/`) ist die WebSocket-Adresse, an der sich der Client verbindet. Verwende **verschiedene** Adressen, wenn dieselbe Anwendung noch etwas anderes ausliefert: Ein Proxy auf `/` nimmt jede Anfrage, auch die deiner eigenen Routen (er läuft vor ihnen). `logger` ist eine Funktion (Standard: gibt mit Datum aus); übergib `null` für keinen.
- `PROXYCLIENT(serverurl, port, [logger])` läuft auf der privaten Seite (in diesem Beispiel wird die Adresse des Servers mit `CONF.$port`, dem Port der Anwendung, gebaut). `serverurl` ist die WebSocket-Adresse des Servers (`ws://` oder `wss://`; `http` wird zu `ws`) und `port` ist `3000` oder `ip:3000`, das lokale Programm, das die Anfragen erhält. Es gibt den WebSocket-Client zurück.
- **Ein Client gleichzeitig:** Verbindet sich ein zweiter Client, schließt der Server ihn mit dem Code `4001`. Ohne Client lautet die Antwort des Servers `Not yet available.`.
- Das lokale Programm erhält den **vollständigen Pfad der ursprünglichen Anfrage**, einschließlich des `endpoint` (`/tunnel/hello`), die Header des Besuchers und einen Header `x-proxy: Total.js`, mit `host` auf die lokale Adresse gesetzt.
- Die WebSocket-Route hat keine eigene Authentifizierung: Veröffentliche sie nicht ohne etwas davor, das entscheidet, wer sich verbinden darf (die Adresse als Geheimnis, ein eigenes `check`, eine Firewall).

Hier ist eine Anwendung beide Seiten: ein kleines lokales Programm auf Port 9511 (jedes Programm täte es), der Server auf `/tunnel/` und der Client, der sich mit derselben Anwendung verbindet.

```js definitions/local.js
// The program that is "private": an ordinary HTTP server that only listens on the loopback address
require('http').createServer(function(req, res) {
	res.writeHead(200, { 'content-type': 'application/json' });
	res.end(JSON.stringify({ path: req.url, via: req.headers['x-proxy'] || null, host: req.headers.host }));
}).listen(9511, '127.0.0.1');
```

```js controllers/tunnel.js
exports.install = function() {
	ROUTE('GET /status/', status);
	ROUTE('POST /connect/', connect);
};

// The public side: /tunnel/* goes through the tunnel, the WebSocket of the client is /tunnel-socket/. No logger.
PROXYSERVER('/tunnel/', '/tunnel-socket/', null);

let client = null;

function connect($) {
	client = PROXYCLIENT('ws://127.0.0.1:' + CONF.$port + '/tunnel-socket/', '9511', null);
	$.json({ connecting: true });
}

function status($) {
	$.json({ connected: !!client });
}
```
