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

@chubbyts/chubbyts-undici-trusted-proxy

v1.1.0

Published

A trusted proxy middleware for chubbyts-undici-server: resolves the client ip, scheme and host from forwarded headers.

Readme

chubbyts-undici-trusted-proxy

CI Coverage Status Mutation testing badge npm-version

bugs code_smells coverage duplicated_lines_density ncloc sqale_rating alert_status reliability_rating security_rating sqale_index vulnerabilities

Description

A trusted proxy middleware for chubbyts-undici-server: resolves the client ip, scheme and host from the forwarded headers (x-forwarded-for, x-forwarded-proto, x-forwarded-host) of trusted proxies into request attributes.

Requirements

Installation

Through NPM as @chubbyts/chubbyts-undici-trusted-proxy.

npm i @chubbyts/chubbyts-undici-trusted-proxy@^1.1.0

Usage

Behind a reverse proxy (nginx, traefik, a load balancer, ...) the server only sees the proxy, the client data arrives within the forwarded headers, which any client can send as well. The middleware decides which entries of these headers to trust and passes the request on with the clientIp, scheme and host attributes set, so that every other part (rate limiting, logging, access control, url generation, ...) reads them from one place instead of parsing headers.

import type { TrustedProxyAttributes } from '@chubbyts/chubbyts-undici-trusted-proxy/dist/middleware';
import { createForwardedResolver, createTrustedProxyMiddleware } from '@chubbyts/chubbyts-undici-trusted-proxy/dist/middleware';
import type { Handler } from '@chubbyts/chubbyts-undici-server/dist/server';
import { Response, ServerRequest } from '@chubbyts/chubbyts-undici-server/dist/server';

// the ips / cidrs of the proxies: the entries of x-forwarded-for get walked from the right, the first one not within
// the ranges is the client (robust against a varying number of hops)
const trustedProxyMiddleware = createTrustedProxyMiddleware(createForwardedResolver(['10.0.0.0/8', '::1']));

const handler: Handler<TrustedProxyAttributes> = async (serverRequest) => {
  // each one string | undefined: the unresolved ones are undefined
  const { clientIp, scheme, host } = serverRequest.attributes;

  return new Response(`${clientIp} requested ${scheme}://${host}`);
};

(async () => {
  const serverRequest = new ServerRequest<TrustedProxyAttributes>('https://example.com', {
    headers: { 'x-forwarded-for': '203.0.113.1, 10.0.0.1', 'x-forwarded-proto': 'https', 'x-forwarded-host': 'example.com' },
  });

  const response = await trustedProxyMiddleware(serverRequest, handler);
})();

Register the middleware before any middleware that reads the attributes. Requests without a resolvable client ip (no x-forwarded-for, only trusted entries, or a first untrusted entry which is not a valid ip like unknown or ip:port) get undefined attributes. The middleware always sets all three attributes (the unresolved ones as undefined), so that nothing set before it survives. A subnet matching every ip (0.0.0.0/0, ::/0) gets rejected, as it would trust every entry and never resolve anything, an empty list as well, as it would trust no entry and resolve the nearest proxy as client ip, the entries get trimmed.

The scheme and host get only resolved when a client ip was resolved: the entry at the same position, if the header has as many entries as the x-forwarded-for header (proxies appending to all of them), the last (the one the nearest proxy set) otherwise. The scheme gets lowercased.

Security

The middleware only sees the headers, not the connection: it cannot verify that the last hop actually was a trusted proxy. The server must not be reachable except through the proxies, and the proxies must set (or strip) all the forwarded headers, as any header they do not touch is supplied by the client.

If the server (or a middleware in front) sets the address of the connection as remoteAddress attribute (a string, undefined counts as not set), the middleware uses it: a connection from outside the trusted ranges counts as the client itself, and the headers get ignored. A remoteAddress which is not a valid ip (junk, a non string) resolves nothing, the middleware never falls back to the headers. Mind that chubbyts-undici-server itself does not set the attribute, without it the middleware runs in the headers only mode described above.

