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

sla-wizard-plugin-custom-baseurl

v1.0.3

Published

Plugin that overrides the nginx proxy_pass target per endpoint using the x-nginx-server-baseurl OAS extension

Readme

sla-wizard-plugin-custom-baseUrl

A plugin for SLA Wizard and sla-wizard-nginx-confd that adds support for the x-nginx-server-baseurl OAS extension.

When a path declares x-nginx-server-baseurl, nginx will proxy that endpoint to the custom backend URL instead of the global servers[0].url. Endpoints without the extension continue to use the global default.

Client → nginx:  POST /models/chatgpt/v1/chat/completions
nginx → backend: POST http://localhost:8001/v1/chat/completions   ← custom URL

Client → nginx:  POST /models/qwen/v1/chat/completions
nginx → backend: POST http://localhost:8000/v1/chat/completions   ← default URL

The plugin also inherits full x-nginx-strip support (via sla-wizard-plugin-nginx-strip), so you can freely combine both extensions on the same OAS path.


How it works

1. Annotate your OAS with x-nginx-server-baseurl

Add the extension at the path level (not operation level):

# oas.yaml
servers:
  - url: http://localhost:8000   # default for all endpoints

paths:
  /models/qwen/v1/chat/completions:
    post: ...                    # no extension → proxy_pass http://localhost:8000

  /models/chatgpt/v1/chat/completions:
    x-nginx-server-baseurl: http://localhost:8001   # overrides proxy_pass
    post: ...

  /models/claude/v1/chat/completions:
    x-nginx-server-baseurl: http://localhost:8002
    post: ...

2. Write your SLAs normally

# sla.yaml
plan:
  name: normal
  rates:
    /models/chatgpt/v1/chat/completions:
      post:
        requests:
          - max: 5
            period: minute

If you combine this plugin with x-nginx-strip, your SLAs can reference the backend (stripped) path and the plugin handles the expansion automatically.

3. Run the plugin

The plugin generates nginx configuration where each location block uses the endpoint-specific proxy_pass target:

# Without x-nginx-server-baseurl (standard output)
location /sla-alice_normal_modelschatgptv1chatcompletions_POST {
    rewrite /sla-alice_normal_modelschatgptv1chatcompletions_POST  $uri_original  break;
    proxy_pass http://localhost:8000;   ← same URL for every endpoint
    ...
}

# With x-nginx-server-baseurl applied
location /sla-alice_normal_modelschatgptv1chatcompletions_POST {
    rewrite /sla-alice_normal_modelschatgptv1chatcompletions_POST  $uri_original  break;
    proxy_pass http://localhost:8001;   ← custom URL for this endpoint only
    ...
}

Installation

cd sla-wizard-plugin-custom-baseUrl
npm install

The plugin depends on sla-wizard-plugin-nginx-strip (bundled as a local dependency).


Usage — CLI

Register the plugin in a CLI wrapper and invoke the commands.

CLI wrapper (one-time setup)

// my-cli.js
const slaWizard = require("sla-wizard");
const customBaseUrlPlugin = require("sla-wizard-plugin-custom-baseUrl");

slaWizard.use(customBaseUrlPlugin);
slaWizard.program.parse(process.argv);

config-nginx-baseurl — full config (nginx.conf + conf.d/)

Generates the complete nginx configuration split into a main nginx.conf and per-user conf.d/ files:

node my-cli.js config-nginx-baseurl \
  -o ./nginx-output \
  --oas ./specs/oas.yaml \
  --sla ./specs/slas \
  --authName apikey \
  --proxyPort 80

Output:

nginx-output/
├── nginx.conf          ← server block + URI routing rules
└── conf.d/
    ├── sla-alice_us.conf
    ├── sla-bob_us.conf
    └── ...

Each conf.d/ file contains the rate-limiting zones, API-key map, and location blocks for one user. Location blocks for endpoints with x-nginx-server-baseurl will have the custom URL in their proxy_pass directive.

add-to-baseurl-confd — conf.d only (no nginx.conf overwrite)

