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

woodland

v22.0.4

Published

Secure HTTP framework for Node.js. Express-compatible with built-in security, no performance tradeoff.

Readme

Woodland

Secure HTTP framework for Node.js. Express-compatible with built-in security, no performance tradeoff.

npm version Node.js Version License Test Coverage

Quick Start

npm install woodland

ESM

import { createServer } from "node:http";
import { woodland } from "woodland";

const app = woodland();

app.get("/", (req, res) => res.send("Hello World!"));
app.get("/users/:id", (req, res) => res.json({ id: req.params.id }));

createServer(app.route).listen(3000, () => console.log("Server running at http://localhost:3000"));

CommonJS

const { createServer } = require("node:http");
const { woodland } = require("woodland");

const app = woodland();

app.get("/", (req, res) => res.send("Hello World!"));
app.get("/users/:id", (req, res) => res.json({ id: req.params.id }));

createServer(app.route).listen(3000, () => console.log("Server running at http://localhost:3000"));

Why Woodland?

Security-First Design:

  • Zero learning curve - Express-compatible patterns
  • Built-in security - CORS, path traversal, XSS prevention (no additional packages)
  • Secure by default - CORS deny-all, path traversal blocked, HTML escaping automatic
  • TypeScript first - Full type definitions included
  • No performance tradeoff - Security features add ~0.02ms overhead per request
  • Lightweight - Minimal dependencies (6 packages)
  • Dual module support - CommonJS and ESM

Built-in Security Features:

  • CORS enforcement - Default deny-all, explicit allowlist required
  • Path traversal protection - Resolved paths validated against allowed directories
  • XSS prevention - Automatic HTML escaping for user output
  • IP validation - Protects against header spoofing
  • X-Content-Type-Options - Automatic nosniff header
  • Secure error handling - No sensitive data exposure

Common Patterns

REST API

const users = new Map();

app.get("/users", (req, res) => res.json(Array.from(users.values())));
app.get("/users/:id", (req, res) => {
  const user = users.get(req.params.id);
  user ? res.json(user) : res.error(404);
});
app.post("/users", (req, res) => {
  const id = Date.now().toString();
  const user = { ...req.body, id };
  users.set(id, user);
  res.json(user, 201);
});

CORS

const app = woodland({
  origins: ["https://myapp.com", "http://localhost:3000"],
});
// Woodland handles preflight OPTIONS automatically

Static Files

const app = woodland({ autoIndex: true });
app.files("/static", "./public");

Middleware

// Global middleware
app.always((req, res, next) => {
  req.startTime = Date.now();
  next();
});

// Route-specific middleware
app.get("/protected", authenticate, handler);

// Error handler (register last, 4 params)
app.use("/(.*)", (error, req, res, next) => {
  console.error(error);
  res.error(500);
});

Configuration

const app = woodland({
  origins: [], // CORS allowlist (empty = deny all)
  autoIndex: false, // Directory browsing
  etags: true, // ETag support
  cacheSize: 1000, // Route cache size
  cacheTTL: 10000, // Cache TTL in ms
  charset: "utf-8", // Default charset
  logging: {
    enabled: true,
    level: "info",
  },
  time: false, // X-Response-Time header
  silent: false, // Disable server headers
});

Response Helpers

res.json({ data: "value" });
res.send("Hello World");
res.redirect("/new-url");
res.header("x-custom", "value");
res.status(201);
res.error(404);

Request Properties

req.ip;         // Client IP address
req.params;     // URL parameters { id: "123" }
req.parsed;     // URL object
req.allow;      // Allowed methods
req.cors;       // CORS enabled
req.body;       // Request body
req.host;       // Hostname
req.valid;      // Request validity

Event Handlers

app.on("connect", (req, res) => console.log(`Connection from ${req.ip}`));
app.on("finish", (req, res) => analytics.track({ method: req.method, status: res.statusCode }));
app.on("error", (req, res, err) => console.error(`Error ${res.statusCode}:`, err));
app.on("stream", (req, res) => console.log(`Streaming file`));

CLI

# Serve directory (default: http://127.0.0.1:8000)
npx woodland

# Custom port
npx woodland --port=3000

# Custom IP
npx woodland --ip=0.0.0.0

Testing

npm test              # Run tests (100% line coverage)
npm run coverage      # Generate coverage report
npm run benchmark     # Performance benchmarks
npm run lint          # Check linting

Documentation

Performance

Woodland delivers enterprise-grade security without sacrificing performance. Security features add minimal overhead (~0.02ms per request).

| Framework | Security Approach | Mean Response Time | |-----------|------------------|-------------------| | Fastify | Requires plugins | 0.1491ms | | Woodland | Built-in | 0.1866ms | | Express | Requires middleware | 0.1956ms |

Security

Woodland implements multiple layers of protection:

  1. CORS Validation - Default deny-all policy
  2. Path Traversal Protection - Resolved paths validated
  3. Input Validation - IP addresses validated, URLs parsed securely
  4. Output Encoding - HTML escaping automatic
  5. Secure Error Handling - No internal paths exposed

Production Setup:

import helmet from "helmet";
import rateLimit from "express-rate-limit";

app.always(helmet());
app.always(rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }));

License

Copyright (c) 2026 Jason Mulligan

Licensed under the BSD-3-Clause license.

Support