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

@nxtedition/http

v2.0.0

Published

HTTP/HTTP2 server middleware framework with priority-based scheduling, request lifecycle tracking, and Koa-style middleware composition.

Readme

@nxtedition/http

HTTP/HTTP2 server middleware framework with priority-based scheduling, request lifecycle tracking, and Koa-style middleware composition.

Install

npm install @nxtedition/http

Usage

Basic Server

import { createServer } from '@nxtedition/http'

const server = createServer({ keepAliveTimeout: 120_000 }, { logger: pino() }, (ctx) => {
  ctx.res.writeHead(200, { 'content-type': 'text/plain' })
  ctx.res.end('Hello World')
})

server.listen(3000)

Middleware Composition

import { createServer, compose } from '@nxtedition/http'

const auth = async (ctx, next) => {
  if (!ctx.req.headers.authorization) {
    const err = new Error('Unauthorized')
    err.statusCode = 401
    err.expose = true
    throw err
  }
  await next()
}

const handler = async (ctx) => {
  ctx.res.writeHead(200)
  ctx.res.end(JSON.stringify({ user: 'authenticated' }))
}

const server = createServer({ logger: pino() }, [auth, handler])

Priority-Based Scheduling

Requests are automatically prioritized based on the nxt-priority header or user-agent detection. Priority maps to DSCP/ToS values on the socket:

| Priority | Value | DSCP | Use Case | | -------- | ----- | ---- | ---------------- | | highest | 3 | EF | Realtime | | higher | 2 | AF41 | High priority | | high | 1 | AF31 | User experience | | normal | 0 | BE | Default traffic | | low | -1 | LE | Background tasks | | lower | -2 | LE | Replication | | lowest | -3 | LE | Batch jobs |

Error Handling

Thrown errors are automatically serialized to HTTP responses:

const handler = (ctx) => {
  const err = new Error('Validation failed')
  err.statusCode = 422
  err.body = { errors: [{ field: 'email', message: 'required' }] }
  err.headers = { 'x-request-id': ctx.id }
  throw err
}

Error properties:

  • statusCode - HTTP status code (default: 500)
  • body - Response body (object, string, or Buffer)
  • headers - Additional response headers (object or flat array)
  • expose - If true, includes err.message as JSON response body

Context Factory

import { createServer, Context } from '@nxtedition/http'

const server = createServer((req, res) => {
  const ctx = new Context(req, res, logger)
  ctx.db = database
  return ctx
}, handler)

AbortSignal Support

const handler = async (ctx) => {
  // ctx.signal is aborted when the request errors or is aborted
  const data = await fetch('http://upstream/api', { signal: ctx.signal })
  ctx.res.writeHead(200)
  ctx.res.end(await data.text())
}

API

createServer(ctx, middleware?)

createServer(options, ctx, middleware?)

Creates an HTTP server with enhanced request/response classes.

  • options - Server options (extends http.ServerOptions)
    • logger - Pino-compatible logger
    • signal - AbortSignal for graceful shutdown
    • socketTimeout / timeout - Socket timeout (default: 1h)
  • ctx - Context config object { logger, ...opaque } or factory function (req, res) => Context
  • middleware - Handler function or array of middleware functions

compose(...middleware)

Composes middleware functions into a single middleware. Supports arrays and variadic arguments. In development mode, validates that next() is not called multiple times and that middleware properly awaits downstream.

Context

Request context wrapping req and res with:

  • id - Unique request ID
  • req - IncomingMessage instance
  • res - ServerResponse instance
  • target - Parsed URL target (protocol, hostname, port, pathname, search)
  • query - Parsed query parameters
  • userAgent - User-Agent header value
  • priority - Resolved request priority
  • signal - AbortSignal (lazily created)
  • logger - Child logger with request ID

IncomingMessage

Extended http.IncomingMessage with computed id, target, and query properties. Results are lazily cached and invalidated when URL or host changes.

ServerResponse

Extended http.ServerResponse with:

  • timing - Request timing metrics (created, connect, headers, data, end)
  • bytesWritten - Total bytes written to response
  • Custom header tracking that bypasses Node.js per-header bookkeeping. This is a trusted-caller fast path, not a defensive copy of Node's header API.

The custom response implementations require these invariants:

  • Header names passed to setHeader, appendHeader, removeHeader, getHeader, and hasHeader, and names in a writeHead header object, are already lowercase and valid HTTP field names.
  • Header values are valid strings, numbers, or string arrays. Appending to a numeric value may create a response-owned mixed array before serialization. undefined is supported only by setHeader, where it removes the field.
  • Header mutation finishes before writeHead. Raw flat header arrays are not supported; use the header object form instead.
  • getHeaders returns the live internal null-prototype map. Before any header storage is allocated, getHeaderNames returns a shared frozen empty array. Treat returned storage as borrowed and read-only.
  • Arrays passed to setHeader become response-owned. In particular, appendHeader may extend the same array in place, so callers must not freeze or subsequently mutate it.
  • Do not mix the HTTP/2 response header API with direct stream.respond calls, and do not pass HTTP/2 pseudo-headers or connection-specific fields through the custom API.
  • Only explicitly staged fields are tracked. Removing a field such as date does not disable headers that Node may add implicitly during serialization.

Outside production, these invariants are asserted and names and values are validated to catch caller bugs early. With NODE_ENV=production, the hot path skips assertions, normalization, validation, cloning, and defensive merging. Violating the contract in production has undefined behavior and no rollback guarantee. Headers are handed to Node only at writeHead time, where Node's final serializer still enforces wire-level validity once.

requestMiddleware(ctx, next)

Core middleware that handles request lifecycle:

  • Sets request-id response header
  • Fast-dumps GET/HEAD request bodies
  • Tracks pending requests
  • Serializes errors to HTTP responses
  • Logs request lifecycle events

upgradeMiddleware(ctx, next)

Middleware for WebSocket/upgrade request handling with lifecycle logging.

genReqId()

Generates unique request IDs using V8 SMI-optimized integers (req-{base36}).

License

MIT