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

@astroscope/proxy

v0.2.4

Published

HTTP proxy for Astro — strangler fig migrations and API gateway

Downloads

683

Readme

@astroscope/proxy

Note: This package is in active development. APIs may change between versions.

HTTP proxy for Astro — strangler fig migrations and API gateway. Gradually migrate from any backend or proxy to upstream APIs.

Examples

Why?

Astro has no built-in proxy support (roadmap discussion #665). This package fills that gap with two powerful patterns:

  • Strangler fig migration - Gradually migrate any website to Astro - WordPress, Rails, Django, .NET, PHP, or anything else. New Astro pages take precedence while unhandled requests fall through to your existing site.
  • Standalone gateway - Run Astro in standalone mode while proxying to your backend APIs. No need to embed Astro as middleware in Express/Fastify just because you need features like startup hooks or API proxying - use @astroscope/boot for lifecycle and this package for proxying.

Installation

npm install @astroscope/proxy

Usage

Migration (Strangler Fig)

When migrating from a legacy backend, create a catch-all route that forwards unhandled requests to the old system. As you build new pages in Astro, they take precedence over the catch-all, gradually "strangling" the legacy backend.

// src/pages/[...legacy].ts
import { createProxyHandler } from "@astroscope/proxy";

export const ALL = createProxyHandler({
  upstream: process.env.LEGACY_BACKEND!,
});

The ALL export handles all HTTP methods (GET, POST, PUT, DELETE, PATCH, HEAD).

With this setup:

  • src/pages/index.astro → handled by Astro
  • src/pages/about.astro → handled by Astro
  • /old-page (no Astro file) → proxied to legacy backend

API Proxy

For proxying specific paths to an upstream API:

// src/pages/api/[...path].ts
import { createProxyHandler } from "@astroscope/proxy";

export const ALL = createProxyHandler({
  upstream: process.env.API_UPSTREAM!,
});

Options

upstream (required)

The base URL of the upstream server.

createProxyHandler({
  upstream: "https://legacy.example.com",
});

onRequest (optional)

Called before proxying. Can modify the request or short-circuit with a Response.

Useful for adding headers, authentication, logging, rewriting URLs or blocking requests.

createProxyHandler({
  upstream: "https://api.example.com",
  onRequest: (context, targetUrl) => {
    const headers = new Headers(context.request.headers);

    headers.set("Authorization", `Bearer ${getToken()}`);

    return new Request(context.request, { headers });
  },
});

To short-circuit (skip proxying):

onRequest: (context, targetUrl) => {
  if (targetUrl.pathname === "/blocked") {
    return new Response("Not allowed", { status: 403 });
  }
};

To override the pathname (e.g., use original path before any rewrites):

onRequest: (context, targetUrl) => {
  targetUrl.pathname = context.originPathname;
};

onResponse (optional)

Called after receiving a response from upstream. Can modify the response.

createProxyHandler({
  upstream: "https://api.example.com",
  onResponse: (context, response, targetUrl) => {
    const headers = new Headers(response.headers);

    headers.set("X-Proxied-By", "astro");

    return new Response(response.body, {
      status: response.status,
      headers,
    });
  },
});

onError (optional)

Called when an error occurs during proxying. Can return a custom error response.

createProxyHandler({
  upstream: "https://api.example.com",
  onError: (context, error, targetUrl) => {
    console.error(`Proxy failed: ${targetUrl}`, error);

    return new Response("Service temporarily unavailable", {
      status: 503,
      headers: { "Retry-After": "30" },
    });
  },
});

If not provided, returns a default 502 response.

client (optional)

HTTP client configuration for connection pooling and HTTP/2.

createProxyHandler({
  upstream: "https://api.example.com",
  client: {
    pipelining: 10,            // max concurrent requests per origin (default: 10)
    allowH2: true,             // enable HTTP/2 (default: true)
    maxConcurrentStreams: 128, // HTTP/2 max streams (default: 128)
    keepAliveTimeout: 60000,   // keep-alive timeout in ms (default: 60000)
  },
});

Features

  • HTTP/2 support with connection pooling (via undici)
  • Proper stream handling for large responses
  • Request cancellation support
  • Handles 204/304 responses correctly

Requirements

  • Node.js runtime (required by undici)
  • Astro 5.x with SSR output mode

License

MIT