Useful for adding a new user or plan without touching the main nginx.conf:

node my-cli.js add-to-baseurl-confd \
  -o ./nginx-output \
  --oas ./specs/oas.yaml \
  --sla ./specs/slas/sla_newuser.yaml

CLI options

| Option | Description | Default | | --- | --- | --- | | -o, --outDir <dir> | Output directory | required | | --oas <path> | Path to OAS v3 file | ./specs/oas.yaml | | --sla <path> | Single SLA file, directory of SLAs, or URL | ./specs/sla.yaml | | --authLocation <loc> | Where to read the API key: header, query, url | header | | --authName <name> | API key parameter name | apikey | | --proxyPort <port> | Port nginx listens on | 80 | | --customTemplate <path> | Custom nginx config template | — |


Usage — Module (programmatic)

Setup

const slaWizard = require("sla-wizard");
const customBaseUrlPlugin = require("sla-wizard-plugin-custom-baseUrl");

slaWizard.use(customBaseUrlPlugin);

slaWizard.use registers the plugin and exposes its functions directly on the slaWizard object, injecting the sla-wizard context automatically.

slaWizard.configNginxBaseUrl(options) — full config

slaWizard.configNginxBaseUrl({
  outDir: "./nginx-output",
  oas:    "./specs/oas.yaml",
  sla:    "./specs/slas",          // file, directory, or URL
  authLocation: "header",          // optional, default: "header"
  authName:     "apikey",          // optional, default: "apikey"
  proxyPort:    80,                 // optional, default: 80
});

slaWizard.addToBaseUrlConfd(options) — conf.d only

Generates (or updates) only the conf.d/ files without creating or overwriting nginx.conf. Ideal for incremental user management:

slaWizard.addToBaseUrlConfd({
  outDir: "./nginx-output",
  oas:    "./specs/oas.yaml",
  sla:    "./specs/slas/sla_newuser.yaml",
});

Using individual exports directly

The plugin also exports lower-level functions that work without sla-wizard context — useful when integrating into custom pipelines:

const {
  applyBaseUrlToConfig,        // transform a raw config string
  applyBaseUrlTransformations, // transform all .conf files in an output directory
} = require("sla-wizard-plugin-custom-baseUrl");

applyBaseUrlTransformations(outDir, oasPath)

