diff --git a/.changeset/mighty-wasps-perform.md b/.changeset/mighty-wasps-perform.md new file mode 100644 index 000000000000..96c13ed481c2 --- /dev/null +++ b/.changeset/mighty-wasps-perform.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/adapter-node': minor +--- + +feat: add opt-in HTTPS and HTTP/2 support diff --git a/documentation/docs/25-build-and-deploy/40-adapter-node.md b/documentation/docs/25-build-and-deploy/40-adapter-node.md index 575c6b5296df..1e4bf8490ed7 100644 --- a/documentation/docs/25-build-and-deploy/40-adapter-node.md +++ b/documentation/docs/25-build-and-deploy/40-adapter-node.md @@ -110,6 +110,18 @@ We instead read from the _right_, accounting for the number of trusted proxies. The maximum request body size to accept in bytes including while streaming. Defaults to 512kb. You can disable this option with a value of 0 and implement a custom check in [`handle`](hooks#server-hooks-handle) if you need something more advanced. +### `CERT_PATH`, `CERT_KEY_PATH`, and `HTTPS_PORT`: +By default, the server only listens for plain HTTP requests. To enable an additional HTTPS endpoint, you must provide the `CERT_PATH` and `CERT_KEY_PATH` environment variables pointing to a file containing a valid certificate and a file containing its associated private key respectively, both in the PEM format. +The files are read once on startup, so if the contents of the files change, the app will need to be restarted. + +The default port that will be used for the HTTPS endpoint is 3001. You can customize this via the `HTTPS_PORT` environment variable. + +### `NO_HTTP2`: +By default, the HTTPS endpoint will support HTTP/2 as well as HTTP/1.1. If, for some reason, supporting HTTP/2 isn't desirable, you can disable it by setting the `NO_HTTP2` environment variable to a non-empty value (e.g. `1`). + +### `ONLY_HTTPS`: +If you only need an HTTPS endpoint and want to opt out of the default plain HTTP one, you can do so by setting the `ONLY_HTTPS` environment variable to a non-empty value (e.g. `1`). + ## Options The adapter can be configured with various options: diff --git a/packages/adapter-node/src/env.js b/packages/adapter-node/src/env.js index 841bddf2c237..ec791b3cdc29 100644 --- a/packages/adapter-node/src/env.js +++ b/packages/adapter-node/src/env.js @@ -9,7 +9,12 @@ const expected = new Set([ 'ADDRESS_HEADER', 'PROTOCOL_HEADER', 'HOST_HEADER', - 'BODY_SIZE_LIMIT' + 'BODY_SIZE_LIMIT', + 'CERT_PATH', + 'CERT_KEY_PATH', + 'HTTPS_PORT', + 'ONLY_HTTPS', + 'NO_HTTP2' ]); if (ENV_PREFIX) { diff --git a/packages/adapter-node/src/index.js b/packages/adapter-node/src/index.js index ea3feee05860..5b48daa2f47a 100644 --- a/packages/adapter-node/src/index.js +++ b/packages/adapter-node/src/index.js @@ -1,15 +1,38 @@ import { handler } from 'HANDLER'; import { env } from 'ENV'; import polka from 'polka'; +import http from 'node:http'; +import https from 'node:https'; +import http2 from 'node:http2'; +import fs from 'node:fs'; export const path = env('SOCKET_PATH', false); export const host = env('HOST', '0.0.0.0'); export const port = env('PORT', !path && '3000'); +export const cert_path = env('CERT_PATH', false); +export const cert_key_path = env('CERT_KEY_PATH', false); +export const https_port = env('HTTPS_PORT', !path && '3001'); +export const only_https = env('ONLY_HTTPS', false); +export const no_http2 = env('NO_HTTP2', false); -const server = polka().use(handler); +const app = polka().use(handler); -server.listen({ path, host, port }, () => { - console.log(`Listening on ${path ? path : host + ':' + port}`); -}); +if (!only_https) { + http.createServer(app.handler).listen({ path, host, port }, () => { + console.log(`Listening on http://${path ? path : host + ':' + port}`); + }); +} -export { server }; +if (cert_path && cert_key_path) { + const cert = fs.readFileSync(cert_path); + const key = fs.readFileSync(cert_key_path); + const https_server = no_http2 + ? https.createServer({ cert, key }, app.handler) + : http2.createSecureServer({ allowHTTP1: true, cert, key }, app.handler); + + https_server.listen({ path, host, https_port }, () => { + console.log(`Listening on https://${path ? path : host + ':' + https_port}`); + }); +} + +export { app as server };