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

simple-http-dump-server

v1.0.2

Published

Tiny HTTP server that answers every request with 200 and dumps it to stdout and, optionally, a JSON Lines file. A fake upstream for webhooks and client testing.

Readme

simple-http-dump-server

CI npm version npm downloads Docker image Docker Hub version Docker Hub pulls Node.js License: MIT

A tiny HTTP server that answers every request with an empty 200 OK and shows you exactly what was sent.

Point a webhook, a client under test or a misbehaving integration at it and see the method, path, headers and body of every request. Think of it as a self-hosted RequestBin in a single file with two small dependencies.

$ npx simple-http-dump-server
Listening on port 8000 ...
2026-10-07T08:30:32.274Z [::1] - 200 4.072 ms
POST /webhooks/github HTTP/1.1
{"host":"localhost:8000","user-agent":"GitHub-Hookshot/abc123","authorization":"<redacted>","content-type":"application/json","content-length":"21"}
{"action": "opened"}

✨ Features

  • Accepts anything. Any method, any path, any content type. Bodies up to 50 MB by default.
  • Readable output. One block per request: summary line, request line, headers, then the body (truncated to 4 KB, so the log aggregator doesn't fill up).
  • Machine-readable recordings. JSON Lines with full bodies and JSON already parsed, ready for jq.
  • Dump over HTTP. GET /__dump returns the recordings and DELETE /__dump clears them, which suits test suites.
  • Records rejected requests too. A body over the limit gets 413 and still shows up in the log and the dump.
  • Doesn't leak credentials. Authorization, Proxy-Authorization, Cookie and X-Api-Key are always printed as <redacted>.
  • Easy to run. npx, a multi-arch Docker image (amd64/arm64), or a public endpoint on Azure Container Instances.
  • Container-friendly. Runs as numeric UID 1000 (works with runAsNonRoot), fails fast on a bad config, and shuts down cleanly on docker stop.

🚀 Quick start

npx (Node.js 22+):

npx simple-http-dump-server

Docker:

docker run --rm -p 8000:8000 ghcr.io/denis1stomin/simple-http-dump-server

The old Docker Hub image denis1stomin/simple-http-dump-server is outdated (2018). Use the ghcr.io image above. The Docker Hub copy is updated only if the CI has Docker Hub credentials.

Then send it something:

curl -X POST http://localhost:8000/some/path \
  -H 'content-type: application/json' \
  -d '{"SomeProp": "value"}'

⚙️ Configuration

All settings are environment variables.

| Variable | Default | Description | |---------------------|-----------|-----------------------------------------------------------------------------| | PORT | 8000 | Port to listen on. | | BODY_LIMIT | 50mb | Max request body size (100kb, 10mb, ...). Larger bodies get a 413. | | LOG_BODY_LIMIT | 4kb | Max body bytes printed to stdout; the rest is cut with … (truncated, N bytes total). 0 hides bodies. | | DUMP_FILE | (unset) | Store recordings in this file (appended, full bodies). Without it they are kept in memory. | | DUMP_BUFFER_LIMIT | 64mb | Size of the in-memory buffer when DUMP_FILE isn't set; the oldest records are evicted first. | | DUMP_API_PATH | /__dump | Path of the dump API. No authentication; set it to an empty string to turn the API off. |

If DUMP_FILE can't be opened (missing directory, read-only filesystem) or a value is invalid, the server exits at startup with a one-line error instead of failing on the first request.

PORT=9000 BODY_LIMIT=200mb DUMP_FILE=run.jsonl npx simple-http-dump-server

📄 Recordings (JSON Lines)

Every request is recorded as one JSON object per line, in memory or in DUMP_FILE:

{"ts":"2026-10-07T08:30:32.270Z","method":"POST","url":"/some/path","status":200,"headers":{"content-type":"application/json","content-length":"21"},"body":"{\"SomeProp\": \"value\"}","json":{"SomeProp":"value"}}

| Field | Description | |-----------------|----------------------------------------------------------------------------------------------| | ts | When the request was answered (ISO 8601). | | method, url | Request method and URL (with query string). | | status | Status the server answered with: 200, or 413 for bodies over BODY_LIMIT. | | headers | Only content-type and content-length, so no credentials end up in the recordings. | | body | Full body as UTF-8 text (empty for rejected requests). | | json | Parsed body, present only when the content type is JSON (application/json, *+json) and the body parses. |

A record is stored before the response is sent. Once a client has its response, the record is already available.

🔌 Reading the dump over HTTP

The server itself serves the recordings, so tests can fetch them without kubectl cp or exec rights on the pod:

| Request | Response | |------------------|-------------------------------------------------------------------------------------| | GET /__dump | 200, all recordings as application/x-ndjson. In memory mode, the X-Dump-Dropped header says how many old records were evicted. | | DELETE /__dump | 204, clears the recordings (truncates DUMP_FILE, or empties the buffer). | | other methods | 405 |

Calls to the dump API are themselves neither recorded nor logged. If the client under test needs the /__dump path itself, change DUMP_API_PATH.

🔓 The dump API has no authentication. Anyone who can reach the server can read every recorded body (credential headers are never stored, but bodies are stored in full) and can clear the dump. That's fine on localhost or inside a cluster where only your tests can reach the service. Anywhere else, turn the API off with DUMP_API_PATH= (empty), or at least restrict access to the port, e.g. with a Kubernetes NetworkPolicy.

curl -s http://localhost:8000/__dump | jq -c 'select(.status != 200) | {ts, url, status}'
curl -s -X DELETE http://localhost:8000/__dump

Example pytest fixture:

import json

import pytest
import requests

DUMP = "http://http-dump:8000/__dump"


@pytest.fixture
def recorded():
    requests.delete(DUMP).raise_for_status()      # start every test from a clean dump

    def fetch():
        resp = requests.get(DUMP)
        resp.raise_for_status()
        return [json.loads(line) for line in resp.text.splitlines()]

    return fetch


def test_prices_are_uploaded(recorded):
    run_sync()                                    # the code under test calls the fake upstream
    uploads = [r for r in recorded() if r["url"] == "/erp/sync/prices"]
    assert uploads and all(r["status"] == 200 for r in uploads)
    assert len(uploads[0]["json"]) == 5000

More jq examples:

# URLs of all POST requests
jq -r 'select(.method == "POST") | .url' run.jsonl

# number of items in each JSON array body
jq '.json | length' run.jsonl

To get the dump file on the host when running in Docker, mount a directory. The container runs as UID 1000, so the directory must be writable by it:

docker run --rm -p 8000:8000 \
  -e DUMP_FILE=/dump/run.jsonl -v "$PWD:/dump" \
  ghcr.io/denis1stomin/simple-http-dump-server

☸️ Kubernetes

The image runs fine with a hardened security context. Recordings are kept in memory by default, so a read-only root filesystem needs no extra volume:

containers:
  - name: http-dump
    image: ghcr.io/denis1stomin/simple-http-dump-server:latest
    ports: [{ containerPort: 8000 }]
    securityContext:
      runAsNonRoot: true
      readOnlyRootFilesystem: true
      allowPrivilegeEscalation: false

Tests then use GET and DELETE http://<service>:8000/__dump. The API has no authentication, so keep the Service cluster-internal (ClusterIP, no Ingress). If the pod has to be reachable from outside, turn the API off with - { name: DUMP_API_PATH, value: "" }. To keep recordings across many runs or beyond DUMP_BUFFER_LIMIT, add an emptyDir at /tmp and set DUMP_FILE=/tmp/run.jsonl.

☁️ Public endpoint with Azure Container Instances

Need a URL that a cloud service can reach? Run the container on ACI:

az group create --name http-dump --location centralus
CONTAINER_DNS_NAME=$(uuidgen | tr '[:upper:]' '[:lower:]')

az container create --name http-dump-server --resource-group http-dump \
  --image ghcr.io/denis1stomin/simple-http-dump-server \
  --ip-address public --ports 8000 --dns-name-label "$CONTAINER_DNS_NAME"

az container attach --name http-dump-server --resource-group http-dump   # follow the output

curl "http://$CONTAINER_DNS_NAME.centralus.azurecontainer.io:8000/some/path"

When you're done, delete everything with az group delete --name http-dump.

⚠️ A public endpoint accepts requests from anyone, and GET /__dump shows anyone what was recorded. Don't leave it running longer than you need it, and turn the dump API off: add --environment-variables DUMP_API_PATH= to az container create. A hard-to-guess path like DUMP_API_PATH=/$(uuidgen) only hides the API; it isn't authentication.

🛠️ Development

git clone https://github.com/denis1stomin/simple-http-dump-server.git
cd simple-http-dump-server
npm install
npm run lint   # ESLint
npm test       # node:test
npm start

CI/CD

GitHub Actions (ci.yml):

| Trigger | What happens | |---------------------|--------------------------------------------------------------------------------------------------| | Push / pull request | ESLint and tests on Node 22 and 24, hadolint, multi-arch image build, container smoke test | | Push to master | Image pushed to ghcr.io/denis1stomin/simple-http-dump-server:master | | Push (not PRs) | Also pushed to Docker Hub when DOCKERHUB_USERNAME / DOCKERHUB_TOKEN secrets are set | | Tag vX.Y.Z | Image tagged X.Y.Z, X.Y, latest; package published to npm with provenance |

To release, bump version in package.json, then push a matching vX.Y.Z tag. CI rejects the release if the tag and version don't match.

📜 License

MIT © Denis Istomin