Sign In

srvx

Package Overview
Dependencies
Maintainers
1
Versions
86
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

srvx - npm Package Compare versions

Comparing version
0.12.1
to
0.12.2
+61
dist/body-limit.d.mts
/**
* The canonical error thrown when a request body exceeds `maxRequestBodySize`.
*
* It carries a stable, documented shape so any layer can map it to an HTTP
* `413 Payload Too Large` response without string matching.
*
* @see https://srvx.h3.dev/guide/body-limit
*/
interface BodyTooLargeError extends Error {
/** Stable machine-readable code. */
code: "ERR_BODY_TOO_LARGE";
/** HTTP status to respond with. */
statusCode: 413;
/** Alias of {@link statusCode}. */
status: 413;
}
/**
* Creates the canonical {@link BodyTooLargeError | `413 Payload Too Large` error}
* used across srvx when a request body exceeds the configured `maxRequestBodySize`.
*
* @see https://srvx.h3.dev/guide/body-limit
*/
declare function createBodyTooLargeError(maxRequestBodySize: number): BodyTooLargeError;
/**
* Wraps a body `ReadableStream` so the total number of bytes read cannot exceed
* `maxRequestBodySize`.
*
* The wrapper is **pull-based**: it reads from the upstream stream only when the
* consumer pulls, so it preserves backpressure and never buffers the whole body.
* As soon as the accumulated size passes the limit, the wrapped stream errors
* with the {@link createBodyTooLargeError | `413`-style error} and the upstream
* stream is cancelled with that same error (so the underlying source can stop
* producing / release the socket). Cancelling the wrapped stream propagates to
* the upstream stream.
*
* @see https://srvx.h3.dev/guide/body-limit
*/
declare function limitBodyStream(stream: ReadableStream<Uint8Array>, maxRequestBodySize: number): ReadableStream<Uint8Array>;
/**
* Returns a `Request` whose body is size-limited to `maxRequestBodySize`.
*
* If the request has no body it is returned unchanged; otherwise it is rebuilt
* with a size-limited body stream (method, url, headers and signal are
* preserved). Used for runtimes that expose a native `Request` but no body-size
* option (e.g. Deno).
*
* When the request declares a `Content-Length` that already exceeds the limit,
* the body is rejected early: the original body is cancelled without being read
* and the returned request's body errors immediately with the
* {@link createBodyTooLargeError | `413`-style error}. `Content-Length` is only
* a fast path — it may be absent (chunked transfer encoding) or understated, so
* the streaming limit is always enforced regardless. A request that overstates
* its `Content-Length` is rejected on the declared length (a malformed request,
* matching how e.g. Bun and nginx enforce limits). The error still surfaces when
* the body is consumed (`request.text()` / `.json()` / `.arrayBuffer()` /
* `.body`), matching the streamed-limit behaviour.
*
* @see https://srvx.h3.dev/guide/body-limit
*/
declare function limitRequestBody(request: Request, maxRequestBodySize: number): Request;
export { BodyTooLargeError, createBodyTooLargeError, limitBodyStream, limitRequestBody };
function createBodyTooLargeError(maxRequestBodySize) {
return Object.assign(/* @__PURE__ */ new Error(`Request body exceeds the maximum allowed size of ${maxRequestBodySize} bytes.`), {
code: "ERR_BODY_TOO_LARGE",
statusCode: 413,
status: 413
});
}
function limitBodyStream(stream, maxRequestBodySize) {
const reader = stream.getReader();
let size = 0;
return new ReadableStream({
async pull(controller) {
const { done, value } = await reader.read();
if (done) {
controller.close();
return;
}
size += value.byteLength;
if (size > maxRequestBodySize) {
const error = createBodyTooLargeError(maxRequestBodySize);
reader.cancel(error).catch(() => {});
controller.error(error);
return;
}
controller.enqueue(value);
},
cancel(reason) {
return reader.cancel(reason);
}
});
}
function limitRequestBody(request, maxRequestBodySize) {
if (!request.body) return request;
const contentLengthHeader = request.headers.get("content-length");
if ((contentLengthHeader && /^\d+$/.test(contentLengthHeader) ? Number(contentLengthHeader) : NaN) > maxRequestBodySize) {
const error = createBodyTooLargeError(maxRequestBodySize);
request.body.cancel(error).catch(() => {});
return new Request(request, {
body: new ReadableStream({ start(controller) {
controller.error(error);
} }),
duplex: "half"
});
}
return new Request(request, {
body: limitBodyStream(request.body, maxRequestBodySize),
duplex: "half"
});
}
export { createBodyTooLargeError, limitBodyStream, limitRequestBody };
+1
-1
import { FastURL } from "../_chunks/_url.mjs";
import { createWaitUntil, fmtURL, printListening, resolvePortAndHost, resolveTLSOptions, toNativeResponse } from "../_chunks/_utils2.mjs";
import { limitRequestBody } from "../body-limit.mjs";
import { gracefulShutdownPlugin, wrapFetch } from "../_chunks/_plugins.mjs";
import { trustProxyPlugin } from "../_chunks/_trust-proxy.mjs";
import { limitRequestBody } from "../_chunks/_body-limit.mjs";
const FastResponse = Response;

