# Publicera en lokal server genom en tunnel med PROXYSERVER() och PROXYCLIENT()

> Låt en Total.js-server med offentlig adress vidarebefordra förfrågningar till ett program som bara körs på en privat maskin, med en WebSocket-tunnel som den privata sidan öppnar.

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

`PROXY()` vidarebefordrar en förfrågan till en server som proxyn kan nå. En tunnel är till för det motsatta fallet: programmet finns på en bärbar dator eller bakom en brandvägg, så ingen kan ansluta till det, men det kan ansluta utåt. `PROXYSERVER()` och `PROXYCLIENT()` åstadkommer det med en WebSocket som den privata sidan öppnar:

- `PROXYSERVER([endpoint], [socketendpoint], [logger])` körs på den offentliga servern. Varje förfrågan under `endpoint` (standard `/`) skickas genom tunneln; `socketendpoint` (standard `/`) är WebSocket-adressen där klienten ansluter. Använd **olika** adresser när samma applikation serverar något annat: en proxy på `/` tar varje förfrågan, även dem till dina egna routes (den körs före dem). `logger` är en funktion (standard: skriver ut med datum); skicka `null` för ingen.
- `PROXYCLIENT(serverurl, port, [logger])` körs på den privata sidan (i det här exemplet byggs serverns adress med `CONF.$port`, applikationens port). `serverurl` är serverns WebSocket-adress (`ws://` eller `wss://`; `http` ändras till `ws`) och `port` är `3000` eller `ip:3000`, det lokala programmet som tar emot förfrågningarna. Den returnerar WebSocket-klienten.
- **En klient i taget:** när en andra klient ansluter stänger servern den med koden `4001`. Utan klient är serverns svar `Not yet available.`.
- Det lokala programmet får **hela sökvägen för den ursprungliga förfrågan**, inklusive `endpoint` (`/tunnel/hello`), besökarens headers och en header `x-proxy: Total.js`, med `host` satt till den lokala adressen.
- WebSocket-routen har ingen egen autentisering: publicera den inte utan något framför den som avgör vem som får ansluta (adressen som hemlighet, en egen `check`, en brandvägg).

Här är en applikation båda sidorna: ett litet lokalt program på port 9511 (vilket program som helst duger), servern på `/tunnel/` och klienten som ansluter till samma applikation.

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