npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dcl/http-server

v2.2.1

Published

http server component

Readme

@dcl/http-server

forked from https://github.com/well-known-components/http-server

Server options

createServerComponent(components, options) accepts a Partial<IHttpServerOptions> to tune the underlying Node server:

import { createServerComponent } from '@dcl/http-server'

const server = await createServerComponent(
  { config, logs },
  {
    // Reject request bodies larger than 1 MiB.
    maxBodySize: 1024 * 1024,
    // Abort a request whose headers + body don't arrive within 30s.
    requestTimeout: 30_000,
    maxHeadersCount: 100,
    maxRequestsPerSocket: 1000,
    cors: { origin: '*' }
  }
)

| Option | Maps to | Description | | --- | --- | --- | | maxBodySize | (enforced by this component) | Maximum size, in bytes, of an incoming request body. A request that declares a larger Content-Length is rejected with 413 Payload Too Large before the body is read; a body that omits or under-declares its length (e.g. chunked transfer-encoding) is capped with the same 413 while streaming. Unset means no limit. | | cors | (CORS middleware) | CORS configuration applied as middleware. | | keepAliveTimeout | server.keepAliveTimeout | Idle keep-alive socket timeout in ms (default 70000). | | headersTimeout | server.headersTimeout | Time to receive the complete headers in ms (default 75000). | | requestTimeout | server.requestTimeout | Time to receive the entire request in ms. 0 disables it. | | maxHeadersCount | server.maxHeadersCount | Maximum number of request headers. 0 means unlimited. | | maxRequestsPerSocket | server.maxRequestsPerSocket | Max requests served per keep-alive socket. Unset/0 means unlimited. |

A maxBodySize rejection produces a 413 that a handler can also surface itself: when a handler reads an over-limit body inside the middleware chain (e.g. await ctx.request.json()), the read rejects and the error middleware maps it to a 413 response.

maxBodySize must be a positive integer when provided — createServerComponent throws on 0, negative or fractional values (omit the option for "no limit"). When cors is also configured, the up-front Content-Length rejection still carries the actual-response CORS headers, so a cross-origin client can read the 413.

Reading the request body under a maxBodySize

The streaming limit is enforced as ctx.request.body is consumed, so it only turns into a 413 if your handler actually reads the body and propagates stream errors. Reading it with await ctx.request.json() / .text() / .arrayBuffer() or for await (… of ctx.request.body) does this for you — the read rejects with the 413 and the error middleware maps it to a response.

If you instead pipe ctx.request.body into another stream (e.g. a multipart parser like busboy), remember that Readable.prototype.pipe does not forward source errors to the destination. Attach an error handler to the adapted source, or a body-stream error — a client abort or the maxBodySize limiter emitting its 413 — surfaces as an unhandled error (and can crash the process):

import { Readable } from 'stream'

const body = Readable.fromWeb(ctx.request.body as any)
// Forward source errors (client abort, or the maxBodySize 413) so the parser rejects cleanly.
body.on('error', (err) => parser.destroy(err))
body.pipe(parser)

Requests that declare a Content-Length over the limit — the usual case for multipart/form-data uploads from browsers and fetch — are rejected up-front regardless of how the body is consumed.

Per-route body-size limits

maxBodySize on createServerComponent is server-wide. For a tighter limit on specific routes, use createBodySizeLimitMiddleware(bytes) and mount it on those routes:

import { createBodySizeLimitMiddleware } from '@dcl/http-server'

// allow at most 4 KB on this endpoint
router.post('/v1/notes', createBodySizeLimitMiddleware(4096), notesHandler)

It enforces the same dual check as the server-wide option: a request declaring a larger Content-Length is rejected up front with 413 Payload Too Large, and a body that omits or under-declares its length (e.g. chunked) is capped while streaming — the body read by downstream handlers errors with a 413 once the limit is crossed. Either 413 sets Connection: close, so an oversized or stalled client can't tie up the socket. bytes must be a positive integer or the factory throws. It composes with the server-wide maxBodySize (the global cap still applies first).

Returning a native Response from a handler

Handlers return the structural IResponse (Node Readable/Buffer/string/JSON bodies). A native Response (as returned by fetch, with a web ReadableStream body) is not an IResponse — returning one via as any lets response-transforming middleware (e.g. CORS) silently drop its status and body.

When you have a native Response (typically proxying an upstream fetch), adapt it at the boundary with fromNativeResponse:

import { fromNativeResponse } from '@dcl/http-server'

router.get('/proxy/:id', async (ctx) => {
  const upstream = await fetch(`${CONTENT_SERVER}/${ctx.params.id}`)
  return fromNativeResponse(upstream)
})

The body is streamed (not buffered), so proxying large responses stays memory-safe. The passed Response is consumed by the returned stream — don't also read it with .text()/.json().

Plain handlers are unaffected — keep returning the structural shape directly:

return { status: 200, body: { hello: 'world' } }