# Pubblica un server locale tramite un tunnel con PROXYSERVER() e PROXYCLIENT()

> Lascia che un server Total.js con indirizzo pubblico inoltri richieste a un programma che gira solo su una macchina privata, con un tunnel WebSocket aperto dal lato privato.

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

`PROXY()` inoltra una richiesta a un server che il proxy può raggiungere. Un tunnel serve nel caso opposto: il programma è su un portatile o dietro un firewall, quindi nessuno può connettersi ad esso, ma esso può connettersi verso l'esterno. `PROXYSERVER()` e `PROXYCLIENT()` lo ottengono con un solo WebSocket aperto dal lato privato:

- `PROXYSERVER([endpoint], [socketendpoint], [logger])` gira sul server pubblico. Ogni richiesta sotto `endpoint` (predefinito `/`) viene inviata attraverso il tunnel; `socketendpoint` (predefinito `/`) è l'indirizzo WebSocket dove si connette il client. Usa indirizzi **diversi** quando la stessa applicazione serve altro: un proxy su `/` prende ogni richiesta, anche quelle delle tue route (viene eseguito prima di esse). `logger` è una funzione (predefinito: stampa con la data); passa `null` per nessuno.
- `PROXYCLIENT(serverurl, port, [logger])` gira sul lato privato (in questo esempio l'indirizzo del server è costruito con `CONF.$port`, la porta dell'applicazione). `serverurl` è l'indirizzo WebSocket del server (`ws://` o `wss://`; `http` viene cambiato in `ws`) e `port` è `3000` o `ip:3000`, il programma locale che riceve le richieste. Restituisce il client WebSocket.
- **Un client alla volta:** quando si connette un secondo client, il server lo chiude con il codice `4001`. Senza client la risposta del server è `Not yet available.`.
- Il programma locale riceve il **percorso completo della richiesta originale**, incluso l'`endpoint` (`/tunnel/hello`), le intestazioni del visitatore e un'intestazione `x-proxy: Total.js`, con `host` impostato sull'indirizzo locale.
- La route WebSocket non ha un'autenticazione propria: non pubblicarla senza qualcosa davanti che decida chi può connettersi (l'indirizzo come segreto, un `check` tuo, un firewall).

Qui un'applicazione è entrambi i lati: un piccolo programma locale sulla porta 9511 (andrebbe bene qualsiasi programma), il server su `/tunnel/` e il client che si connette alla stessa applicazione.

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