diff options
Diffstat (limited to 'packages/integrations/node/src/http-server.ts')
-rw-r--r-- | packages/integrations/node/src/http-server.ts | 131 |
1 files changed, 0 insertions, 131 deletions
diff --git a/packages/integrations/node/src/http-server.ts b/packages/integrations/node/src/http-server.ts deleted file mode 100644 index 904937601..000000000 --- a/packages/integrations/node/src/http-server.ts +++ /dev/null @@ -1,131 +0,0 @@ -import https from 'https'; -import fs from 'node:fs'; -import http from 'node:http'; -import { fileURLToPath } from 'node:url'; -import send from 'send'; -import enableDestroy from 'server-destroy'; - -interface CreateServerOptions { - client: URL; - port: number; - host: string | undefined; - removeBase: (pathname: string) => string; - assets: string; -} - -function parsePathname(pathname: string, host: string | undefined, port: number) { - try { - const urlPathname = new URL(pathname, `http://${host}:${port}`).pathname; - return decodeURI(encodeURI(urlPathname)); - } catch (err) { - return undefined; - } -} - -export function createServer( - { client, port, host, removeBase, assets }: CreateServerOptions, - handler: http.RequestListener -) { - // The `base` is removed before passed to this function, so we don't - // need to check for it here. - const assetsPrefix = `/${assets}/`; - function isImmutableAsset(pathname: string) { - return pathname.startsWith(assetsPrefix); - } - - const listener: http.RequestListener = (req, res) => { - if (req.url) { - let pathname: string | undefined = removeBase(req.url); - pathname = pathname[0] === '/' ? pathname : '/' + pathname; - const encodedURI = parsePathname(pathname, host, port); - - if (!encodedURI) { - res.writeHead(400); - res.end('Bad request.'); - return res; - } - - const stream = send(req, encodedURI, { - root: fileURLToPath(client), - dotfiles: pathname.startsWith('/.well-known/') ? 'allow' : 'deny', - }); - - let forwardError = false; - - stream.on('error', (err) => { - if (forwardError) { - console.error(err.toString()); - res.writeHead(500); - res.end('Internal server error'); - return; - } - // File not found, forward to the SSR handler - handler(req, res); - }); - stream.on('headers', (_res: http.ServerResponse<http.IncomingMessage>) => { - if (isImmutableAsset(encodedURI)) { - // Taken from https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#immutable - _res.setHeader('Cache-Control', 'public, max-age=31536000, immutable'); - } - }); - stream.on('directory', () => { - // On directory find, redirect to the trailing slash - let location: string; - if (req.url!.includes('?')) { - const [url = '', search] = req.url!.split('?'); - location = `${url}/?${search}`; - } else { - location = req.url + '/'; - } - - res.statusCode = 301; - res.setHeader('Location', location); - res.end(location); - }); - stream.on('file', () => { - forwardError = true; - }); - stream.pipe(res); - } else { - handler(req, res); - } - }; - - let httpServer: - | http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> - | https.Server<typeof http.IncomingMessage, typeof http.ServerResponse>; - - if (process.env.SERVER_CERT_PATH && process.env.SERVER_KEY_PATH) { - httpServer = https.createServer( - { - key: fs.readFileSync(process.env.SERVER_KEY_PATH), - cert: fs.readFileSync(process.env.SERVER_CERT_PATH), - }, - listener - ); - } else { - httpServer = http.createServer(listener); - } - httpServer.listen(port, host); - enableDestroy(httpServer); - - // Resolves once the server is closed - const closed = new Promise<void>((resolve, reject) => { - httpServer.addListener('close', resolve); - httpServer.addListener('error', reject); - }); - - return { - host, - port, - closed() { - return closed; - }, - server: httpServer, - stop: async () => { - await new Promise((resolve, reject) => { - httpServer.destroy((err) => (err ? reject(err) : resolve(undefined))); - }); - }, - }; -} |