# Публикувайте локален сървър през тунел с PROXYSERVER() и PROXYCLIENT()

> Оставете Total.js сървър с публичен адрес да препраща заявки към програма, която работи само на частна машина, чрез WebSocket тунел, който отваря частната страна.

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

`PROXY()` препраща заявка към сървър, до който прокситата може да стигне. Тунелът е за обратния случай: програмата е на лаптоп или зад защитна стена, така че никой не може да се свърже с нея, но тя може да се свърже навън. `PROXYSERVER()` и `PROXYCLIENT()` постигат това с един WebSocket, който отваря частната страна:

- `PROXYSERVER([endpoint], [socketendpoint], [logger])` работи на публичния сървър. Всяка заявка под `endpoint` (по подразбиране `/`) се изпраща през тунела; `socketendpoint` (по подразбиране `/`) е WebSocket адресът, където се свързва клиентът. Използвайте **различни** адреси, когато същото приложение обслужва и нещо друго: проксито на `/` поема всяка заявка, дори тези към вашите собствени маршрути (работи преди тях). `logger` е функция (по подразбиране: печата с дата); подайте `null` за никакъв.
- `PROXYCLIENT(serverurl, port, [logger])` работи на частната страна (в този пример адресът на сървъра се изгражда с `CONF.$port`, порта на приложението). `serverurl` е WebSocket адресът на сървъра (`ws://` или `wss://`; `http` се сменя с `ws`), а `port` е `3000` или `ip:3000`, локалната програма, която получава заявките. Връща WebSocket клиента.
- **Един клиент наведнъж:** когато се свърже втори клиент, сървърът го затваря с кода `4001`. Без клиент отговорът на сървъра е `Not yet available.`.
- Локалната програма получава **пълния път на оригиналната заявка**, включително `endpoint` (`/tunnel/hello`), заглавията на посетителя и заглавие `x-proxy: Total.js`, като `host` е зададен на локалния адрес.
- WebSocket маршрутът няма собствена автентикация: не го публикувайте без нещо пред него, което решава кой може да се свърже (адресът като тайна, ваш собствен `check`, защитна стена).

Тук едно приложение е и двете страни: малка локална програма на порт 9511 (върши работа всяка програма), сървърът на `/tunnel/` и клиентът, който се свързва със същото приложение.

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