Reads the OAS from oasPath, then for every endpoint that declares x-nginx-server-baseurl, rewrites every matching proxy_pass directive inside <outDir>/nginx.conf and <outDir>/conf.d/*.conf — replacing the default server URL with the endpoint-specific custom URL.

const { applyBaseUrlTransformations } = require("sla-wizard-plugin-custom-baseUrl");

// After generating nginx config into outDir with any other tool...
applyBaseUrlTransformations("./nginx-output", "./specs/oas.yaml");

applyBaseUrlToConfig(configContent, baseUrlMap, defaultUrl)

Lower-level string transformation. Takes the raw config text, a map of sanitizedEndpoint → customUrl, and the default URL to replace, and returns the modified config string.

const { applyBaseUrlToConfig } = require("sla-wizard-plugin-custom-baseUrl");

const modified = applyBaseUrlToConfig(nginxConfString, {
  modelschatgptv1chatcompletions: "http://localhost:8001",
  modelsclaudev1chatcompletions:  "http://localhost:8002",
}, "http://localhost:8000");

Combining with x-nginx-strip

The plugin is built on top of sla-wizard-plugin-nginx-strip, so both extensions work together on the same OAS path. When you annotate an endpoint with both, nginx will:

  1. Receive the full public path (e.g. /models/chatgpt/v1/chat/completions)
  2. Forward the stripped backend path (e.g. /v1/chat/completions) — from x-nginx-strip
  3. Send the request to the custom backend URL (e.g. http://localhost:8001) — from x-nginx-server-baseurl
paths:
  /models/chatgpt/v1/chat/completions:
    x-nginx-strip: "/models/chatgpt"             # strip this prefix before forwarding
    x-nginx-server-baseurl: http://localhost:8001 # forward to this backend

  /models/claude/v1/chat/completions:
    x-nginx-strip: "/models/claude"
    x-nginx-server-baseurl: http://localhost:8002

When using x-nginx-strip, your SLAs can reference the backend (stripped) path and the plugin expands them automatically:

plan:
  rates:
    /v1/chat/completions:     # stripped path — expanded to all matching OAS paths
      post:
        requests:
          - max: 10
            period: minute

Complete example

OAS (oas.yaml)

openapi: 3.0.3
info:
  title: LLM Gateway API
  version: 1.0.0
servers:
  - url: http://localhost:8000   # default backend

paths:
  /models/qwen/v1/chat/completions:
    post:
      summary: Qwen completions
      operationId: postQwenCompletion
      responses:
        "200":
          description: OK

  /models/chatgpt/v1/chat/completions:
    x-nginx-server-baseurl: http://localhost:8001
    post:
      summary: ChatGPT completions
      operationId: postChatGPTCompletion
      responses:
        "200":
          description: OK

  /models/claude/v1/chat/completions:
    x-nginx-server-baseurl: http://localhost:8002
    post:
      summary: Claude completions
      operationId: postClaudeCompletion
      responses:
        "200":
          description: OK

SLA (sla.yaml)

sla4oas: 1.0.0
context:
  id: sla-alice
  type: agreement
  api:
    $ref: ./oas.yaml
  apikeys:
    - my-secret-key-abc123
plan:
  name: standard
  rates:
    /models/chatgpt/v1/chat/completions:
      post:
        requests:
          - max: 10
            period: minute
    /models/claude/v1/chat/completions:
      post:
        requests:
          - max: 10
            period: minute

Generate config (programmatic)

const slaWizard = require("sla-wizard");
const customBaseUrlPlugin = require("sla-wizard-plugin-custom-baseUrl");

slaWizard.use(customBaseUrlPlugin);

slaWizard.configNginxBaseUrl({
  outDir: "./nginx-output",
  oas:    "./oas.yaml",
  sla:    "./sla.yaml",
});

Generated conf.d/sla-alice_standard.conf (excerpt)

# Rate limiting zones
limit_req_zone $http_apikey zone=sla-alice_standard_modelschatgptv1chatcompletions_POST:10m rate=10r/m;
limit_req_zone $http_apikey zone=sla-alice_standard_modelsclaudev1chatcompletions_POST:10m rate=10r/m;

# Endpoint locations
location /sla-alice_standard_modelschatgptv1chatcompletions_POST {
    rewrite /sla-alice_standard_modelschatgptv1chatcompletions_POST  $uri_original  break;
    proxy_pass http://localhost:8001;   ← chatgpt backend
    limit_req zone=sla-alice_standard_modelschatgptv1chatcompletions_POST burst=9 nodelay;
}

location /sla-alice_standard_modelsclaudev1chatcompletions_POST {
    rewrite /sla-alice_standard_modelsclaudev1chatcompletions_POST  $uri_original  break;
    proxy_pass http://localhost:8002;   ← claude backend
    limit_req zone=sla-alice_standard_modelsclaudev1chatcompletions_POST burst=9 nodelay;
}

The qwen endpoint has no x-nginx-server-baseurl, so its location block (in nginx.conf) keeps proxy_pass http://localhost:8000.


Running the tests

npm test

The test suite covers:

  • UnitapplyBaseUrlToConfig: replacement, non-replacement, edge cases (empty input, no location blocks, block without proxy_pass, indentation preservation, partial-URL guard)
  • UnitapplyBaseUrlTransformations: file I/O, no-op when no extension present, graceful handling of missing files/directories
  • IntegrationconfigNginxBaseUrl and addToBaseUrlConfd: correct output structure, proxy_pass values per endpoint, both strip and baseurl transforms coexisting, idempotency, single-file SLA input
  • CLI — both commands, --help output, missing required argument, single-file SLA input, stdout success messages

License

Apache License 2.0 — same as SLA Wizard.