@@ -7,0 +7,0 @@ function serve(options) {

import { FastURL, lazyInherit } from "../_chunks/_url.mjs";
import { createWaitUntil, fmtURL, printListening, resolvePortAndHost, resolveTLSOptions } from "../_chunks/_utils2.mjs";
import { createBodyTooLargeError, limitBodyStream } from "../body-limit.mjs";
import { errorPlugin, gracefulShutdownPlugin, wrapFetch } from "../_chunks/_plugins.mjs";
import { HOST_RE, forwardedHopValue, resolveClientIP, trustedHops } from "../_chunks/_trust-proxy.mjs";
import { createBodyTooLargeError, limitBodyStream } from "../_chunks/_body-limit.mjs";
import nodeHTTP, { IncomingMessage, ServerResponse } from "node:http";

@@ -7,0 +7,0 @@ import { Duplex, PassThrough, Readable, addAbortSignal } from "node:stream";

@@ -208,3 +208,3 @@ import { bold, cyan, gray, green, magenta, red, url, yellow } from "./_chunks/_utils.mjs";

name: "srvx",
version: "0.12.0",
version: "0.12.1",
description: "Universal Server."

@@ -211,0 +211,0 @@ };

{
"name": "srvx",
"version": "0.12.1",
"version": "0.12.2",
"description": "Universal Server.",

@@ -30,2 +30,3 @@ "homepage": "https://srvx.h3.dev",

"./static": "./dist/static.mjs",
"./body-limit": "./dist/body-limit.mjs",
"./log": "./dist/log.mjs",

@@ -32,0 +33,0 @@ "./tracing": "./dist/tracing.mjs",

function createBodyTooLargeError(maxRequestBodySize) {
return Object.assign(/* @__PURE__ */ new Error(`Request body exceeds the maximum allowed size of ${maxRequestBodySize} bytes.`), {
code: "ERR_BODY_TOO_LARGE",
statusCode: 413,
status: 413
});
}
function limitBodyStream(stream, maxRequestBodySize) {
const reader = stream.getReader();
let size = 0;
return new ReadableStream({
async pull(controller) {
const { done, value } = await reader.read();
if (done) {
controller.close();
return;
}
size += value.byteLength;
if (size > maxRequestBodySize) {
const error = createBodyTooLargeError(maxRequestBodySize);
reader.cancel(error).catch(() => {});
controller.error(error);
return;
}
controller.enqueue(value);
},
cancel(reason) {
return reader.cancel(reason);
}
});
}
function limitRequestBody(request, maxRequestBodySize) {
if (!request.body) return request;
return new Request(request, {
body: limitBodyStream(request.body, maxRequestBodySize),
duplex: "half"
});
}
export { createBodyTooLargeError, limitBodyStream, limitRequestBody };