The clientIp is always a valid ip in its canonical form (lowercased, compressed, without zone id, e.g. ::ffff:203.0.113.1 for an ipv4 mapped ipv6 address), so that it can be compared as a string. Ipv4 mapped ipv6 addresses (::ffff:10.0.0.1) match ipv4 subnets (10.0.0.0/8) of the trusted proxies.

The scheme and host get taken from the headers as sent by the proxies (the scheme only lowercased): before using them for url generation or redirects, check the scheme against http / https and the host against the hosts the application serves (an allowlist), so that a proxy passing the client's x-forwarded-proto / x-forwarded-host through cannot poison generated urls:

const { scheme, host } = serverRequest.attributes;

if ((scheme !== 'http' && scheme !== 'https') || !['example.com', 'www.example.com'].includes(host ?? '')) {
  return new Response('Bad Request', { status: 400 });
}

Headers

The second argument replaces the header names (for is required, the others are optional), useful for a proxy setting a single value header like x-real-ip:

createForwardedResolver(['10.0.0.0/8'], { for: 'x-real-ip', proto: 'x-forwarded-proto' });

Service factories (chubbyts-dic-config)

The package ships service factories (abstract factories built on chubbyts-dic-config-factory) for a chubbyts-dic-config (or any chubbyts-dic-types compatible) container within @chubbyts/chubbyts-undici-trusted-proxy/dist/service-factory, configured through config.chubbyts.trustedProxy:

import type { ConfigFactory } from '@chubbyts/chubbyts-dic-config/dist/dic-config';
import { createContainerByConfigFactory } from '@chubbyts/chubbyts-dic-config/dist/dic-config';
import type { TrustedProxyAttributes } from '@chubbyts/chubbyts-undici-trusted-proxy/dist/middleware';
import type { TrustedProxyConfig } from '@chubbyts/chubbyts-undici-trusted-proxy/dist/service-factory';
import { trustedProxyMiddlewareServiceFactory } from '@chubbyts/chubbyts-undici-trusted-proxy/dist/service-factory';
import type { Middleware } from '@chubbyts/chubbyts-undici-server/dist/server';

const container = createContainerByConfigFactory({
  chubbyts: {
    trustedProxy: {
      trustedProxies: ['10.0.0.0/8', '::1'],
      // headers: { for: 'x-forwarded-for', proto: 'x-forwarded-proto', host: 'x-forwarded-host' },
    } satisfies TrustedProxyConfig,
  },
  dependencies: {
    factories: new Map<string, ConfigFactory>([['trustedProxyMiddleware', trustedProxyMiddlewareServiceFactory()]]),
  },
})();

const trustedProxyMiddleware = container.get<Middleware<TrustedProxyAttributes>>('trustedProxyMiddleware');

The trustedProxyMiddlewareServiceFactory uses the service trustedProxyForwardedResolver of the container if registered, and creates it through the shipped forwardedResolverServiceFactory otherwise. Register it under its name to replace it or to share it with other services.

With names

To serve different parts of an application behind different proxies (a public load balancer, an internal one, ...), the same factories can be registered multiple times with a name: the config is then read from config.chubbyts.trustedProxy.<name> and the name gets appended to each service id (trustedProxyMiddlewarepublic, trustedProxyForwardedResolverpublic, ...).

const container = createContainerByConfigFactory({
  chubbyts: {
    trustedProxy: {
      public: { trustedProxies: ['10.0.0.0/8', '::1'] },
      internal: { trustedProxies: ['192.168.0.0/16'], headers: { for: 'x-real-ip', proto: 'x-forwarded-proto' } },
    } satisfies Record<string, TrustedProxyConfig>,
  },
  dependencies: {
    factories: new Map<string, ConfigFactory>([
      ['trustedProxyMiddlewarepublic', trustedProxyMiddlewareServiceFactory('public')],
      ['trustedProxyMiddlewareinternal', trustedProxyMiddlewareServiceFactory('internal')],
    ]),
  },
})();

const publicTrustedProxyMiddleware = container.get<Middleware<TrustedProxyAttributes>>('trustedProxyMiddlewarepublic');
const internalTrustedProxyMiddleware = container.get<Middleware<TrustedProxyAttributes>>('trustedProxyMiddlewareinternal');

Copyright

2026 Dominik Zogg