Secure HTTP framework for Node.js. Express-compatible with built-in security, no performance tradeoff.
npm install woodlandimport { 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"));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"));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
nosniffheader - Secure error handling - No sensitive data exposure
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);
});const app = woodland({
origins: ["https://myapp.com", "http://localhost:3000"],
});
// Woodland handles preflight OPTIONS automaticallyconst app = woodland({ autoIndex: true });
app.files("/static", "./public");// 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);
});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
});res.json({ data: "value" });
res.send("Hello World");
res.redirect("/new-url");
res.header("x-custom", "value");
res.status(201);
res.error(404);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 validityapp.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`));# 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.0npm test # Run tests (100% line coverage)
npm run coverage # Generate coverage report
npm run benchmark # Performance benchmarks
npm run lint # Check linting- API Reference - Complete method documentation
- Technical Documentation - Architecture, OWASP security, internals
- Code Style Guide - Conventions and best practices
- Benchmarks - Performance testing results
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 |
Woodland implements multiple layers of protection:
- CORS Validation - Default deny-all policy
- Path Traversal Protection - Resolved paths validated
- Input Validation - IP addresses validated, URLs parsed securely
- Output Encoding - HTML escaping automatic
- 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 }));Copyright (c) 2026 Jason Mulligan
Licensed under the BSD-3-Clause license.
- Issues: GitHub Issues
- Discussions: GitHub Discussions