Last active
February 26, 2019 17:44
-
-
Save perpen/5a87605dc78783d2380ef44bc9b95ee7 to your computer and use it in GitHub Desktop.
Working on cephalopod/cephalo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
https://node-a/pod/3 -> pod-home app | |
https://node-a/pod/3/wetty -> http://localhost:3031 | |
https://node-a/pod/3/theia -> http://localhost:3032 | |
*/ | |
const http = require('http'); | |
const url = require('url'); | |
const fs = require('fs'); | |
const path = require('path'); | |
const PORT = 8080; | |
const INTERFACE = '127.0.0.1'; | |
const USER = null; | |
const POD_PORT_RANGE_START = 3000 | |
const POD_PORT_RANGE_WIDTH = 10 | |
const HOME_PATH_RX = new RegExp('^/pod/(\\d+)/?$'); | |
function home(req, res) { | |
var matches = HOME_PATH_RX.exec(req.url); | |
if (!matches) return false; | |
var pod_number = parseInt(matches[1]); | |
const config = {}; | |
res.setHeader('Content-type', 'text/html'); | |
const html = ` | |
<html> | |
<head> | |
<title>${config.pod_number}@node-a</title> | |
</head> | |
<body> | |
<div> | |
<h2>pod ${config.pod_number}@node-a</h2> | |
Owner: ${config.user_display_name} (${config.user})<br> | |
<a href="/pod/${config.pod_number}/wetty/">wetty</a> <br> | |
<a href="/pod/${config.pod_number}/theia/">theia</a> <br> | |
</div> | |
<div> | |
<h1>idea</h1> | |
<h2>pod ${config.pod_number}@node-a</h2> | |
Owner: ${config.user_display_name} (${config.user})<br> | |
<br> | |
To start <a href="/pod/${config.pod_number}/wetty/">wetty</a> enter the password for Joe: | |
<input type="password" name="password"/> | |
</div> | |
</body> | |
</html>`; | |
res.end(html); | |
return true; | |
}; | |
const UI_PATH_RX = new RegExp('^(/pod/(\\d+))((/(wetty|theia))(/.*)?)$'); | |
function ui(req, res) { | |
console.log("Request for " + req.url); | |
var proxy_params; | |
{ | |
var matches = UI_PATH_RX.exec(req.url); | |
if (!matches) return false; | |
req.headers['host'] = "127.0.0.1"; | |
// used to rewrite response cookies from post() | |
req.ui_context = matches[1] + matches[4]; | |
var pod_number = parseInt(matches[2]); | |
var pod_port = POD_PORT_RANGE_START + POD_PORT_RANGE_WIDTH * pod_number + 1; | |
proxy_params = { | |
host: "127.0.0.1", | |
port: pod_port, | |
method: req.method, | |
path: (matches[6] || '/'), | |
headers: req.headers | |
}; | |
} | |
if (proxy_params == null) { | |
return false; | |
} | |
console.log(proxy_params); | |
var proxy_req = http.request(proxy_params, function(proxy_res) { | |
var cooks = proxy_res.headers['set-cookie']; | |
if (cooks) { | |
var new_cooks = [cooks[0].replace(/^(.* Path=)(.*)$/, "$1" + req.ui_context + "$2")]; | |
proxy_res.headers['set-cookie'] = new_cooks; | |
} | |
if (proxy_res.headers.connection) { | |
if (req.headers.connection) { | |
proxy_res.headers.connection = req.headers.connection; | |
} else { | |
proxy_res.headers.connection = 'close'; | |
} | |
} | |
res.writeHead(proxy_res.statusCode, proxy_res.headers); | |
// FIXME ??? | |
if (proxy_res.statusCode === 304) { | |
res.end(); | |
return; | |
} | |
proxy_res.addListener('data', function(chunk) { | |
res.write(chunk, 'binary'); | |
}); | |
proxy_res.addListener('end', function() { | |
res.end(); | |
}); | |
}); | |
proxy_req.on('error', function(e) { | |
console.log("Request for " + req.url + " failed - back-end server caused exception : " + e); | |
res.writeHead(503, { | |
'content-type': 'text/html' | |
}); | |
res.end('An error was encountered talking to the back-end server.'); | |
return; | |
}); | |
req.addListener('data', function(chunk) { | |
proxy_req.write(chunk, 'binary'); | |
}); | |
req.addListener('end', function() { | |
proxy_req.end(); | |
}); | |
return true; | |
} | |
function fileHandler(req, res) { | |
console.log(`${req.method} ${req.url}`); | |
const parsedUrl = url.parse(req.url); | |
let pathname = `.${parsedUrl.pathname}`; | |
const allowed = [ | |
'./favicon.ico', | |
]; | |
if (!allowed.includes(pathname)) { | |
const msg = `File not allowed: ${pathname}`; | |
console.log(msg); | |
res.statusCode = 401; | |
res.end(msg); | |
return; | |
} | |
const ext = path.parse(pathname).ext; | |
const map = { | |
'.ico': 'image/x-icon', | |
'.html': 'text/html', | |
'.js': 'text/javascript', | |
'.json': 'application/json', | |
'.css': 'text/css', | |
'.png': 'image/png', | |
'.jpg': 'image/jpeg' | |
}; | |
fs.exists(pathname, function (exist) { | |
if(!exist) { | |
const msg = `File not found: ${pathname}`; | |
console.log(msg); | |
res.statusCode = 404; | |
res.end(msg); | |
return; | |
} | |
fs.readFile(pathname, function(err, data) { | |
if (err){ | |
const msg = `Error getting the file: ${err}.`; | |
console.log(msg); | |
res.statusCode = 500; | |
res.end(msg); | |
} else { | |
res.setHeader('Content-type', map[ext] || 'text/plain' ); | |
res.end(data); | |
} | |
}); | |
}) | |
}; | |
////////////////////////////////////////////////// | |
process.on('uncaughtException', function(err) { | |
console.log("ERROR:" + err); | |
console.log(err.stack); | |
}); | |
const handler = function(req, res) { | |
home(req, res) || ui(req, res) || fileHandler(req, res); | |
} | |
http.createServer().addListener("request", handler).listen(PORT, INTERFACE); | |
if (USER) { | |
console.log("Switching to user " + USER); | |
process.setuid(USER); | |
} | |
console.log(`Serving on ${INTERFACE}:${PORT}`); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment