1 | const {promisify} = require('util')
|
2 | const {createServer} = require('http')
|
3 | const parseUrl = require('parseurl')
|
4 | const send = require('send')
|
5 | const {untilBefore} = require('until-before')
|
6 | const {getHost} = require('./helpers/getHost')
|
7 |
|
8 | const MOVED_PERMANENTLY = 301
|
9 | const PERMANENT_REDIRECT = 308
|
10 | const MISDIRECTED_REQUEST = 421
|
11 | const INTERNAL_SERVER_ERROR = 500
|
12 |
|
13 | const ACME_PREFIX = '/.well-known/acme-challenge/'
|
14 |
|
15 | const DEFAULT_PORT_HTTPS = 443
|
16 |
|
17 | module.exports.redirect = async (options) => {
|
18 | function requestListener (request, response) {
|
19 | const hostname = untilBefore.call(getHost(request), ':')
|
20 | const {pathname} = parseUrl(request)
|
21 |
|
22 | console.log(`HTTP/${request.httpVersion} ${request.method} ${request.url}`)
|
23 |
|
24 | if (pathname.startsWith(ACME_PREFIX)) {
|
25 | if (options.acme.redirect.length > 0) {
|
26 | const location = options.acme.redirect + pathname
|
27 | response.writeHead(MOVED_PERMANENTLY, {location})
|
28 | response.end()
|
29 | return
|
30 | } else if (options.acme.webroot.length > 0) {
|
31 | const {pathname} = parseUrl(request)
|
32 | const sendOptions = {
|
33 | root: options.acme.webroot,
|
34 | etag: false,
|
35 | lastModified: false
|
36 | }
|
37 | send(request, pathname, sendOptions)
|
38 | .on('error', (error) => {
|
39 | response.statusCode = error.status || INTERNAL_SERVER_ERROR
|
40 | response.end()
|
41 | })
|
42 | .pipe(response)
|
43 | return
|
44 | }
|
45 | }
|
46 |
|
47 | if (hostname === '') {
|
48 | response.writeHead(MISDIRECTED_REQUEST)
|
49 | response.end()
|
50 | } else {
|
51 | const location = options.http.to === DEFAULT_PORT_HTTPS
|
52 | ? `https://${hostname}${request.url}`
|
53 | : `https://${hostname}:${options.http.to}${request.url}`
|
54 | response.writeHead(PERMANENT_REDIRECT, {location})
|
55 | response.end()
|
56 | }
|
57 | }
|
58 | const server = createServer(requestListener)
|
59 | await promisify(server.listen.bind(server))(options.http.from)
|
60 | return server
|
61 | }
|