{"id":17061,"library":"router","title":"Router","description":"The `router` package provides a simple, middleware-style routing solution for Node.js HTTP servers. It is currently at version 2.2.0, with releases occurring periodically, often incorporating dependency updates and internal refactorings to reduce its external footprint, as seen in recent 2.x versions. This module was originally extracted from the Express project, offering a lightweight alternative that can be used directly with Node.js's native `http.createServer` or integrated into other web frameworks. Key differentiators include its minimalistic API, adherence to the familiar `(req, res, next)` middleware signature, and flexible routing capabilities through HTTP method-specific handlers (`router.get`, `router.post`, etc.) and general-purpose middleware (`router.use`). It supports asynchronous middleware, including Promises, and offers options for strictness, case sensitivity, and parameter merging.","status":"active","version":"2.2.0","language":"javascript","source_language":"en","source_url":"https://github.com/pillarjs/router","tags":["javascript"],"install":[{"cmd":"npm install router","lang":"bash","label":"npm"},{"cmd":"yarn add router","lang":"bash","label":"yarn"},{"cmd":"pnpm add router","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Commonly used for handling fall-through requests and errors from the router, especially when integrated with Node's native HTTP server.","package":"finalhandler","optional":false},{"reason":"Used for internal logging; its presence has fluctuated between v2 releases, but it is currently included for diagnostics.","package":"debug","optional":true}],"imports":[{"note":"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.","wrong":"import { Router } from 'router'; // Router is typically the default export\nconst Router = require('router'); // CommonJS is valid, but ESM is preferred in modern Node.js","symbol":"Router","correct":"import Router from 'router';"},{"note":"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.","symbol":"router(req, res, callback)","correct":"router(req, res, finalhandler(req, res));"},{"note":"`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.","wrong":"router.use('/api', (req, res, next) => { res.end('Data'); }); // Omits next(), which will stall the request if middleware doesn't end it.","symbol":"router.use","correct":"router.use('/api', myMiddleware);"},{"note":"`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.","wrong":"const finalhandler = require('finalhandler');","symbol":"finalhandler","correct":"import finalhandler from 'finalhandler';"}],"quickstart":{"code":"import http from 'node:http';\nimport Router from 'router';\nimport finalhandler from 'finalhandler';\n\nconst router = Router({\n  caseSensitive: false, // paths like /hello and /Hello are treated the same\n  strict: false // trailing slashes are optional\n});\n\n// Global middleware to log incoming requests\nrouter.use((req, res, next) => {\n  console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);\n  next(); // Must call next to pass control to subsequent middleware/routes\n});\n\n// Handle a GET request to the root path\nrouter.get('/', (req, res) => {\n  res.setHeader('Content-Type', 'text/plain; charset=utf-8');\n  res.end('Hello from the Router!');\n});\n\n// Handle a POST request to '/data'\nrouter.post('/data', (req, res) => {\n  let body = '';\n  req.on('data', chunk => { body += chunk; });\n  req.on('end', () => {\n    res.setHeader('Content-Type', 'application/json');\n    res.end(JSON.stringify({ received: body, status: 'ok' }));\n  });\n});\n\n// Middleware demonstrating next('route') to skip subsequent handlers for the current route\nrouter.get('/skip-example', (req, res, next) => {\n  if (req.query.skip) {\n    console.log('Skipping to the next route handler...');\n    return next('route'); // Skip this handler and the next for this route\n  }\n  next();\n}, (req, res) => {\n  res.end('This handler will be skipped if ?skip=true is in the query.');\n});\n\nconst server = http.createServer((req, res) => {\n  // The router processes the request; if no route matches or an error occurs,\n  // finalhandler ensures a proper HTTP response is sent.\n  router(req, res, finalhandler(req, res, { onerror: console.error }));\n});\n\nserver.listen(3000, () => {\n  console.log('Router server listening on http://localhost:3000');\n});","lang":"javascript","description":"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."},"warnings":[{"fix":"Update route definitions to use `(.*)` for wildcard groups instead of `(*)` and ensure `req.params` access relies on named parameters. Test existing routes thoroughly after upgrading.","message":"The `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.","severity":"breaking","affected_versions":">=2.0.0-beta.1"},{"fix":"Ensure your Node.js environment meets the minimum requirement specified in `package.json`'s `engines` field (currently `>=18`).","message":"Support 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.","severity":"breaking","affected_versions":">=2.0.0-alpha.1"},{"fix":"Always ensure your middleware calls `next()` unless it explicitly handles and ends the HTTP response (e.g., `res.end()`).","message":"Middleware 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.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Carefully 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.","message":"The 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.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"For 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.","message":"The `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.","severity":"deprecated","affected_versions":"2.0.0-beta.1 - 2.1.x"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Ensure 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.","cause":"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()`.","error":"ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client"},{"fix":"Inspect all middleware and route handlers to ensure every execution path either calls `next()` to continue processing or sends a complete HTTP response.","cause":"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.).","error":"Request hangs indefinitely / connection timeout"},{"fix":"Verify 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).","cause":"No route defined within the `router` instance matched the incoming request's HTTP method and path, leading the `finalhandler` callback to report a 404.","error":"404 Not Found (from finalhandler)"}],"ecosystem":"npm","meta_description":null}