-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathserver.js
114 lines (94 loc) · 3.3 KB
/
server.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
//
// The purpose of this is very simple: it accepts HTTP requests
// and redirect all requests to the specified location with the
// specified HTTP status code.
//
// 301 Moved Permanently
// 302 Found
// 303 See Other
// 307 Temporary Redirect
//
const express = require('express')
const path = require('path')
const fs = require('fs')
async function loadHosts() {
try {
const hostPath = process.env.HOSTS_FILE_PATH || '/etc/redirect/hosts.json'
const hostsData = await fs.promises.readFile(hostPath, 'utf8')
return JSON.parse(hostsData)
} catch (e) {
if (e.code !== 'ENOENT') console.error('error loading hosts file:', e)
return
}
}
async function runMultiHost(hosts) {
const app = express()
const port = process.env.HTTP_PORT || 80
const index = {}
// Disable x-powered-by header
app.disable('x-powered-by')
hosts.forEach(host => {
if (!host.source || !host.destination) {
console.log(`invalid host: ${host}`)
return
}
// Ensure we strip any trailing slashes from host.destination
if (host.destination.endsWith('/')) {
host.destination = host.destination.substr(0, host.destination.length - 1)
}
// Ensure defaults are set
host.statusCode = host.statusCode || 307
host.preserveUrl = host.preserveUrl || false
// Add to the index for quick lookup
index[host.source] = host
console.log(`+ redirecting ${host.source} to ${host.destination} with statusCode ${host.statusCode}`)
})
app.get('*', (req, res, next) => {
let host = req.headers.host
let destination = null
let statusCode = 307
if (index[host + req.url]) {
const hostUrl = host + req.url
destination = index[hostUrl].preserveUrl ? index[hostUrl].destination + req.url : index[hostUrl].destination
statusCode = index[hostUrl].statusCode
} else if (index[host]) {
destination = index[host].preserveUrl ? index[host].destination : index[host].destination
statusCode = index[host].statusCode
}
if (destination) {
if (destination.substring(0, 4) != 'http') destination = `${req.protocol}://${destination}`
return res.redirect(statusCode, destination)
}
// Otherwise, 404
next()
})
app.listen(port, () => {
console.log(`adamkdean/redirect listening on port ${port}`)
})
}
async function runSingleHost() {
const app = express()
const port = process.env.HTTP_PORT || 80
const statusCode = parseInt(process.env.REDIRECT_STATUS_CODE) || 307
const preserveUrl = process.env.PRESERVE_URL || false
// Disable x-powered-by header
app.disable('x-powered-by')
let location = process.env.REDIRECT_LOCATION || ''
if (!location) {
console.error('error: running in single host mode and REDIRECT_LOCATION is not set!')
process.exit(1)
}
// Ensure we strip any trailing slashes from REDIRECT_LOCATION
if (location.endsWith('/')) location = location.substr(0, location.length - 1)
app.get('*', (req, res) => res.redirect(statusCode, preserveUrl ? location + req.url : location))
app.listen(port, () => {
console.log(`+ redirecting all requests to ${location} with statusCode ${statusCode}`)
console.log(`adamkdean/redirect listening on port ${port}`)
})
}
async function main() {
const hosts = await loadHosts()
if (hosts) runMultiHost(hosts)
else runSingleHost()
}
main()