Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslnode 18–226 runs
build_error
glibcnode 18–226 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
Router
✓ import Router from 'router';
✗ import { Router } from 'router'; // Router is typically the default export
const Router = require('router'); // CommonJS is valid, but ESM is preferred in modern Node.js
The `Router` constructor is the primary export of the package. While CommonJS `require` is supported, ESM `import` is recommended for Node.js environments >=18. It is typically imported as a default export, not a named one.
router(req, res, callback)
✓ router(req, res, finalhandler(req, res));
After instantiating, the `router` itself is a function designed to act as middleware. It requires `req`, `res`, and a callback (often `finalhandler` for comprehensive error and fall-through handling) to process the request lifecycle.
router.use
✓ router.use('/api', myMiddleware);
✗ router.use('/api', (req, res, next) => { res.end('Data'); }); // Omits next(), which will stall the request if middleware doesn't end it.
`router.use` adds middleware that runs for all HTTP methods on a given path. Middleware functions *must* call `next()` to pass control to the subsequent handler in the stack, or explicitly end the HTTP response.
finalhandler
✓ import finalhandler from 'finalhandler';
✗ const finalhandler = require('finalhandler');
`finalhandler` is a separate, crucial dependency for graceful error handling and ensuring requests complete when a route is not found or an error occurs. It should be imported from its own package.
This example sets up a Node.js HTTP server using `router` to handle GET and POST requests, demonstrates global middleware, custom `Router` options, and the critical role of `finalhandler` for comprehensive request and error management. It also illustrates `next('route')` for fine-grained control.
import http from 'node:http';
import Router from 'router';
import finalhandler from 'finalhandler';
const router = Router({
caseSensitive: false, // paths like /hello and /Hello are treated the same
strict: false // trailing slashes are optional
});
// Global middleware to log incoming requests
router.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next(); // Must call next to pass control to subsequent middleware/routes
});
// Handle a GET request to the root path
router.get('/', (req, res) => {
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
res.end('Hello from the Router!');
});
// Handle a POST request to '/data'
router.post('/data', (req, res) => {
let body = '';
req.on('data', chunk => { body += chunk; });
req.on('end', () => {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({ received: body, status: 'ok' }));
});
});
// Middleware demonstrating next('route') to skip subsequent handlers for the current route
router.get('/skip-example', (req, res, next) => {
if (req.query.skip) {
console.log('Skipping to the next route handler...');
return next('route'); // Skip this handler and the next for this route
}
next();
}, (req, res) => {
res.end('This handler will be skipped if ?skip=true is in the query.');
});
const server = http.createServer((req, res) => {
// The router processes the request; if no route matches or an error occurs,
// finalhandler ensures a proper HTTP response is sent.
router(req, res, finalhandler(req, res, { onerror: console.error }));
});
server.listen(3000, () => {
console.log('Router server listening on http://localhost:3000');
});
Debug
Known issues
breakingThe `path-to-regexp` dependency, which powers route matching, underwent significant breaking changes in `v2.0.0-beta.1`. Specifically, the wildcard `(*)` for matching groups is no longer valid and must be written as `(.*)`. Additionally, named matching groups are no longer available by position in `req.params`, requiring explicit naming for parameter access.fixUpdate route definitions to use `(.*)` for wildcard groups instead of `(*)` and ensure `req.params` access relies on named parameters. Test existing routes thoroughly after upgrading.
affects: >=2.0.0-beta.1
breakingSupport for Node.js versions below 0.10 was explicitly dropped in `v2.0.0-alpha.1`. While the current `package.json` specifies `engines.node >= 18`, this historical change marked a significant breaking point for legacy environments.fixEnsure your Node.js environment meets the minimum requirement specified in `package.json`'s `engines` field (currently `>=18`).
affects: >=2.0.0-alpha.1
gotchaMiddleware functions, including those defined with `router.use` or specific HTTP methods, *must* explicitly call `next()` to pass control to the next middleware or handler in the stack. Failing to call `next()` will cause the request to hang indefinitely if the response is not otherwise terminated.fixAlways ensure your middleware calls `next()` unless it explicitly handles and ends the HTTP response (e.g., `res.end()`).
affects: >=1.0.0
gotchaThe router provides specific control flow options within middleware: `next()`, `next('route')`, and `next('router')`. `next('route')` bypasses remaining middleware and handlers *for the current matching route*, proceeding to the next route in the stack. `next('router')` exits the *current router instance completely*, invoking the top-level callback (e.g., `finalhandler`). Misunderstanding these can lead to unexpected or incorrect routing behavior.fixCarefully review the documentation for `next('route')` and `next('router')` to ensure correct control flow within complex routing scenarios, particularly when trying to skip specific handlers or entire router instances. affects: >=1.0.0
deprecatedThe `debug` dependency for internal logging was removed in `v2.0.0-beta.1` but subsequently restored in `v2.2.0`. If you relied on `debug` logging from `router` between these versions (e.g., in `v2.0.x` or `v2.1.x`), it would have been absent.fixFor versions `2.2.0` and later, `debug` logging is restored. If you require `debug` output on earlier v2 versions, consider upgrading or using alternative logging within your middleware.
affects: 2.0.0-beta.1 - 2.1.x
Errors
Common errors & fixes
ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client
Attempting to set HTTP headers or send response data after a previous middleware or route handler has already completed the response, or called `res.end()`.
fixEnsure that only one part of your middleware chain or a single route handler is responsible for explicitly ending the HTTP response. If a middleware doesn't end the response, it must call `next()` without implicitly sending headers.
Request hangs indefinitely / connection timeout
A middleware function or route handler failed to call `next()` to pass control, and also did not explicitly terminate the HTTP response (`res.end()`, `res.json()`, etc.).
fixInspect all middleware and route handlers to ensure every execution path either calls `next()` to continue processing or sends a complete HTTP response.
404 Not Found (from finalhandler)
No route defined within the `router` instance matched the incoming request's HTTP method and path, leading the `finalhandler` callback to report a 404.
fixVerify that your `router.get()`, `router.post()`, etc., definitions accurately match the expected request paths and HTTP methods. Check for common issues like typos, leading/trailing slashes (controlled by `strict` option), and case sensitivity (controlled by `caseSensitive` option).
Audit
Dependencies
finalhandlerrequiredCommonly used for handling fall-through requests and errors from the router, especially when integrated with Node's native HTTP server.
debugoptionalUsed for internal logging; its presence has fluctuated between v2 releases, but it is currently included for diagnostics.