ForgeTotal.js 5
fr

Total.js 5

Publier un serveur local par un tunnel avec PROXYSERVER() et PROXYCLIENT()

Total.js 5 · total5@0.0.19 proxytunnelwebsocketintegrations Exécutée avec Total.js 5

PROXY() transmet une requête à un serveur que le proxy peut atteindre. Un tunnel sert au cas inverse : le programme est sur un portable ou derrière un pare-feu, personne ne peut donc s'y connecter, mais lui peut se connecter vers l'extérieur. PROXYSERVER() et PROXYCLIENT() le réalisent avec un seul WebSocket que le côté privé ouvre :

  • PROXYSERVER([endpoint], [socketendpoint], [logger]) s'exécute sur le serveur public. Chaque requête sous endpoint (par défaut /) passe par le tunnel ; socketendpoint (par défaut /) est l'adresse WebSocket où le client se connecte. Utilisez des adresses différentes quand la même application sert autre chose : un proxy sur / prend toutes les requêtes, y compris celles de vos propres routes (il s'exécute avant elles). logger est une fonction (par défaut : écrit avec la date) ; passez null pour aucun.
  • PROXYCLIENT(serverurl, port, [logger]) s'exécute du côté privé (dans cet exemple l'adresse du serveur est construite avec CONF.$port, le port de l'application). serverurl est l'adresse WebSocket du serveur (ws:// ou wss:// ; http est changé en ws) et port est 3000 ou ip:3000, le programme local qui reçoit les requêtes. Il renvoie le client WebSocket.
  • Un client à la fois : quand un second client se connecte, le serveur le ferme avec le code 4001. Sans client, la réponse du serveur est Not yet available..
  • Le programme local reçoit le chemin complet de la requête d'origine, y compris l'endpoint (/tunnel/hello), les en-têtes du visiteur et un en-tête x-proxy: Total.js, avec host défini à l'adresse locale.
  • La route WebSocket n'a pas d'authentification propre : ne la publiez pas sans quelque chose devant elle qui décide qui peut se connecter (l'adresse est le secret, un check à vous, un pare-feu).

Ici une application est les deux côtés : un petit programme local sur le port 9511 (n'importe quel programme conviendrait), le serveur sur /tunnel/ et le client qui se connecte à la même application.

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