Skip to content

Commit

Permalink
[breaking] limit adapter-node request size (#6684)
Browse files Browse the repository at this point in the history
  • Loading branch information
benmccann authored Sep 9, 2022
1 parent f1e762b commit ba168b0
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 5 deletions.
6 changes: 6 additions & 0 deletions .changeset/tricky-ducks-kneel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@sveltejs/adapter-node': patch
'@sveltejs/kit': patch
---

[breaking] limit adapter-node request size
4 changes: 4 additions & 0 deletions packages/adapter-node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ Instead, we read from the _right_, accounting for the number of trusted proxies.

> If you need to read the left-most address instead (and don't care about spoofing) — for example, to offer a geolocation service, where it's more important for the IP address to be _real_ than _trusted_, you can do so by inspecting the `x-forwarded-for` header within your app.
### `BODY_SIZE_LIMIT`

The maximum request body size to accept in bytes. Defaults to 512kb. This option does not allow streaming. You can disable this option with a value of 0 and implement a custom check in [`handle`](https://kit.svelte.dev/docs/hooks#server-hooks-handle) if you need something more advanced.

## Options

The adapter can be configured with various options:
Expand Down
8 changes: 6 additions & 2 deletions packages/adapter-node/src/handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ const server = new Server(manifest);
await server.init({ env: process.env });
const origin = env('ORIGIN', undefined);
const xff_depth = parseInt(env('XFF_DEPTH', '1'));

const address_header = env('ADDRESS_HEADER', '').toLowerCase();
const protocol_header = env('PROTOCOL_HEADER', '').toLowerCase();
const host_header = env('HOST_HEADER', 'host').toLowerCase();
const body_size_limit = parseInt(env('BODY_SIZE_LIMIT', '524288'));

const dir = path.dirname(fileURLToPath(import.meta.url));

Expand Down Expand Up @@ -49,7 +49,11 @@ const ssr = async (req, res) => {
let request;

try {
request = await getRequest({ base: origin || get_origin(req.headers), request: req });
request = await getRequest({
base: origin || get_origin(req.headers),
request: req,
bodySizeLimit: body_size_limit
});
} catch (err) {
res.statusCode = err.status || 400;
res.end(err.reason || 'Invalid request body');
Expand Down
20 changes: 17 additions & 3 deletions packages/kit/src/exports/node/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import * as set_cookie_parser from 'set-cookie-parser';

/**
* @param {import('http').IncomingMessage} req
* @param {number} [body_size_limit]
*/
function get_raw_body(req) {
function get_raw_body(req, body_size_limit) {
const h = req.headers;

if (!h['content-type']) {
Expand All @@ -20,6 +21,19 @@ function get_raw_body(req) {
return null;
}

if (body_size_limit) {
if (!length) {
throw new Error(
`Received content-length of ${length}. content-length must be provided when body size limit is specified.`
);
}
if (length > body_size_limit) {
throw new Error(
`Received content-length of ${length}, but only accept up to ${body_size_limit} bytes.`
);
}
}

if (req.destroyed) {
const readable = new ReadableStream();
readable.cancel();
Expand Down Expand Up @@ -69,7 +83,7 @@ function get_raw_body(req) {
}

/** @type {import('@sveltejs/kit/node').getRequest} */
export async function getRequest({ request, base }) {
export async function getRequest({ request, base, bodySizeLimit }) {
let headers = /** @type {Record<string, string>} */ (request.headers);
if (request.httpVersionMajor === 2) {
// we need to strip out the HTTP/2 pseudo-headers because node-fetch's
Expand All @@ -85,7 +99,7 @@ export async function getRequest({ request, base }) {
return new Request(base + request.url, {
method: request.method,
headers,
body: get_raw_body(request)
body: get_raw_body(request, bodySizeLimit)
});
}

Expand Down
1 change: 1 addition & 0 deletions packages/kit/types/ambient.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ declare module '@sveltejs/kit/node' {
export function getRequest(opts: {
base: string;
request: import('http').IncomingMessage;
bodySizeLimit?: number;
}): Promise<Request>;
export function setResponse(res: import('http').ServerResponse, response: Response): void;
}
Expand Down

0 comments on commit ba168b0

Please sign in to comment.