# Publică un server local printr-un tunel cu PROXYSERVER() și PROXYCLIENT()

> Lasă un server Total.js cu adresă publică să redirecționeze cereri către un program care rulează doar pe o mașină privată, cu un tunel WebSocket pe care îl deschide partea privată.

Framework: total5
Product: Total.js 5 (total5@0.0.19)
Language: ro
Content-SHA256: 115705e4bb02ec58c86cb10b306094f164b54fb6a8e1f018c1133a108afb8b43
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: total5-installed@total5@0.0.19
Review: not-recorded

`PROXY()` redirecționează o cerere către un server la care proxy-ul poate ajunge. Un tunel este pentru cazul opus: programul este pe un laptop sau în spatele unui firewall, deci nimeni nu se poate conecta la el, dar el se poate conecta spre exterior. `PROXYSERVER()` și `PROXYCLIENT()` fac asta cu un singur WebSocket pe care îl deschide partea privată:

- `PROXYSERVER([endpoint], [socketendpoint], [logger])` rulează pe serverul public. Fiecare cerere sub `endpoint` (implicit `/`) este trimisă prin tunel; `socketendpoint` (implicit `/`) este adresa WebSocket unde se conectează clientul. Folosește adrese **diferite** când aceeași aplicație servește și altceva: un proxy pe `/` preia orice cerere, și pe cele ale rutelor tale (rulează înaintea lor). `logger` este o funcție (implicit: tipărește cu data); transmite `null` pentru niciuna.
- `PROXYCLIENT(serverurl, port, [logger])` rulează pe partea privată (în acest exemplu adresa serverului este construită cu `CONF.$port`, portul aplicației). `serverurl` este adresa WebSocket a serverului (`ws://` sau `wss://`; `http` se schimbă în `ws`) și `port` este `3000` sau `ip:3000`, programul local care primește cererile. Returnează clientul WebSocket.
- **Un singur client odată:** când se conectează un al doilea client, serverul îl închide cu codul `4001`. Fără client, răspunsul serverului este `Not yet available.`.
- Programul local primește **calea întreagă a cererii originale**, inclusiv `endpoint` (`/tunnel/hello`), antetele vizitatorului și un antet `x-proxy: Total.js`, cu `host` setat la adresa locală.
- Ruta WebSocket nu are autentificare proprie: nu o publica fără ceva în față care să decidă cine se poate conecta (adresa ca secret, un `check` al tău, un firewall).

Aici o aplicație este ambele părți: un mic program local pe portul 9511 (ar merge orice program), serverul pe `/tunnel/` și clientul care se conectează la aceeași aplicație.

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