{"id":17094,"library":"express-unless","title":"Conditional Express Middleware Skipping","description":"express-unless is a utility library for Express.js that enables conditional execution of middleware functions. It allows developers to attach an `unless` method directly to any Express middleware, providing granular control over when that middleware should be skipped. The library currently ships as version 2.1.3 and has seen stable releases, with the latest update in April 2021. It differentiates itself by offering a fluent API for defining skip conditions based on HTTP methods, request paths (including regular expressions and path/method pairs), file extensions, or a fully custom predicate function. This approach simplifies complex conditional routing logic often found in Express applications, providing a cleaner way to apply authentication, logging, or other cross-cutting concerns selectively.","status":"active","version":"2.1.3","language":"javascript","source_language":"en","source_url":"git://github.com/jfromaniello/express-unless","tags":["javascript","typescript"],"install":[{"cmd":"npm install express-unless","lang":"bash","label":"npm"},{"cmd":"yarn add express-unless","lang":"bash","label":"yarn"},{"cmd":"pnpm add express-unless","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"express-unless modifies Express middleware and requires an Express application environment to function.","package":"express","optional":false}],"imports":[{"note":"The `unless` function is a named export. Default import is incorrect.","wrong":"import unless from 'express-unless';","symbol":"unless","correct":"import { unless } from 'express-unless';"},{"note":"This is the CommonJS `require` syntax as shown in the package's README.","symbol":"unless","correct":"const { unless } = require('express-unless');"},{"note":"Used for type hinting the options object passed to `unless` in TypeScript.","symbol":"UnlessOptions","correct":"import type { UnlessOptions } from 'express-unless';"}],"quickstart":{"code":"import express from 'express';\nimport { unless } from 'express-unless';\n\nconst app = express();\nconst port = 3000;\n\n// 1. A middleware to simulate authentication\nconst requiresAuth = (req: express.Request, res: express.Response, next: express.NextFunction) => {\n  if (req.headers.authorization === 'Bearer my-secret-token') {\n    console.log('User authenticated.');\n    next();\n  } else {\n    console.warn('Authentication failed for:', req.originalUrl);\n    res.status(401).send('Unauthorized');\n  }\n};\n\n// Extend the middleware with unless (type assertion for TypeScript compatibility)\n(requiresAuth as any).unless = unless;\n\n// Apply authentication to all routes UNLESS they are '/public', '/status' or OPTIONS requests\napp.use(\n  (requiresAuth as any).unless({\n    path: ['/public', '/status'],\n    method: ['OPTIONS']\n  })\n);\n\n// 2. A simple logger middleware\nconst logger = (req: express.Request, res: express.Response, next: express.NextFunction) => {\n  console.log(`[${new Date().toISOString()}] ${req.method} ${req.originalUrl}`);\n  next();\n};\n(logger as any).unless = unless;\n\n// Skip logging for image files or paths including '/no-log'\napp.use(logger.unless({\n  ext: ['.png', '.jpg', '.gif'],\n  custom: (req: express.Request) => req.originalUrl.includes('/no-log')\n}));\n\n// Public route - no auth needed\napp.get('/public', (req, res) => {\n  res.send('This is a public page.');\n});\n\n// Status route - no auth needed\napp.get('/status', (req, res) => {\n  res.send('Server is healthy.');\n});\n\n// Authenticated route\napp.get('/admin', (req, res) => {\n  res.send('Welcome to the admin area!');\n});\n\n// Route with images (logging skipped)\napp.get('/images/test.png', (req, res) => {\n  res.send('Serving image.');\n});\n\n// Route where logging is skipped via custom function\napp.get('/no-log/data', (req, res) => {\n  res.send('This route will not be logged.');\n});\n\n// Default route\napp.get('/', (req, res) => {\n  res.send('Hello World!');\n});\n\napp.listen(port, () => {\n  console.log(`Express app listening at http://localhost:${port}`);\n  console.log('Try:');\n  console.log('  GET http://localhost:3000/ - Authenticated');\n  console.log('  GET http://localhost:3000/public - Not Authenticated');\n  console.log('  GET http://localhost:3000/admin - Authenticated (requires Authorization: Bearer my-secret-token)');\n  console.log('  OPTIONS http://localhost:3000/admin - Not Authenticated (skipped by method)');\n  console.log('  GET http://localhost:3000/images/test.png - Logging skipped');\n  console.log('  GET http://localhost:3000/no-log/data - Logging skipped by custom function');\n});","lang":"typescript","description":"This quickstart sets up an Express application demonstrating how to apply `unless` to an authentication middleware and a logging middleware, skipping them based on paths, methods, extensions, and custom functions."},"warnings":[{"fix":"Be aware that the middleware object itself is mutated. In TypeScript, cast the middleware to `any` or extend its interface if using `express.Request` and `express.Response` interfaces directly, e.g., `(myMiddleware as any).unless = unless;`.","message":"The `unless` function extends existing middleware objects by adding an 'unless' property. This pattern, while effective, modifies foreign objects and could potentially conflict with other libraries or internal middleware properties if not handled carefully. Use type assertions in TypeScript to accommodate this design.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Review the Express API documentation for `req.url` vs `req.originalUrl`. If your middleware is mounted at a subpath and you want conditions to apply relative to that subpath, explicitly set `useOriginalUrl: false` in your `unless` options.","message":"The `path` option for `unless` matches against `req.originalUrl` by default. If you intend to match against the URL excluding router mounts, set `useOriginalUrl: false` to match against `req.url` instead. Misunderstanding this distinction is a common source of routing errors in Express.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Carefully consider the order of `app.use()` calls. Generally, apply `unless`-enhanced middleware before routers that might modify the request path properties. Test your conditional logic thoroughly across various routes.","message":"The behavior of `unless` is sensitive to middleware order. If a preceding middleware modifies `req.url` or `req.originalUrl`, or if `unless` itself is applied before a router, it can lead to unexpected conditional skips or runs.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Ensure that `mymid.unless = unless;` (or `(myMiddleware as any).unless = unless;` in TypeScript) is executed before attempting to call `mymid.unless(...)`. Verify `mymid` is a valid function.","cause":"The `unless` function from `express-unless` has not been correctly assigned to the middleware function, or the middleware function itself is undefined.","error":"TypeError: Cannot read properties of undefined (reading 'unless')"},{"fix":"Review the `unless` options: ensure `path` regular expressions are correct, `method` arrays include all intended methods, `ext` matches actual file extensions, and `custom` functions return the expected boolean value. Use `console.log` statements within a `custom` function to debug its return value and `req.originalUrl`/`req.url` values. Remember `unless` means 'skip if condition is met'.","cause":"The conditions specified in the `unless` options (e.g., `path`, `method`, `ext`, `custom`) are not evaluating as expected, causing the middleware to either always execute or always be skipped.","error":"Middleware is always running/never running despite `unless` configuration."}],"ecosystem":"npm","meta_description":null}