-
Notifications
You must be signed in to change notification settings - Fork 1
/
http-proxy.js
143 lines (121 loc) · 3.82 KB
/
http-proxy.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
const httpProxy = require('http-proxy')
const fs = require('fs')
const https = require('https')
const http = require('http')
const uuidv4 = require('uuid/v4')
const Docker = require('dockerode')
let docker = new Docker({ socketPath: '/var/run/docker.sock' })
const containerOpts = {
Image: 'production-12-14',
Tty: false,
ExposedPorts: { "3000/tcp": {} },
HostConfig: {
Runtime: 'runsc',
Memory: 50000000,
CpuPeriod: 100000,
CpuQuota: 20000,
}
}
const ROOT = 'repl.space'
const PORT = 3000
let sessions = {}
// let isPendingStart = false
const options = {
key: fs.readFileSync('/etc/letsencrypt/live/repl.space-0001/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/repl.space-0001/fullchain.pem'),
};
const proxy = httpProxy.createProxyServer({
secure: true,
ws: true,
followRedirects: true,
});
const proxyServer = https.createServer(options, async (req, res) => {
if (req.method === 'DELETE') {
console.log(sessions, req.headers)
const containerId = sessions[req.headers.host].containerId
docker.getContainer(containerId).remove({ force: true })
delete sessions[req.headers.host]
res.writeHead(202)
return res.end('DELETED')
}
if (req.headers.host !== ROOT && !sessions[req.headers.host]) {
res.writeHead(404)
return res.end()
}
if (req.headers.host === ROOT) {
// if (isPendingStart) {
// res.writeHead(429)
// return res.end()
// }
let sessionId = uuidv4().slice(0, 6)
const template = require('fs').readFileSync(__dirname + '/assets/redirect.html', { encoding: 'utf-8' })
const html = template.replace('${}', `https://${sessionId}.${ROOT}`)
res.setHeader('content-type', 'text/html')
res.end(html)
docker.createContainer(containerOpts, (err, container) => {
// isPendingStart = true
container.start((err, data) => {
if (err) console.log(err);
container.inspect(container.id).then(data => {
const IPAddress = data.NetworkSettings.IPAddress
const containerURL = `http://${IPAddress}:${PORT}`
const sessionURL = sessionId + '.' + ROOT
sessions[sessionURL] = {
ip: containerURL,
containerId: container.id
}
console.log(container.id) // log container ID to console upon initialization
setTimeout(() => {
// isPendingStart = false
const fetch = require('node-fetch')
fetch(containerURL + '/session', {
method: 'POST',
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ sessionURL })
})
}, 5000)
})
})
})
return
// res.writeHead(301, {
// 'Location': `https://${sessionId}.${ROOT}`,
// 'Cache-Control': 'no-cache'
// })
}
proxy.web(
req,
res,
{ target: sessions[req.headers.host].ip },
(e) => log_error(e, req)
);
});
proxyServer.on('upgrade', (req, socket, head) => {
proxy.ws(req, socket, head, { target: sessions[req.headers.host].ip });
});
docker.listContainers((err, containers) => {
containers.forEach((containerInfo) => {
docker.getContainer(containerInfo.Id).remove({ force: true })
});
});
proxyServer.listen(443);
http.createServer((req, res) => {
// enable http deletes
if (req.method === 'DELETE') {
console.log(sessions, req.headers)
const containerId = sessions[req.headers.host].containerId
docker.getContainer(containerId).remove({ force: true })
delete sessions[req.headers.host]
res.writeHead(202)
return res.end('DELETED')
}
res.writeHead(301, { 'Location': 'https://' + req.headers.host })
res.end()
}).listen(80)
function log_error(e,req){
if(e){
console.error(e.message);
console.log(req.headers.host,'-->', sessions[req.headers.host].ip);
console.log('-----');
}
}