----
url: https://expressjs.com/en/blog/2
----

# Blog

Stay tuned for details on new releases, enhancements, and everything you need to know to make the most of your Express applications. Let's dive into what's new!

[Announcements](/en/blog/2026-05-18-a-new-look-for-express)

## [A New Look for Express](/en/blog/2026-05-18-a-new-look-for-express)

[Sebastian BeltranMay 18, 2026](/en/blog/2026-05-18-a-new-look-for-express)

[Security](/en/blog/2026-03-30-security-releases)

## [March 2026 Security Releases](/en/blog/2026-03-30-security-releases)

[Ulises GasconMar 30, 2026](/en/blog/2026-03-30-security-releases)

[Security](/en/blog/2026-02-27-security-releases)

## [February 2026 Security Releases](/en/blog/2026-02-27-security-releases)

[Ulises GascónFeb 27, 2026](/en/blog/2026-02-27-security-releases)

[Security](/en/blog/2025-12-01-security-releases)

## [November 2025 Security Releases](/en/blog/2025-12-01-security-releases)

[Ulises GascónDec 1, 2025](/en/blog/2025-12-01-security-releases)

[Security](/en/blog/2025-07-31-security-releases)

## [July 2025 Security Releases](/en/blog/2025-07-31-security-releases)

[Ulises GascónJul 31, 2025](/en/blog/2025-07-31-security-releases)

[Security](/en/blog/2025-07-18-security-releases)

## [June 2025 Security Releases](/en/blog/2025-07-18-security-releases)

[Ulises GascónJul 18, 2025](/en/blog/2025-07-18-security-releases)

----
url: https://expressjs.com/en/4x/starter/installing
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/starter/installing.mdx)

# [Installing](#overview)

Before you begin, make sure you have [Node.js](https://nodejs.org/) 0.10 or higher installed. Then, create a directory for your application and navigate into it.

Terminal window

```
mkdir myapp
cd myapp
```

Use the `npm init` command to create a `package.json` file for your application. For more information on how `package.json` works, see [Specifics of npm’s package.json handling](https://docs.npmjs.com/files/package.json).

Terminal window

```
npm init
```

Terminal window

```
yarn init
```

Terminal window

```
pnpm init
```

Terminal window

```
bun init
```

This command prompts you for a number of things, such as the name and version of your application. For now, you can simply hit RETURN to accept the defaults for most of them, with the following exception:

```
entry point: (index.js)
```

Enter `app.js`, or whatever you want the name of the main file to be. If you want it to be `index.js`, hit RETURN to accept the suggested default file name.

Now, install Express in the `myapp` directory and save it in the dependencies list. For example:

Terminal window

```
npm install express
```

Terminal window

```
yarn add express
```

Terminal window

```
pnpm add express
```

Terminal window

```
bun add express
```

To install Express temporarily and not add it to the dependencies list:

Terminal window

```
npm install express --no-save
```

Terminal window

```
bun add express --no-save
```

### Note

By default with version npm 5.0+, `npm install` adds the module to the `dependencies` list in the `package.json` file; with earlier versions of npm, you must specify the `--save` option explicitly. Then, afterwards, running `npm install` in the app directory will automatically install modules in the dependencies list.

## [TypeScript](#typescript)

Express is written in JavaScript and does not bundle its own type definitions. To use it with TypeScript, install TypeScript together with the community-maintained types for Express and Node.js (from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped)) as development dependencies:

Terminal window

```
npm install --save-dev typescript @types/express@4 @types/node
```

Terminal window

```
yarn add --dev typescript @types/express@4 @types/node
```

Terminal window

```
pnpm add --save-dev typescript @types/express@4 @types/node
```

Terminal window

```
bun add --dev typescript @types/express@4 @types/node
```

### Warning

Some middleware does not bundle its own type definitions. If you add an official middleware package that TypeScript reports as untyped, also install its types from DefinitelyTyped as a dev dependency, for example `@types/cors` alongside `cors`.

Add a `tsconfig.json`. These options mirror how Node.js runs TypeScript and make the compiler reject non-erasable syntax (such as `enum`s, namespaces, and parameter properties) that Node cannot strip:

tsconfig.json

```
{
  "compilerOptions": {
    "target": "esnext",
    "module": "nodenext",
    "rewriteRelativeImportExtensions": true,
    "erasableSyntaxOnly": true,
    "verbatimModuleSyntax": true,
    "noEmit": true,
    "strict": true,
    "skipLibCheck": true
  }
}
```

Write your application in TypeScript, annotating the [request](/en/4x/api/request/) and [response](/en/4x/api/response/) objects:

src/app.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


app.get('/', (req: Request, res: Response) => {
  res.send('Hello World!');
});


app.listen(3000);
```

You do not need to annotate everything. When you pass a handler directly to a route method or to `app.use()`, Express infers the types of `req`, `res`, and `next`, and it infers route parameters from the path, so `req.params.id` is a `string` in `app.get('/users/:id', ...)`. Add explicit types only where TypeScript has no context to infer from: error-handling middleware, whose `(err, req, res, next)` signature is not inferred, and handlers you define separately from the route. In those cases, annotate the parameters or type the whole function as `RequestHandler` or `ErrorRequestHandler`.

Run the file directly with Node.js, which strips the TypeScript types and runs the result without a build step:

Terminal window

```
node src/app.ts
```

### Note

Running `.ts` files directly requires Node.js >= 22.18.0 (or >= 23.6.0 on the v23 line) and TypeScript >= 5.8. Node strips the types but does not type-check them, so run `npx tsc` to type-check your project. For more details, see the Node.js guide on [running TypeScript natively](https://nodejs.org/learn/typescript/run-natively).

----
url: https://expressjs.com/en/4x/guide/writing-middleware
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/guide/writing-middleware.mdx)

# [Writing middleware for use in Express apps](#overview)

*Middleware* functions are functions that have access to the [request object](/en/4x/api/request/) (`req`), the [response object](/en/4x/api/response/) (`res`), and the `next` function in the application’s request-response cycle. The `next` function is a function in the Express router which, when invoked, executes the middleware succeeding the current middleware.

|   |                                                                                                                                                                                                                                                                                                                                                                                                                           |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | HTTP method for which the middleware function applies.Path (route) for which the middleware function applies.The middleware function.Callback argument to the middleware function, called “next” by convention.HTTP [response](/en/4x/api/response/) argument to the middleware function, called “res” by convention.HTTP [request](/en/4x/api/request/) argument to the middleware function, called “req” by convention. |

Starting with Express 5, middleware functions that return a Promise will call `next(value)` when they reject or throw an error. `next` will be called with either the rejected value or the thrown Error.

## [Example](#example)

Here is an example of a simple “Hello World” Express application. The remainder of this article will define and add three middleware functions to the application: one called `myLogger` that prints a simple log message, one called `requestTime` that displays the timestamp of the HTTP request, and one called `validateCookies` that validates incoming cookies.

index.cjs

```
const express = require('express');
const app = express();


app.get('/', (req, res) => {
  res.send('Hello World!');
});


app.listen(3000);
```

index.mjs

```
import express from 'express';


const app = express();


app.get('/', (req, res) => {
  res.send('Hello World!');
});


app.listen(3000);
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


app.get('/', (req: Request, res: Response) => {
  res.send('Hello World!');
});


app.listen(3000);
```

### [Middleware function myLogger](#middleware-function-mylogger)

Here is a simple example of a middleware function called “myLogger”. This function just prints “LOGGED” when a request to the app passes through it. The middleware function is assigned to a variable named `myLogger`.

```
const myLogger = function (req, res, next) {
  console.log('LOGGED');
  next();
};
```

```
import { type Request, type Response, type NextFunction } from 'express';


const myLogger = function (req: Request, res: Response, next: NextFunction) {
  console.log('LOGGED');
  next();
};
```

Here `myLogger` is defined on its own rather than passed directly to `app.use()`, so TypeScript has no context to infer its parameters and they are annotated explicitly. You can instead type the whole function as `RequestHandler`, which types `req`, `res`, and `next` for you. When the middleware is written inline in the `app.use()` call, Express infers those three parameters and no annotations are needed.

### Caution

Notice the call above to `next()`. Calling this function invokes the next middleware function in the app. The `next()` function is not a part of the Node.js or Express API, but is the third argument that is passed to the middleware function. The `next()` function could be named anything, but by convention it is always named “next”. To avoid confusion, always use this convention.

To load the middleware function, call `app.use()`, specifying the middleware function. For example, the following code loads the `myLogger` middleware function before the route to the root path (/).

index.cjs

```
const express = require('express');
const app = express();


const myLogger = function (req, res, next) {
  console.log('LOGGED');
  next();
};


app.use(myLogger);


app.get('/', (req, res) => {
  res.send('Hello World!');
});


app.listen(3000);
```

index.mjs

```
import express from 'express';


const app = express();


const myLogger = function (req, res, next) {
  console.log('LOGGED');
  next();
};


app.use(myLogger);


app.get('/', (req, res) => {
  res.send('Hello World!');
});


app.listen(3000);
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();


const myLogger = function (req: Request, res: Response, next: NextFunction) {
  console.log('LOGGED');
  next();
};


app.use(myLogger);


app.get('/', (req: Request, res: Response) => {
  res.send('Hello World!');
});


app.listen(3000);
```

Every time the app receives a request, it prints the message “LOGGED” to the terminal.

The order of middleware loading is important: middleware functions that are loaded first are also executed first.

If `myLogger` is loaded after the route to the root path, the request never reaches it and the app doesn’t print “LOGGED”, because the route handler of the root path terminates the request-response cycle.

The middleware function `myLogger` simply prints a message, then passes on the request to the next middleware function in the stack by calling the `next()` function.

### [Middleware function requestTime](#middleware-function-requesttime)

Next, we’ll create a middleware function called “requestTime” and add a property called `requestTime` to the [request object](/en/4x/api/request/).

### Caution

Because the middleware adds a property to `req`, extend the request type in TypeScript with [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html). Declare the property (as optional, since a middleware may not run for every request) in a `.d.ts` file that is part of your project:

types/express.d.ts

```
declare global {
  namespace Express {
    interface Request {
      requestTime?: number;
    }
  }
}


export {};
```

TypeScript picks up the file automatically, so no `tsconfig.json` change is needed unless you have set a custom `include` that does not cover its location. See [Extending the API in TypeScript](/en/4x/guide/overriding-express-api/#extending-the-api-in-typescript) for adding other custom properties and methods.

```
const requestTime = function (req, res, next) {
  req.requestTime = Date.now();
  next();
};
```

```
import { type Request, type Response, type NextFunction } from 'express';


const requestTime = function (req: Request, res: Response, next: NextFunction) {
  req.requestTime = Date.now();
  next();
};
```

The app now uses the `requestTime` middleware function. Also, the callback function of the root path route uses the property that the middleware function adds to `req` (the request object).

index.cjs

```
const express = require('express');
const app = express();


const requestTime = function (req, res, next) {
  req.requestTime = Date.now();
  next();
};


app.use(requestTime);


app.get('/', (req, res) => {
  let responseText = 'Hello World!<br>';
  responseText += `<small>Requested at: ${req.requestTime}</small>`;
  res.send(responseText);
});


app.listen(3000);
```

index.mjs

```
import express from 'express';


const app = express();


const requestTime = function (req, res, next) {
  req.requestTime = Date.now();
  next();
};


app.use(requestTime);


app.get('/', (req, res) => {
  let responseText = 'Hello World!<br>';
  responseText += `<small>Requested at: ${req.requestTime}</small>`;
  res.send(responseText);
});


app.listen(3000);
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();


const requestTime = function (req: Request, res: Response, next: NextFunction) {
  req.requestTime = Date.now();
  next();
};


app.use(requestTime);


app.get('/', (req: Request, res: Response) => {
  let responseText = 'Hello World!<br>';
  responseText += `<small>Requested at: ${req.requestTime}</small>`;
  res.send(responseText);
});


app.listen(3000);
```

When you make a request to the root of the app, the app now displays the timestamp of your request in the browser.

### [Middleware function validateCookies](#middleware-function-validatecookies)

Finally, we’ll create a middleware function that validates incoming cookies and sends a 400 response if cookies are invalid.

Here’s an example function that validates cookies with an external async service.

```
async function cookieValidator(cookies) {
  try {
    await externallyValidateCookie(cookies.testCookie);
  } catch {
    throw new Error('Invalid cookies');
  }
}
```

```
async function cookieValidator(cookies: Record<string, string>) {
  try {
    await externallyValidateCookie(cookies.testCookie);
  } catch {
    throw new Error('Invalid cookies');
  }
}
```

Here, we use the [`cookie-parser`](/en/resources/middleware/cookie-parser/) middleware to parse incoming cookies off the `req` object and pass them to our `cookieValidator` function. The `validateCookies` middleware returns a Promise that upon rejection will automatically trigger our error handler.

index.cjs

```
const express = require('express');
const cookieParser = require('cookie-parser');
const cookieValidator = require('./cookieValidator');


const app = express();


async function validateCookies(req, res, next) {
  await cookieValidator(req.cookies);
  next();
}


app.use(cookieParser());


app.use(validateCookies);


// error handler
app.use((err, req, res, next) => {
  res.status(400).send(err.message);
});


app.listen(3000);
```

index.mjs

```
import express from 'express';
import cookieParser from 'cookie-parser';
import cookieValidator from './cookieValidator';


const app = express();


async function validateCookies(req, res, next) {
  await cookieValidator(req.cookies);
  next();
}


app.use(cookieParser());


app.use(validateCookies);


// error handler
app.use((err, req, res, next) => {
  res.status(400).send(err.message);
});


app.listen(3000);
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';
import cookieParser from 'cookie-parser';
import cookieValidator from './cookieValidator';


const app: Express = express();


async function validateCookies(req: Request, res: Response, next: NextFunction) {
  await cookieValidator(req.cookies);
  next();
}


app.use(cookieParser());


app.use(validateCookies);


// error handler
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  res.status(400).send(err.message);
});


app.listen(3000);
```

### Caution

Note how `next()` is called after `await cookieValidator(req.cookies)`. This ensures that if `cookieValidator` resolves, the next middleware in the stack will get called. If you pass anything to the `next()` function (except the string `'route'` or `'router'`), Express regards the current request as being an error and will skip any remaining non-error handling routing and middleware functions.

Because you have access to the [request object](/en/4x/api/request/), the [response object](/en/4x/api/response/), the next middleware function in the stack, and the whole [Node.js API](https://nodejs.org/api/), the possibilities with middleware functions are endless.

## [Configurable middleware](#configurable-middleware)

If you need your middleware to be configurable, export a function which accepts an options object or other parameters, which, then returns the middleware implementation based on the input parameters.

my-middleware.cjs

```
module.exports = function (options) {
  return function (req, res, next) {
    // Implement the middleware function based on the options object
    next();
  };
};
```

my-middleware.mjs

```
export default function (options) {
  return function (req, res, next) {
    // Implement the middleware function based on the options object
    next();
  };
}
```

my-middleware.ts

```
import { type Request, type Response, type NextFunction } from 'express';


export default function (options) {
  return function (req: Request, res: Response, next: NextFunction) {
    // Implement the middleware function based on the options object
    next();
  };
}
```

The middleware can now be used as shown below.

index.cjs

```
const mw = require('./my-middleware.cjs');


app.use(mw({ option1: '1', option2: '2' }));
```

index.mjs

```
import mw from './my-middleware.mjs';


app.use(mw({ option1: '1', option2: '2' }));
```

index.ts

```
import mw from './my-middleware';


app.use(mw({ option1: '1', option2: '2' }));
```

Refer to [cookie-session](https://github.com/expressjs/cookie-session) and [compression](https://github.com/expressjs/compression) for examples of configurable middleware.

----
url: https://expressjs.com/en/blog/2026-02-27-security-releases
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2026-02-27-security-releases)

security

# [February 2026 Security Releases](#overview)

Ulises GascónFebruary 27, 2026

[](https://x.com/intent/tweet?text=February%202026%20Security%20Releases\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-02-27-security-releases%2F)[](https://bsky.app/intent/compose?text=February%202026%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-02-27-security-releases%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-02-27-security-releases%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-02-27-security-releases%2F\&text=February%202026%20Security%20Releases)[](https://wa.me/?text=February%202026%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-02-27-security-releases%2F)[](/feed.xml)

The Express team has released a new patch version of [multer](https://www.npmjs.com/package/multer) addressing two high-severity security vulnerabilities.

### Warning

We recommend upgrading to the latest version of multer to secure your applications.

The following vulnerabilities have been addressed:

* [CVE-2026-3304 in multer middleware (High)](#cve-2026-3304-in-multer-middleware-high)
* [CVE-2026-2359 in multer middleware (High)](#cve-2026-2359-in-multer-middleware-high)

## [CVE-2026-3304 in multer middleware (High)](#cve-2026-3304-in-multer-middleware-high)

**[multer](https://www.npmjs.com/package/multer) versions `<2.1.0` are vulnerable to denial of service via incomplete cleanup**

A vulnerability in Multer versions `<2.1.0` allows an attacker to trigger a Denial of Service (DoS) by sending malformed requests, potentially causing resource exhaustion.

**Affected versions**: `< 2.1.0`\
**Patched version**: `>= 2.1.0`

For more details, see [GHSA-xf7r-hgr6-v32p](https://github.com/expressjs/multer/security/advisories/GHSA-xf7r-hgr6-v32p).

## [CVE-2026-2359 in multer middleware (High)](#cve-2026-2359-in-multer-middleware-high)

**[multer](https://www.npmjs.com/package/multer) versions `<2.1.0` are vulnerable to denial of service via resource exhaustion**

A vulnerability in Multer versions `<2.1.0` allows an attacker to trigger a Denial of Service (DoS) by dropping connection during file upload, potentially causing resource exhaustion.

**Affected versions**: `< 2.1.0`\
**Patched version**: `>= 2.1.0`

For more details, see [GHSA-v52c-386h-88mc](https://github.com/expressjs/multer/security/advisories/GHSA-v52c-386h-88mc).

***

We recommend upgrading to the latest version of multer to secure your applications.

----
url: https://expressjs.com/en/resources/middleware/vhost
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/vhost.mdx)

# [vhost middleware](#overview)

v3.0.2[GitHub](https://github.com/expressjs/vhost)[Changelog](https://github.com/expressjs/vhost/releases)[npm](https://www.npmjs.com/package/vhost)

## [Install](#install)

Terminal window

```
npm install vhost
```

Terminal window

```
yarn add vhost
```

Terminal window

```
pnpm add vhost
```

Terminal window

```
bun add vhost
```

### Note

`vhost` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/vhost
```

Terminal window

```
yarn add --dev @types/vhost
```

Terminal window

```
pnpm add --save-dev @types/vhost
```

Terminal window

```
bun add --dev @types/vhost
```

## [API](#api)

```
var vhost = require('vhost');
```

### [vhost(hostname, handle)](#vhosthostname-handle)

Create a new middleware function to hand off request to `handle` when the incoming host for the request matches `hostname`. The function is called as `handle(req, res, next)`, like a standard middleware.

`hostname` can be a string or a RegExp object. When `hostname` is a string it can contain `*` to match 1 or more characters in that section of the hostname. When `hostname` is a RegExp, it will be forced to case-insensitive (since hostnames are) and will be forced to match based on the start and end of the hostname.

When host is matched and the request is sent down to a vhost handler, the `req.vhost` property will be populated with an object. This object will have numeric properties corresponding to each wildcard (or capture group if RegExp object provided) and the `hostname` that was matched.

```
var connect = require('connect');
var vhost = require('vhost');
var app = connect();


app.use(
  vhost('*.*.example.com', function handle(req, res, next) {
    // for match of "foo.bar.example.com:8080" against "*.*.example.com":
    console.dir(req.vhost.host); // => 'foo.bar.example.com:8080'
    console.dir(req.vhost.hostname); // => 'foo.bar.example.com'
    console.dir(req.vhost.length); // => 2
    console.dir(req.vhost[0]); // => 'foo'
    console.dir(req.vhost[1]); // => 'bar'
  })
);
```

## [Examples](#examples)

### [using with connect for static serving](#using-with-connect-for-static-serving)

```
var connect = require('connect');
var serveStatic = require('serve-static');
var vhost = require('vhost');


var mailapp = connect();


// add middlewares to mailapp for mail.example.com


// create app to serve static files on subdomain
var staticapp = connect();
staticapp.use(serveStatic('public'));


// create main app
var app = connect();


// add vhost routing to main app for mail
app.use(vhost('mail.example.com', mailapp));


// route static assets for "assets-*" subdomain to get
// around max host connections limit on browsers
app.use(vhost('assets-*.example.com', staticapp));


// add middlewares and main usage to app


app.listen(3000);
```

### [using with connect for user subdomains](#using-with-connect-for-user-subdomains)

```
var connect = require('connect');
var serveStatic = require('serve-static');
var vhost = require('vhost');


var mainapp = connect();


// add middlewares to mainapp for the main web site


// create app that will server user content from public/{username}/
var userapp = connect();


userapp.use(function (req, res, next) {
  var username = req.vhost[0]; // username is the "*"


  // pretend request was for /{username}/* for file serving
  req.originalUrl = req.url;
  req.url = '/' + username + req.url;


  next();
});
userapp.use(serveStatic('public'));


// create main app
var app = connect();


// add vhost routing for main app
app.use(vhost('userpages.local', mainapp));
app.use(vhost('www.userpages.local', mainapp));


// listen on all subdomains for user pages
app.use(vhost('*.userpages.local', userapp));


app.listen(3000);
```

### [using with any generic request handler](#using-with-any-generic-request-handler)

```
var connect = require('connect');
var http = require('http');
var vhost = require('vhost');


// create main app
var app = connect();


app.use(
  vhost('mail.example.com', function (req, res) {
    // handle req + res belonging to mail.example.com
    res.setHeader('Content-Type', 'text/plain');
    res.end('hello from mail!');
  })
);


// an external api server in any framework
var httpServer = http.createServer(function (req, res) {
  res.setHeader('Content-Type', 'text/plain');
  res.end('hello from the api!');
});


app.use(
  vhost('api.example.com', function (req, res) {
    // handle req + res belonging to api.example.com
    // pass the request to a standard Node.js HTTP server
    httpServer.emit('request', req, res);
  })
);


app.listen(3000);
```

## [License](#license)

[MIT](https://github.com/expressjs/vhost/blob/HEAD/LICENSE)

----
url: https://expressjs.com/en/resources/middleware/body-parser
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/body-parser.mdx)

# [body-parser middleware](#overview)

v2.3.0[GitHub](https://github.com/expressjs/body-parser)[Changelog](https://github.com/expressjs/body-parser/releases)[npm](https://www.npmjs.com/package/body-parser)

Node.js body parsing middleware.

Parse incoming request bodies in a middleware before your handlers, available under the `req.body` property.

**Note** As `req.body`’s shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, `req.body.foo.toString()` may fail in multiple ways, for example the `foo` property may not be there or may not be a string, and `toString` may not be a function and instead a string or other user input.

[Learn about the anatomy of an HTTP transaction in Node.js](https://nodejs.org/en/learn/http/anatomy-of-an-http-transaction).

*This does not handle multipart bodies*, due to their complex and typically large nature. For multipart bodies, you may be interested in the following modules:

* [busboy](https://www.npmjs.com/package/busboy#readme) and [connect-busboy](https://www.npmjs.com/package/connect-busboy#readme)
* [multiparty](https://www.npmjs.com/package/multiparty#readme) and [connect-multiparty](https://www.npmjs.com/package/connect-multiparty#readme)
* [formidable](https://www.npmjs.com/package/formidable#readme)
* [multer](https://www.npmjs.com/package/multer#readme)

This module provides the following parsers:

* [JSON body parser](#bodyparserjsonoptions)
* [Raw body parser](#bodyparserrawoptions)
* [Text body parser](#bodyparsertextoptions)
* [URL-encoded form body parser](#bodyparserurlencodedoptions)

All parsers support automatic inflation of `gzip`, `br` (brotli), `deflate` and `zstd` encodings. `zstd` is available in Node.js `^22.15.0` and `>=23.8.0`.

Other body parsers you might be interested in:

* [body](https://www.npmjs.com/package/body#readme)
* [co-body](https://www.npmjs.com/package/co-body#readme)

## [Installation](#installation)

Terminal window

```
npm install body-parser
```

Terminal window

```
yarn add body-parser
```

Terminal window

```
pnpm add body-parser
```

Terminal window

```
bun add body-parser
```

### Note

`body-parser` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/body-parser
```

Terminal window

```
yarn add --dev @types/body-parser
```

Terminal window

```
pnpm add --save-dev @types/body-parser
```

Terminal window

```
bun add --dev @types/body-parser
```

## [API](#api)

```
// Import all parsers
const bodyParser = require('body-parser');


// Or import individual parsers directly
const json = require('body-parser/json');
const urlencoded = require('body-parser/urlencoded');
const raw = require('body-parser/raw');
const text = require('body-parser/text');
```

The `bodyParser` object exposes various factories to create middlewares. All middlewares will populate the `req.body` property with the parsed body when the `Content-Type` request header matches the `type` option.

The various errors returned by this module are described in the [errors section](#errors).

### [bodyParser.json(\[options\])](#bodyparserjsonoptions)

Returns middleware that only parses `json` and only looks at requests where the `Content-Type` header matches the `type` option. This parser accepts any Unicode encoding of the body.

A new `body` object containing the parsed data is populated on the `request` object after the middleware (i.e. `req.body`).

#### [Options](#options)

The `json` function takes an optional `options` object that may contain any of the following keys:

##### [defaultCharset](#defaultcharset)

Specify the default character set for the json content if the charset is not specified in the `Content-Type` header of the request. Defaults to `utf-8`.

##### [inflate](#inflate)

When set to `true`, then deflated (compressed) bodies will be inflated; when `false`, deflated bodies are rejected. Defaults to `true`.

##### [limit](#limit)

Controls the maximum request body size. If this is a number, then the value specifies the number of bytes; if it is a string, the value is passed to the [bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults to `'100kb'`.

> It’s recommended not to configure a very high limit and to use the default value whenever possible. Allowing larger payloads increases memory usage because of the resources required for decoding and transformations, and it can also lead to longer response times as more data is processed. By ‘very high’, we mean values above the default, for example payloads of 5 MB or more can already start to introduce these risks. With the default limits, these issues do not occur.

##### [reviver](#reviver)

The `reviver` option is passed directly to `JSON.parse` as the second argument. You can find more information on this argument [in the MDN documentation about JSON.parse](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#the_reviver_parameter).

##### [strict](#strict)

When set to `true`, will only accept arrays and objects; when `false` will accept anything `JSON.parse` accepts. Defaults to `true`.

##### [type](#type)

The `type` option is used to determine what media type the middleware will parse. This option can be a string, array of strings, or a function. If not a function, `type` option is passed directly to the [type-is](https://www.npmjs.com/package/type-is#readme) library and this can be an extension name (like `json`), a mime type (like `application/json`), or a mime type with a wildcard (like `*/*` or `*/json`). If a function, the `type` option is called as `fn(req)` and the request is parsed if it returns a truthy value. Defaults to `application/json`.

##### [verify](#verify)

The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, where `buf` is a `Buffer` of the raw request body and `encoding` is the encoding of the request. The parsing can be aborted by throwing an error.

### [bodyParser.raw(\[options\])](#bodyparserrawoptions)

Returns middleware that parses all bodies as a `Buffer` and only looks at requests where the `Content-Type` header matches the `type` option.

A new `body` object containing the parsed data is populated on the `request` object after the middleware (i.e. `req.body`). This will be a `Buffer` object of the body.

#### [Options](#options-1)

The `raw` function takes an optional `options` object that may contain any of the following keys:

##### [inflate](#inflate-1)

When set to `true`, then deflated (compressed) bodies will be inflated; when `false`, deflated bodies are rejected. Defaults to `true`.

##### [limit](#limit-1)

Controls the maximum request body size. If this is a number, then the value specifies the number of bytes; if it is a string, the value is passed to the [bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults to `'100kb'`.

> It’s recommended not to configure a very high limit and to use the default value whenever possible. Allowing larger payloads increases memory usage because of the resources required for decoding and transformations, and it can also lead to longer response times as more data is processed. By ‘very high’, we mean values above the default, for example payloads of 5 MB or more can already start to introduce these risks. With the default limits, these issues do not occur.

##### [type](#type-1)

The `type` option is used to determine what media type the middleware will parse. This option can be a string, array of strings, or a function. If not a function, `type` option is passed directly to the [type-is](https://www.npmjs.com/package/type-is#readme) library and this can be an extension name (like `bin`), a mime type (like `application/octet-stream`), or a mime type with a wildcard (like `*/*` or `application/*`). If a function, the `type` option is called as `fn(req)` and the request is parsed if it returns a truthy value. Defaults to `application/octet-stream`.

##### [verify](#verify-1)

The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, where `buf` is a `Buffer` of the raw request body and `encoding` is the encoding of the request. The parsing can be aborted by throwing an error.

### [bodyParser.text(\[options\])](#bodyparsertextoptions)

Returns middleware that parses all bodies as a string and only looks at requests where the `Content-Type` header matches the `type` option.

A new `body` string containing the parsed data is populated on the `request` object after the middleware (i.e. `req.body`). This will be a string of the body.

#### [Options](#options-2)

The `text` function takes an optional `options` object that may contain any of the following keys:

##### [defaultCharset](#defaultcharset-1)

Specify the default character set for the text content if the charset is not specified in the `Content-Type` header of the request. Defaults to `utf-8`.

##### [inflate](#inflate-2)

When set to `true`, then deflated (compressed) bodies will be inflated; when `false`, deflated bodies are rejected. Defaults to `true`.

##### [limit](#limit-2)

Controls the maximum request body size. If this is a number, then the value specifies the number of bytes; if it is a string, the value is passed to the [bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults to `'100kb'`.

> It’s recommended not to configure a very high limit and to use the default value whenever possible. Allowing larger payloads increases memory usage because of the resources required for decoding and transformations, and it can also lead to longer response times as more data is processed. By ‘very high’, we mean values above the default, for example payloads of 5 MB or more can already start to introduce these risks. With the default limits, these issues do not occur.

##### [type](#type-2)

The `type` option is used to determine what media type the middleware will parse. This option can be a string, array of strings, or a function. If not a function, `type` option is passed directly to the [type-is](https://www.npmjs.com/package/type-is#readme) library and this can be an extension name (like `txt`), a mime type (like `text/plain`), or a mime type with a wildcard (like `*/*` or `text/*`). If a function, the `type` option is called as `fn(req)` and the request is parsed if it returns a truthy value. Defaults to `text/plain`.

##### [verify](#verify-2)

The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, where `buf` is a `Buffer` of the raw request body and `encoding` is the encoding of the request. The parsing can be aborted by throwing an error.

### [bodyParser.urlencoded(\[options\])](#bodyparserurlencodedoptions)

Returns middleware that only parses `urlencoded` bodies and only looks at requests where the `Content-Type` header matches the `type` option. This parser accepts only UTF-8 and ISO-8859-1 encodings of the body.

A new `body` object containing the parsed data is populated on the `request` object after the middleware (i.e. `req.body`). This object will contain key-value pairs, where the value can be a string or array (when `extended` is `false`), or any type (when `extended` is `true`).

#### [Options](#options-3)

The `urlencoded` function takes an optional `options` object that may contain any of the following keys:

##### [extended](#extended)

The “extended” syntax allows for rich objects and arrays to be encoded into the URL-encoded format, allowing for a JSON-like experience with URL-encoded. For more information, please [see the qs library](https://www.npmjs.com/package/qs#readme).

Defaults to `false`.

##### [inflate](#inflate-3)

When set to `true`, then deflated (compressed) bodies will be inflated; when `false`, deflated bodies are rejected. Defaults to `true`.

##### [limit](#limit-3)

Controls the maximum request body size. If this is a number, then the value specifies the number of bytes; if it is a string, the value is passed to the [bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults to `'100kb'`.

> It’s recommended not to configure a very high limit and to use the default value whenever possible. Allowing larger payloads increases memory usage because of the resources required for decoding and transformations, and it can also lead to longer response times as more data is processed. By ‘very high’, we mean values above the default, for example payloads of 5 MB or more can already start to introduce these risks. With the default limits, these issues do not occur.

##### [parameterLimit](#parameterlimit)

The `parameterLimit` option controls the maximum number of parameters that are allowed in the URL-encoded data. If a request contains more parameters than this value, a 413 will be returned to the client. Defaults to `1000`.

##### [type](#type-3)

The `type` option is used to determine what media type the middleware will parse. This option can be a string, array of strings, or a function. If not a function, `type` option is passed directly to the [type-is](https://www.npmjs.com/package/type-is#readme) library and this can be an extension name (like `urlencoded`), a mime type (like `application/x-www-form-urlencoded`), or a mime type with a wildcard (like `*/x-www-form-urlencoded`). If a function, the `type` option is called as `fn(req)` and the request is parsed if it returns a truthy value. Defaults to `application/x-www-form-urlencoded`.

##### [verify](#verify-3)

The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, where `buf` is a `Buffer` of the raw request body and `encoding` is the encoding of the request. The parsing can be aborted by throwing an error.

##### [defaultCharset](#defaultcharset-2)

The default charset to parse as, if not specified in content-type. Must be either `utf-8` or `iso-8859-1`. Defaults to `utf-8`.

##### [charsetSentinel](#charsetsentinel)

Whether to let the value of the `utf8` parameter take precedence as the charset selector. It requires the form to contain a parameter named `utf8` with a value of `✓`. Defaults to `false`.

##### [interpretNumericEntities](#interpretnumericentities)

Whether to decode numeric entities such as `&#9786;` when parsing an iso-8859-1 form. Defaults to `false`.

##### [depth](#depth)

The `depth` option is used to configure the maximum depth of the `qs` library when `extended` is `true`. This allows you to limit the amount of keys that are parsed and can be useful to prevent certain types of abuse. Defaults to `32`. It is recommended to keep this value as low as possible.

## [Errors](#errors)

The middlewares provided by this module create errors using the [`http-errors` module](https://www.npmjs.com/package/http-errors). The errors will typically have a `status`/`statusCode` property that contains the suggested HTTP response code, an `expose` property to determine if the `message` property should be displayed to the client, a `type` property to determine the type of error without matching against the `message`, and a `body` property containing the read body, if available.

The following are the common errors created, though any error can come through for various reasons.

### [content encoding unsupported](#content-encoding-unsupported)

This error will occur when the request had a `Content-Encoding` header that contained an encoding but the “inflation” option was set to `false`. The `status` property is set to `415`, the `type` property is set to `'encoding.unsupported'`, and the `charset` property will be set to the encoding that is unsupported.

### [entity parse failed](#entity-parse-failed)

This error will occur when the request contained an entity that could not be parsed by the middleware. The `status` property is set to `400`, the `type` property is set to `'entity.parse.failed'`, and the `body` property is set to the entity value that failed parsing.

### [entity verify failed](#entity-verify-failed)

This error will occur when the request contained an entity that could not be verified by the defined `verify` option. The `status` property is set to `403`, the `type` property is set to `'entity.verify.failed'`, and the `body` property is set to the entity value that failed verification.

### [request aborted](#request-aborted)

This error will occur when the request is aborted by the client before reading the body has finished. The `received` property will be set to the number of bytes received before the request was aborted and the `expected` property is set to the number of expected bytes. The `status` property is set to `400` and `type` property is set to `'request.aborted'`.

### [request entity too large](#request-entity-too-large)

This error will occur when the request body’s size is larger than the “limit” option. The `limit` property will be set to the byte limit and the `length` property will be set to the request body’s length. The `status` property is set to `413` and the `type` property is set to `'entity.too.large'`.

### [request size did not match content length](#request-size-did-not-match-content-length)

This error will occur when the request’s length did not match the length from the `Content-Length` header. This typically occurs when the request is malformed, typically when the `Content-Length` header was calculated based on characters instead of bytes. The `status` property is set to `400` and the `type` property is set to `'request.size.invalid'`.

### [stream encoding should not be set](#stream-encoding-should-not-be-set)

This error will occur when something called the `req.setEncoding` method prior to this middleware. This module operates directly on bytes only and you cannot call `req.setEncoding` when using this module. The `status` property is set to `500` and the `type` property is set to `'stream.encoding.set'`.

### [stream is not readable](#stream-is-not-readable)

This error will occur when the request is no longer readable when this middleware attempts to read it. This typically means something other than a middleware from this module read the request body already and the middleware was also configured to read the same request. The `status` property is set to `500` and the `type` property is set to `'stream.not.readable'`.

### [too many parameters](#too-many-parameters)

This error will occur when the content of the request exceeds the configured `parameterLimit` for the `urlencoded` parser. The `status` property is set to `413` and the `type` property is set to `'parameters.too.many'`.

### [unsupported charset “BOGUS”](#unsupported-charset-bogus)

This error will occur when the request had a charset parameter in the `Content-Type` header, but the `iconv-lite` module does not support it OR the parser does not support it. The charset is contained in the message as well as in the `charset` property. The `status` property is set to `415`, the `type` property is set to `'charset.unsupported'`, and the `charset` property is set to the charset that is unsupported.

### [unsupported content encoding “bogus”](#unsupported-content-encoding-bogus)

This error will occur when the request had a `Content-Encoding` header that contained an unsupported encoding. The encoding is contained in the message as well as in the `encoding` property. The `status` property is set to `415`, the `type` property is set to `'encoding.unsupported'`, and the `encoding` property is set to the encoding that is unsupported.

### [The input exceeded the depth](#the-input-exceeded-the-depth)

This error occurs when using `bodyParser.urlencoded` with the `extended` property set to `true` and the input exceeds the configured `depth` option. The `status` property is set to `400`. It is recommended to review the `depth` option and evaluate if it requires a higher value. When the `depth` option is set to `32` (default value), the error will not be thrown.

## [Examples](#examples)

### [Express/Connect top-level generic](#expressconnect-top-level-generic)

This example demonstrates adding a generic JSON and URL-encoded parser as a top-level middleware, which will parse the bodies of all incoming requests. This is the simplest setup.

```
const express = require('express');
const bodyParser = require('body-parser');


const app = express();


// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded());


// parse application/json
app.use(bodyParser.json());


app.use(function (req, res) {
  res.setHeader('Content-Type', 'text/plain');
  res.write('you posted:\n');
  res.end(String(JSON.stringify(req.body, null, 2)));
});
```

### [Express route-specific](#express-route-specific)

This example demonstrates adding body parsers specifically to the routes that need them. In general, this is the most recommended way to use body-parser with Express.

```
const express = require('express');
const bodyParser = require('body-parser');


const app = express();


// create application/json parser
const jsonParser = bodyParser.json();


// create application/x-www-form-urlencoded parser
const urlencodedParser = bodyParser.urlencoded();


// POST /login gets urlencoded bodies
app.post('/login', urlencodedParser, function (req, res) {
  if (!req.body || !req.body.username) res.sendStatus(400);
  res.send('welcome, ' + req.body.username);
});


// POST /api/users gets JSON bodies
app.post('/api/users', jsonParser, function (req, res) {
  if (!req.body) res.sendStatus(400);
  // create user in req.body
});
```

### [Change accepted type for parsers](#change-accepted-type-for-parsers)

All the parsers accept a `type` option which allows you to change the `Content-Type` that the middleware will parse.

```
const express = require('express');
const bodyParser = require('body-parser');


const app = express();


// parse various different custom JSON types as JSON
app.use(bodyParser.json({ type: 'application/*+json' }));


// parse some custom thing into a Buffer
app.use(bodyParser.raw({ type: 'application/vnd.custom-type' }));


// parse an HTML body into a string
app.use(bodyParser.text({ type: 'text/html' }));
```

## [License](#license)

[MIT](https://github.com/expressjs/body-parser/blob/HEAD/LICENSE)

----
url: https://expressjs.com/en/5x/guide/writing-middleware
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/guide/writing-middleware.mdx)

# [Writing middleware for use in Express apps](#overview)

*Middleware* functions are functions that have access to the [request object](/en/5x/api/request/) (`req`), the [response object](/en/5x/api/response/) (`res`), and the `next` function in the application’s request-response cycle. The `next` function is a function in the Express router which, when invoked, executes the middleware succeeding the current middleware.

Starting with Express 5, middleware functions that return a Promise will call `next(value)` when they reject or throw an error. `next` will be called with either the rejected value or the thrown Error.

## [Example](#example)

Here is an example of a simple “Hello World” Express application. The remainder of this article will define and add three middleware functions to the application: one called `myLogger` that prints a simple log message, one called `requestTime` that displays the timestamp of the HTTP request, and one called `validateCookies` that validates incoming cookies.

index.cjs

```
const express = require('express');
const app = express();


app.get('/', (req, res) => {
  res.send('Hello World!');
});


app.listen(3000);
```

index.mjs

```
import express from 'express';


const app = express();


app.get('/', (req, res) => {
  res.send('Hello World!');
});


app.listen(3000);
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


app.get('/', (req: Request, res: Response) => {
  res.send('Hello World!');
});


app.listen(3000);
```

### [Middleware function myLogger](#middleware-function-mylogger)

Here is a simple example of a middleware function called “myLogger”. This function just prints “LOGGED” when a request to the app passes through it. The middleware function is assigned to a variable named `myLogger`.

```
const myLogger = function (req, res, next) {
  console.log('LOGGED');
  next();
};
```

```
import { type Request, type Response, type NextFunction } from 'express';


const myLogger = function (req: Request, res: Response, next: NextFunction) {
  console.log('LOGGED');
  next();
};
```

Here `myLogger` is defined on its own rather than passed directly to `app.use()`, so TypeScript has no context to infer its parameters and they are annotated explicitly. You can instead type the whole function as `RequestHandler`, which types `req`, `res`, and `next` for you. When the middleware is written inline in the `app.use()` call, Express infers those three parameters and no annotations are needed.

### Caution

Notice the call above to `next()`. Calling this function invokes the next middleware function in the app. The `next()` function is not a part of the Node.js or Express API, but is the third argument that is passed to the middleware function. The `next()` function could be named anything, but by convention it is always named “next”. To avoid confusion, always use this convention.

To load the middleware function, call `app.use()`, specifying the middleware function. For example, the following code loads the `myLogger` middleware function before the route to the root path (/).

index.cjs

```
const express = require('express');
const app = express();


const myLogger = function (req, res, next) {
  console.log('LOGGED');
  next();
};


app.use(myLogger);


app.get('/', (req, res) => {
  res.send('Hello World!');
});


app.listen(3000);
```

index.mjs

```
import express from 'express';


const app = express();


const myLogger = function (req, res, next) {
  console.log('LOGGED');
  next();
};


app.use(myLogger);


app.get('/', (req, res) => {
  res.send('Hello World!');
});


app.listen(3000);
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();


const myLogger = function (req: Request, res: Response, next: NextFunction) {
  console.log('LOGGED');
  next();
};


app.use(myLogger);


app.get('/', (req: Request, res: Response) => {
  res.send('Hello World!');
});


app.listen(3000);
```

Every time the app receives a request, it prints the message “LOGGED” to the terminal.

The order of middleware loading is important: middleware functions that are loaded first are also executed first.

If `myLogger` is loaded after the route to the root path, the request never reaches it and the app doesn’t print “LOGGED”, because the route handler of the root path terminates the request-response cycle.

The middleware function `myLogger` simply prints a message, then passes on the request to the next middleware function in the stack by calling the `next()` function.

### [Middleware function requestTime](#middleware-function-requesttime)

Next, we’ll create a middleware function called “requestTime” and add a property called `requestTime` to the [request object](/en/5x/api/request/).

### Caution

Because the middleware adds a property to `req`, extend the request type in TypeScript with [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html). Declare the property (as optional, since a middleware may not run for every request) in a `.d.ts` file that is part of your project:

types/express.d.ts

```
declare global {
  namespace Express {
    interface Request {
      requestTime?: number;
    }
  }
}


export {};
```

TypeScript picks up the file automatically, so no `tsconfig.json` change is needed unless you have set a custom `include` that does not cover its location. See [Extending the API in TypeScript](/en/5x/guide/overriding-express-api/#extending-the-api-in-typescript) for adding other custom properties and methods.

```
const requestTime = function (req, res, next) {
  req.requestTime = Date.now();
  next();
};
```

```
import { type Request, type Response, type NextFunction } from 'express';


const requestTime = function (req: Request, res: Response, next: NextFunction) {
  req.requestTime = Date.now();
  next();
};
```

The app now uses the `requestTime` middleware function. Also, the callback function of the root path route uses the property that the middleware function adds to `req` (the request object).

index.cjs

```
const express = require('express');
const app = express();


const requestTime = function (req, res, next) {
  req.requestTime = Date.now();
  next();
};


app.use(requestTime);


app.get('/', (req, res) => {
  let responseText = 'Hello World!<br>';
  responseText += `<small>Requested at: ${req.requestTime}</small>`;
  res.send(responseText);
});


app.listen(3000);
```

index.mjs

```
import express from 'express';


const app = express();


const requestTime = function (req, res, next) {
  req.requestTime = Date.now();
  next();
};


app.use(requestTime);


app.get('/', (req, res) => {
  let responseText = 'Hello World!<br>';
  responseText += `<small>Requested at: ${req.requestTime}</small>`;
  res.send(responseText);
});


app.listen(3000);
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();


const requestTime = function (req: Request, res: Response, next: NextFunction) {
  req.requestTime = Date.now();
  next();
};


app.use(requestTime);


app.get('/', (req: Request, res: Response) => {
  let responseText = 'Hello World!<br>';
  responseText += `<small>Requested at: ${req.requestTime}</small>`;
  res.send(responseText);
});


app.listen(3000);
```

When you make a request to the root of the app, the app now displays the timestamp of your request in the browser.

### [Middleware function validateCookies](#middleware-function-validatecookies)

Finally, we’ll create a middleware function that validates incoming cookies and sends a 400 response if cookies are invalid.

Here’s an example function that validates cookies with an external async service.

```
async function cookieValidator(cookies) {
  try {
    await externallyValidateCookie(cookies.testCookie);
  } catch {
    throw new Error('Invalid cookies');
  }
}
```

```
async function cookieValidator(cookies: Record<string, string>) {
  try {
    await externallyValidateCookie(cookies.testCookie);
  } catch {
    throw new Error('Invalid cookies');
  }
}
```

Here, we use the [`cookie-parser`](/en/resources/middleware/cookie-parser/) middleware to parse incoming cookies off the `req` object and pass them to our `cookieValidator` function. The `validateCookies` middleware returns a Promise that upon rejection will automatically trigger our error handler.

index.cjs

```
const express = require('express');
const cookieParser = require('cookie-parser');
const cookieValidator = require('./cookieValidator');


const app = express();


async function validateCookies(req, res, next) {
  await cookieValidator(req.cookies);
  next();
}


app.use(cookieParser());


app.use(validateCookies);


// error handler
app.use((err, req, res, next) => {
  res.status(400).send(err.message);
});


app.listen(3000);
```

index.mjs

```
import express from 'express';
import cookieParser from 'cookie-parser';
import cookieValidator from './cookieValidator';


const app = express();


async function validateCookies(req, res, next) {
  await cookieValidator(req.cookies);
  next();
}


app.use(cookieParser());


app.use(validateCookies);


// error handler
app.use((err, req, res, next) => {
  res.status(400).send(err.message);
});


app.listen(3000);
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';
import cookieParser from 'cookie-parser';
import cookieValidator from './cookieValidator';


const app: Express = express();


async function validateCookies(req: Request, res: Response, next: NextFunction) {
  await cookieValidator(req.cookies);
  next();
}


app.use(cookieParser());


app.use(validateCookies);


// error handler
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  res.status(400).send(err.message);
});


app.listen(3000);
```

### Caution

Note how `next()` is called after `await cookieValidator(req.cookies)`. This ensures that if `cookieValidator` resolves, the next middleware in the stack will get called. If you pass anything to the `next()` function (except the string `'route'` or `'router'`), Express regards the current request as being an error and will skip any remaining non-error handling routing and middleware functions.

Because you have access to the [request object](/en/5x/api/request/), the [response object](/en/5x/api/response/), the next middleware function in the stack, and the whole [Node.js API](https://nodejs.org/api/), the possibilities with middleware functions are endless.

## [Configurable middleware](#configurable-middleware)

If you need your middleware to be configurable, export a function which accepts an options object or other parameters, which, then returns the middleware implementation based on the input parameters.

my-middleware.cjs

```
module.exports = function (options) {
  return function (req, res, next) {
    // Implement the middleware function based on the options object
    next();
  };
};
```

my-middleware.mjs

```
export default function (options) {
  return function (req, res, next) {
    // Implement the middleware function based on the options object
    next();
  };
}
```

my-middleware.ts

```
import { type Request, type Response, type NextFunction } from 'express';


export default function (options: Record<string, unknown>) {
  return function (req: Request, res: Response, next: NextFunction) {
    // Implement the middleware function based on the options object
    next();
  };
}
```

The middleware can now be used as shown below.

index.cjs

```
const mw = require('./my-middleware.cjs');


app.use(mw({ option1: '1', option2: '2' }));
```

index.mjs

```
import mw from './my-middleware.mjs';


app.use(mw({ option1: '1', option2: '2' }));
```

Refer to [cookie-session](https://github.com/expressjs/cookie-session) and [compression](https://github.com/expressjs/compression) for examples of configurable middleware.

----
url: https://expressjs.com/en/resources/
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/index.mdx)

# [Resources](#overview)

Find resources to help you learn, contribute, and connect with the Express.js ecosystem. Whether you’re looking to get involved in the community, explore middleware, or understand key concepts, you’ll find what you need here.

### [Community](/en/resources/community/)

[Connect with the Express.js community, learn about the technical committee, and get involved in discussions.](/en/resources/community/)

### [Contributing to Express](/en/resources/contributing/)

[Find out how to contribute to Express.js, including guidelines for reporting issues and submitting pull requests.](/en/resources/contributing/)

### [Glossary](/en/resources/glossary/)

[A comprehensive glossary of terms related to Express.js, Node.js, middleware, routing, and other key concepts.](/en/resources/glossary/)

### [Utilities](/en/resources/utils/)

[Discover utility modules related to Express.js and Node.js, including tools for cookies, CSRF protection, URL parsing, and more.](/en/resources/utils/)

### [Middleware](/en/resources/middleware/)

[Explore middleware modules for Express.js to extend your application with additional functionality.](/en/resources/middleware/)

----
url: https://expressjs.com/en/4x/api/response
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/4x/api/response/index.mdx)

# [Response](#overview)

The `res` object represents the HTTP response that an Express app sends when it gets an HTTP request.

In this documentation and by convention, the object is always referred to as `res` (and the HTTP request is `req`) but its actual name is determined by the parameters to the callback function in which you’re working.

For example:

```
app.get('/user/:id', function (req, res) {
  res.send('user ' + req.params.id);
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/:id', function (req: Request, res: Response) {
  res.send('user ' + req.params.id);
});
```

But you could just as well have:

```
app.get('/user/:id', function (request, response) {
  response.send('user ' + request.params.id);
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/:id', function (request: Request, response: Response) {
  response.send('user ' + request.params.id);
});
```

The `res` object is an enhanced version of Node’s own response object and supports all [built-in fields and methods](https://nodejs.org/api/http.html#class-httpserverresponse).

## [Properties](#properties)

### [res.app](#resapp)

Type:`Application`

This property holds a reference to the instance of the Express application that is using the middleware.

`res.app` is identical to the [req.app](/en/4x/api/request/#reqapp) property in the request object.

```
app.get('/', function (req, res) {
  console.dir(res.app.get('view engine'));
  console.dir(res.app === req.app);
  // => true
  res.send('OK');
});
```

```
import { type Request, type Response } from 'express';


app.get('/', function (req: Request, res: Response) {
  console.dir(res.app.get('view engine'));
  console.dir(res.app === req.app);
  // => true
  res.send('OK');
});
```

### [res.headersSent](#resheaderssent)

Type:`Boolean`

Boolean property that indicates if the app sent HTTP headers for the response.

```
app.get('/', function (req, res) {
  console.dir(res.headersSent); // false
  res.send('OK');
  console.dir(res.headersSent); // true
});
```

```
import { type Request, type Response } from 'express';


app.get('/', function (req: Request, res: Response) {
  console.dir(res.headersSent); // false
  res.send('OK');
  console.dir(res.headersSent); // true
});
```

### [res.locals](#reslocals)

Type:`Object`

Use this property to set variables accessible in templates rendered with [res.render](#resrender). The variables set on `res.locals` are available within a single request-response cycle, and will not be shared between requests.

### Warning

The `locals` object is used by view engines to render a response. The object keys may be particularly sensitive and should not contain user-controlled input, as it may affect the operation of the view engine or provide a path to cross-site scripting. Consult the documentation for the used view engine for additional considerations.

In order to keep local variables for use in template rendering between requests, use [app.locals](/en/4x/api/application/#applocals) instead.

This property is useful for exposing request-level information such as the request path name, authenticated user, user settings, and so on to templates rendered within the application.

```
app.use(function (req, res, next) {
  // Make `user` and `authenticated` available in templates
  res.locals.user = req.user;
  res.locals.authenticated = !req.user.anonymous;
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use(function (req: Request, res: Response, next: NextFunction) {
  // Make `user` and `authenticated` available in templates
  res.locals.user = req.user;
  res.locals.authenticated = !req.user.anonymous;
  next();
});
```

### [res.req](#resreq)

Type:`Request`

This property holds a reference to the [request object](/en/4x/api/request/) that relates to this response object.

```
app.get('/', function (req, res) {
  console.dir(res.req === req);
  // => true
  res.send('OK');
});
```

```
import { type Request, type Response } from 'express';


app.get('/', function (req: Request, res: Response) {
  console.dir(res.req === req);
  // => true
  res.send('OK');
});
```

Added in:`v4.11.0`

Appends the specified `value` to the HTTP response header `field`. If the header is not already set, it creates the header with the specified value. The `value` parameter can be a string or an array.

### Note

calling `res.set()` after `res.append()` will reset the previously-set header value.

```
res.append('Link', ['<http://localhost/>', '<http://localhost:3000/>']);
res.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly');
res.append('Warning', '199 Miscellaneous warning');
```

### [res.attachment()](#resattachment)

#### Arguments

`filename`

Type:`String | undefined`

The file name used to set the `Content-Disposition` “filename=” parameter and the `Content-Type` (from its extension).

↵Returns:`Response`

Sets the HTTP response `Content-Disposition` header field to “attachment”. If a `filename` is given, then it sets the Content-Type based on the extension name via `res.type()`, and sets the `Content-Disposition` “filename=” parameter.

```
res.attachment();
// Content-Disposition: attachment


res.attachment('path/to/logo.png');
// Content-Disposition: attachment; filename="logo.png"
// Content-Type: image/png
```

If the `maxAge` or `expires` options are set, the cookie may not be cleared depending on the time values provided, as Express does not ignore these options. It is therefore recommended to omit these options when calling this method. Passing these two options has been deprecated since Express v4.20.0.

### Caution

Web browsers and other compliant clients will only clear the cookie if the given `options` is identical to those given to [res.cookie()](#rescookie), excluding `expires` and `maxAge`.

```
res.cookie('name', 'tobi', { path: '/admin' });
res.clearCookie('name', { path: '/admin' });
```

```
res.cookie('name', 'tobi', { domain: '.example.com', path: '/admin', secure: true });
res.cookie('remember_me', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
```

You can set multiple cookies in a single response by calling `res.cookie` multiple times, for example:

```
res
  .status(201)
  .cookie('access_token', 'Bearer ' + token, {
    expires: new Date(Date.now() + 8 * 3600000), // cookie will be removed after 8 hours
  })
  .cookie('test', 'test')
  .redirect(301, '/admin');
```

The `encode` option allows you to choose the function used for cookie value encoding. Does not support asynchronous functions.

Example use case: You need to set a domain-wide cookie for another site in your organization. This other site (not under your administrative control) does not use URI-encoded cookie values.

```
// Default encoding
res.cookie('some_cross_domain_cookie', 'http://mysubdomain.example.com', { domain: 'example.com' });
// Result: 'some_cross_domain_cookie=http%3A%2F%2Fmysubdomain.example.com; Domain=example.com; Path=/'


// Custom encoding
res.cookie('some_cross_domain_cookie', 'http://mysubdomain.example.com', {
  domain: 'example.com',
  encode: String,
});
// Result: 'some_cross_domain_cookie=http://mysubdomain.example.com; Domain=example.com; Path=/;'
```

The `maxAge` option is a convenience option for setting “expires” relative to the current time in milliseconds. The following is equivalent to the second example above.

```
res.cookie('remember_me', '1', { maxAge: 900000, httpOnly: true });
```

You can pass an object as the `value` parameter; it is then serialized as JSON and parsed by `bodyParser()` middleware.

```
res.cookie('cart', { items: [1, 2, 3] });
res.cookie('cart', { items: [1, 2, 3] }, { maxAge: 900000 });
```

When using [cookie-parser](https://www.npmjs.com/package/cookie-parser) middleware, this method also supports signed cookies. Simply include the `signed` option set to `true`. Then `res.cookie()` will use the secret passed to `cookieParser(secret)` to sign the value.

```
res.cookie('name', 'tobi', { signed: true });
```

Later you may access this value through the [req.signedCookie](/en/4x/api/request/#reqsignedcookies) object.

Type:`Object | undefined`Added in:`v4.16.0`

```
res.download('/report-12345.pdf');


res.download('/report-12345.pdf', 'report.pdf');


res.download('/report-12345.pdf', 'report.pdf', function (err) {
  if (err) {
    // Handle error, but keep in mind the response may be partially-sent
    // so check res.headersSent
  } else {
    // decrement a download credit, etc.
  }
});
```

```
res.end();
res.status(404).end();
```

### [res.format()](#resformat)

#### Arguments

`object`

Type:`Object`

An object whose keys are MIME types (or extension names) mapped to handler functions, optionally with a `default` handler.

↵Returns:`Response`

Performs content-negotiation on the `Accept` HTTP header on the request object, when present. It uses [req.accepts()](/en/4x/api/request/#reqaccepts) to select a handler for the request, based on the acceptable types ordered by their quality values. If the header is not specified, the first callback is invoked. When no match is found, the server responds with 406 “Not Acceptable”, or invokes the `default` callback.

The `Content-Type` response header is set when a callback is selected. However, you may alter this within the callback using methods such as `res.set()` or `res.type()`.

The following example would respond with `{ "message": "hey" }` when the `Accept` header field is set to “application/json” or ”\*/json” (however if it is ”\*/\*”, then the response will be “hey”).

```
res.format({
  'text/plain': function () {
    res.send('hey');
  },


  'text/html': function () {
    res.send('<p>hey</p>');
  },


  'application/json': function () {
    res.send({ message: 'hey' });
  },


  default: function () {
    // log the request and respond with 406
    res.status(406).send('Not Acceptable');
  },
});
```

In addition to canonicalized MIME types, you may also use extension names mapped to these types for a slightly less verbose implementation:

```
res.format({
  text: function () {
    res.send('hey');
  },


  html: function () {
    res.send('<p>hey</p>');
  },


  json: function () {
    res.send({ message: 'hey' });
  },
});
```

```
res.get('Content-Type');
// => "text/plain"
```

### [res.json()](#resjson)

#### Arguments

`body`

Type:`any | undefined`

The value to send as JSON. Can be any JSON type: object, array, string, Boolean, number, or null.

`status`

Type:`Number | undefined`Deprecated in:`v4.2.0`

The HTTP status code, accepted as a positional argument by the old `res.json(obj, status)` and `res.json(status, obj)` signatures. Use [res.status()](#resstatus) instead.

↵Returns:`Response`

Sends a JSON response. This method sends a response (with the correct content-type) that is the parameter converted to a JSON string using [JSON.stringify()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).

The parameter can be any JSON type, including object, array, string, Boolean, number, or null, and you can also use it to convert other values to JSON.

```
res.json(null);
res.json({ user: 'tobi' });
res.status(500).json({ error: 'message' });
```

### Caution

The signature `res.json(obj, status)` has been deprecated since Express v4.2.0 (and the reversed `res.json(status, obj)` since v4.7.0). Set the status separately and chain the call instead: `res.status(status).json(obj)`.

You can update your code automatically with the following codemod:

Terminal window

```
npx codemod@latest @expressjs/status-send-order
```

Terminal window

```
yarn dlx codemod@latest @expressjs/status-send-order
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/status-send-order
```

Terminal window

```
bunx codemod@latest @expressjs/status-send-order
```

### [res.jsonp()](#resjsonp)

#### Arguments

`body`

Type:`any | undefined`

The value to send as a JSONP response. Can be any JSON type.

`status`

Type:`Number | undefined`Deprecated in:`v4.2.0`

The HTTP status code, accepted as a positional argument by the old `res.jsonp(obj, status)` and `res.jsonp(status, obj)` signatures. Use [res.status()](#resstatus) instead.

↵Returns:`Response`

Sends a JSON response with JSONP support. This method is identical to `res.json()`, except that it opts-in to JSONP callback support.

```
res.jsonp(null);
// => callback(null)


res.jsonp({ user: 'tobi' });
// => callback({ "user": "tobi" })


res.status(500).jsonp({ error: 'message' });
// => callback({ "error": "message" })
```

By default, the JSONP callback name is simply `callback`. Override this with the

[jsonp callback name](/en/4x/api/application/#application-settings) setting.

The following are some examples of JSONP responses using the same code:

```
// ?callback=foo
res.jsonp({ user: 'tobi' });
// => foo({ "user": "tobi" })


app.set('jsonp callback name', 'cb');


// ?cb=foo
res.status(500).jsonp({ error: 'message' });
// => foo({ "error": "message" })
```

### Caution

The signature `res.jsonp(obj, status)` has been deprecated since Express v4.2.0 (and the reversed `res.jsonp(status, obj)` since v4.7.0). Set the status separately and chain the call instead: `res.status(status).jsonp(obj)`.

You can update your code automatically with the following codemod:

Terminal window

```
npx codemod@latest @expressjs/status-send-order
```

Terminal window

```
yarn dlx codemod@latest @expressjs/status-send-order
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/status-send-order
```

Terminal window

```
bunx codemod@latest @expressjs/status-send-order
```

### [res.links()](#reslinks)

#### Arguments

`links`

Type:`Record<String, String>`

An object whose properties (such as `next` and `last`) populate the `Link` response header.

↵Returns:`Response`

Joins the `links` provided as properties of the parameter to populate the response’s `Link` HTTP header field.

For example, the following call:

```
res.links({
  next: 'http://api.example.com/users?page=2',
  last: 'http://api.example.com/users?page=5',
});
```

Yields the following results:

```
Link: <http://api.example.com/users?page=2>; rel="next",
      <http://api.example.com/users?page=5>; rel="last"
```

```
res.location('/foo/bar');
res.location('http://example.com');
res.location('back');
```

### Caution

`'back'` was deprecated in 4.21.0, use `req.get('Referrer') || '/'` as an argument instead.

A `path` value of “back” has a special meaning, it refers to the URL specified in the `Referer` header of the request. If the `Referer` header was not specified, it refers to ”/”.

See also [Security best practices: Prevent open redirect vulnerabilities](/en/advanced/best-practice-security/#prevent-open-redirects).

Redirects to the URL derived from the specified `path`, with specified `status`, a positive integer that corresponds to an [HTTP status code](https://www.rfc-editor.org/rfc/rfc9110#name-status-codes) . If not specified, `status` defaults to 302 “Found”.

```
res.redirect('/foo/bar');
res.redirect('http://example.com');
res.redirect(301, 'http://example.com');
res.redirect('../login');
```

### Caution

The reversed signature `res.redirect(path, status)` (status as the second argument) has been deprecated since Express v4.6.0. Use `res.redirect(status, path)` instead.

You can update your code automatically with the following codemod:

Terminal window

```
npx codemod@latest @expressjs/redirect-arg-order
```

Terminal window

```
yarn dlx codemod@latest @expressjs/redirect-arg-order
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/redirect-arg-order
```

Terminal window

```
bunx codemod@latest @expressjs/redirect-arg-order
```

Redirects can be a fully-qualified URL for redirecting to a different site:

```
res.redirect('https://google.com');
```

Redirects can be relative to the root of the host name. For example, if the application is on `http://example.com/admin/post/new`, the following would redirect to the URL `http://example.com/admin`:

```
res.redirect('/admin');
```

Redirects can be relative to the current URL. For example, from `http://example.com/blog/admin/` (notice the trailing slash), the following would redirect to the URL `http://example.com/blog/admin/post/new`.

```
res.redirect('post/new');
```

Redirecting to `post/new` from `http://example.com/blog/admin` (no trailing slash), will redirect to `http://example.com/blog/post/new`.

If you found the above behavior confusing, think of path segments as directories (with trailing slashes) and files, it will start to make sense.

Path-relative redirects are also possible. If you were on `http://example.com/admin/post/new`, the following would redirect to `http://example.com/admin/post`:

```
res.redirect('..');
```

A `back` redirection redirects the request back to the [referer](https://en.wikipedia.org/wiki/HTTP_referer), defaulting to `/` when the referer is missing.

```
res.redirect('back');
```

### Caution

`back` redirect was deprecated in 4.21.0, use `req.get('Referrer') || '/'` as an argument instead.

For more information, see [Using template engines with Express](/en/4x/guide/using-template-engines/).

### Warning

The `view` argument performs file system operations like reading a file from disk and evaluating Node.js modules, and as so for security reasons should not contain input from the end-user.

### Warning

The `locals` object is used by view engines to render a response. The object keys may be particularly sensitive and should not contain user-controlled input, as it may affect the operation of the view engine or provide a path to cross-site scripting. Consult the documentation for the used view engine for additional considerations.

### Caution

The local variable `cache` enables view caching. Set it to `true`, to cache the view during development; view caching is enabled in production by default.

```
// send the rendered view to the client
res.render('index');


// if a callback is specified, the rendered HTML string has to be sent explicitly
res.render('index', function (err, html) {
  res.send(html);
});


// pass a local variable to the view
res.render('user', { name: 'Tobi' }, function (err, html) {
  // ...
});
```

### [res.send()](#ressend)

#### Arguments

`body`

Type:`String | Buffer | Object | Array | Boolean | undefined`

The response body. Strings are sent as HTML; objects and arrays as JSON; Buffers as binary.

`status`

Type:`Number | undefined`Deprecated in:`v4.5.0`

The HTTP status code, accepted as a positional argument by the old `res.send(body, status)`, `res.send(status, body)`, and `res.send(status)` signatures. Use [res.status()](#resstatus) or [res.sendStatus()](#ressendstatus) instead.

↵Returns:`Response`

Sends the HTTP response.

The `body` parameter can be a `Buffer` object, a `String`, an object, `Boolean`, or an `Array`. For example:

```
res.send(Buffer.from('whoop'));
res.send({ some: 'json' });
res.send('<p>some html</p>');
res.status(404).send('Sorry, we cannot find that!');
res.status(500).send({ error: 'something blew up' });
```

This method performs many useful tasks for simple non-streaming responses: For example, it automatically assigns the `Content-Length` HTTP response header field (unless previously defined) and provides automatic HEAD and HTTP cache freshness support.

When the parameter is a `Buffer` object, the method sets the `Content-Type` response header field to “application/octet-stream”, unless previously defined as shown below:

```
res.set('Content-Type', 'text/html');
res.send(Buffer.from('<p>some html</p>'));
```

When the parameter is a `String`, the method sets the `Content-Type` to “text/html”:

```
res.send('<p>some html</p>');
```

When the parameter is an `Array` or `Object`, Express responds with the JSON representation:

```
res.send({ user: 'tobi' });
res.send([1, 2, 3]);
```

### Caution

The signatures `res.send(body, status)` and `res.send(status)` have been deprecated since Express v4.5.0 (the reversed `res.send(status, body)` since v4.7.0). To set the status, chain the call: `res.status(status).send(body)`. To send only a status code, use [`res.sendStatus()`](#ressendstatus). If you need to send a number as the body, convert it to a string first (for example, `res.send(String(123))`) so it is not interpreted as a status code.

You can update your code automatically with the following codemod:

Terminal window

```
npx codemod@latest @expressjs/status-send-order
```

Terminal window

```
yarn dlx codemod@latest @expressjs/status-send-order
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/status-send-order
```

Terminal window

```
bunx codemod@latest @expressjs/status-send-order
```

Added in:`v4.8.0`

Transfers the file at the given `path`. Sets the `Content-Type` response HTTP header field based on the filename’s extension. Unless the `root` option is set in the options object, `path` must be an absolute path to the file.

### Warning

This API provides access to data on the running file system. Ensure that either (a) the way in which the `path` argument was constructed into an absolute path is secure if it contains user input or (b) set the `root` option to the absolute path of a directory to contain access within.

When the `root` option is provided, the `path` argument is allowed to be a relative path, including containing `..`. Express will validate that the relative path provided as `path` will resolve within the given `root` option.

The method invokes the callback function `fn(err)` when the transfer is complete or when an error occurs. If the callback function is specified and an error occurs, the callback function must explicitly handle the response process either by ending the request-response cycle, or by passing control to the next route.

Here is an example of using `res.sendFile` with all its arguments.

```
app.get('/file/:name', function (req, res, next) {
  var options = {
    root: path.join(__dirname, 'public'),
    dotfiles: 'deny',
    headers: {
      'x-timestamp': Date.now(),
      'x-sent': true,
    },
  };


  var fileName = req.params.name;
  res.sendFile(fileName, options, function (err) {
    if (err) {
      next(err);
    } else {
      console.log('Sent:', fileName);
    }
  });
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get('/file/:name', function (req: Request, res: Response, next: NextFunction) {
  const options = {
    root: path.join(__dirname, 'public'),
    dotfiles: 'deny',
    headers: {
      'x-timestamp': Date.now(),
      'x-sent': true,
    },
  };


  const fileName = req.params.name;
  res.sendFile(fileName, options, function (err) {
    if (err) {
      next(err);
    } else {
      console.log('Sent:', fileName);
    }
  });
});
```

The following example illustrates using `res.sendFile` to provide fine-grained support for serving files:

```
app.get('/user/:uid/photos/:file', function (req, res) {
  var uid = req.params.uid;
  var file = req.params.file;


  req.user.mayViewFilesFrom(uid, function (yes) {
    if (yes) {
      res.sendFile('/uploads/' + uid + '/' + file);
    } else {
      res.status(403).send("Sorry! You can't see that.");
    }
  });
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/:uid/photos/:file', function (req: Request, res: Response) {
  const uid = req.params.uid;
  const file = req.params.file;


  req.user.mayViewFilesFrom(uid, function (yes) {
    if (yes) {
      res.sendFile('/uploads/' + uid + '/' + file);
    } else {
      res.status(403).send("Sorry! You can't see that.");
    }
  });
});
```

For more information, or if you have issues or concerns, see [send](https://github.com/pillarjs/send).

### [res.sendfile()](#ressendfile-1)

#### Arguments

`path`

Type:`String`

The path to the file to transfer.

`options`

Type:`Object | undefined`

Options for serving the file. In addition to the options accepted by [`res.sendFile()`](#ressendfile), the legacy `hidden` and `from` options are supported (use `dotfiles` and `root` instead).

`fn`

Type:`Function | undefined`

Callback `fn(err)` invoked when the transfer completes or an error occurs.

Deprecated in:`v4.8.0`

### Caution

`res.sendfile()` (lower-cased) is the legacy version of [`res.sendFile()`](#ressendfile) and behaves identically. The camel-cased `res.sendFile()` was introduced in Express v4.8.0, and `res.sendfile()` has emitted a deprecation warning since that release. Use `res.sendFile()` instead.

You can update your code automatically with the following codemod:

Terminal window

```
npx codemod@latest @expressjs/camelcase-sendfile
```

Terminal window

```
yarn dlx codemod@latest @expressjs/camelcase-sendfile
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/camelcase-sendfile
```

Terminal window

```
bunx codemod@latest @expressjs/camelcase-sendfile
```

Transfers the file at the given `path`. This is the legacy, lower-cased version of [`res.sendFile()`](#ressendfile) and behaves the same way. Prefer `res.sendFile()` in new code.

```
res.sendStatus(404);
```

```
res.set('Content-Type', 'text/plain');


res.set({
  'Content-Type': 'text/plain',
  'Content-Length': '123',
  ETag: '12345',
});
```

```
res.status(403).end();
res.status(400).send('Bad Request');
res.status(404).sendFile('/absolute/path/to/404.png');
```

### [res.type()](#restype)

#### Arguments

`type`

Type:`String`

The MIME type, or a file extension that is looked up to a MIME type. If it contains `/`, it is used as-is.

↵Returns:`Response`

Sets the `Content-Type` HTTP header to the MIME type as determined by the specified `type`. If `type` contains the ”/” character, then it sets the `Content-Type` to the exact value of `type`, otherwise it is assumed to be a file extension and the MIME type is looked up in a mapping using the `express.static.mime.lookup()` method.

```
res.type('.html');
// => 'text/html'
res.type('html');
// => 'text/html'
res.type('json');
// => 'application/json'
res.type('application/json');
// => 'application/json'
res.type('png');
// => 'image/png'
```

```
res.vary('User-Agent').render('docs');
```

----
url: https://expressjs.com/en/5x/guide/debugging
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/guide/debugging.mdx)

# [Debugging Express](#overview)

To see all the internal logs used in Express, set the `DEBUG` environment variable to `express:*,router,router:*` when launching your app. Routing is handled by the separate [router](https://github.com/pillarjs/router) package, so its logs live under the `router` namespace and are not included in `express:*`.

Terminal window

```
$ DEBUG=express:*,router,router:* node index.js
```

On Windows, use the corresponding command.

Terminal window

```
> $env:DEBUG = "express:*,router,router:*"; node index.js
```

Running this command on a small app with a JSON body parser and a mounted router prints the following output:

index.cjs

```
const express = require('express');


const app = express();


app.use(express.json());


const users = express.Router();
users.get('/', (req, res) => {
  res.json([]);
});


app.use('/users', users);


app.get('/', (req, res) => {
  res.send('Hello World!');
});


app.listen(3000);
```

index.mjs

```
import express from 'express';


const app = express();


app.use(express.json());


const users = express.Router();
users.get('/', (req, res) => {
  res.json([]);
});


app.use('/users', users);


app.get('/', (req, res) => {
  res.send('Hello World!');
});


app.listen(3000);
```

Terminal window

```
$ DEBUG=express:*,router,router:* node index.js
  express:application set "x-powered-by" to true +0ms
  express:application set "etag" to 'weak' +3ms
  express:application set "etag fn" to [Function: generateETag] +0ms
  express:application set "env" to 'development' +1ms
  express:application set "query parser" to 'simple' +0ms
  express:application set "query parser fn" to [Function: parse] +0ms
  express:application set "subdomain offset" to 2 +1ms
  express:application set "trust proxy" to false +0ms
  express:application set "trust proxy fn" to [Function: trustNone] +1ms
  express:application booting in development mode +0ms
  express:application set "view" to [Function: View] +0ms
  express:application set "views" to '/projects/example/views' +1ms
  express:application set "jsonp callback name" to 'callback' +0ms
  router use '/' jsonParser +0ms
  router:layer new '/' +0ms
  router:route new '/' +0ms
  router:layer new '/' +3ms
  router:route get / +0ms
  router:layer new '/' +1ms
  router use '/users' router +4ms
  router:layer new '/users' +0ms
  router:route new '/' +1ms
  router:layer new '/' +0ms
  router:route get / +1ms
  router:layer new '/' +1ms
```

When a request is then made to the app, you will see the logs specified in the Express code:

Terminal window

```
  router dispatching GET /users +712ms
  router jsonParser  : /users +1ms
  router trim prefix (/users) from url /users +2ms
  router router /users : /users +0ms
  router dispatching GET / +0ms
```

To see the logs only from the router implementation, set the value of `DEBUG` to `router,router:*`. Likewise, to see logs only from the application implementation, set the value of `DEBUG` to `express:application`, and so on.

## [Using `debug` in your own code](#using-debug-in-your-own-code)

The same [debug](https://www.npmjs.com/package/debug) module that Express uses internally is available for your application code. Install it, create one or more loggers scoped to a namespace of your choosing, and call them wherever you would otherwise use `console.log`:

Terminal window

```
npm install debug
```

Terminal window

```
yarn add debug
```

Terminal window

```
pnpm add debug
```

Terminal window

```
bun add debug
```

index.cjs

```
const express = require('express');
const debug = require('debug')('myapp:server');


const app = express();


app.get('/', (req, res) => {
  debug('handling request from %s', req.ip);
  res.send('Hello World!');
});


app.listen(3000, () => {
  debug('listening on port 3000');
});
```

index.mjs

```
import express from 'express';
import debugModule from 'debug';


const debug = debugModule('myapp:server');
const app = express();


app.get('/', (req, res) => {
  debug('handling request from %s', req.ip);
  res.send('Hello World!');
});


app.listen(3000, () => {
  debug('listening on port 3000');
});
```

These statements print nothing by default. Enable them through the same `DEBUG` environment variable, using your own namespace:

Terminal window

```
$ DEBUG=myapp:* node index.js
```

You can specify more than one debug namespace by assigning a comma-separated list of names:

Terminal window

```
$ DEBUG=myapp:*,router node index.js
```

## [Setting DEBUG in your IDE](#setting-debug-in-your-ide)

The `DEBUG` environment variable can be set by any process launcher that supports environment variables, including the run and debug configurations of your IDE. For example, in VS Code you can set it in the `env` property of a launch configuration:

.vscode/launch.json

```
{
  "type": "node",
  "request": "launch",
  "name": "Launch Express app",
  "program": "${workspaceFolder}/index.js",
  "env": { "DEBUG": "express:*,router,router:*" }
}
```

See [Node.js debugging in VS Code](https://code.visualstudio.com/docs/nodejs/nodejs-debugging) for the full list of launch options.

## [Using the Node.js inspector](#using-the-nodejs-inspector)

Debug logs show what the app did; for stepping through your code with breakpoints, use the built-in Node.js inspector. Start your app with the `--inspect` flag:

Terminal window

```
$ node --inspect index.js
```

Then attach a debugging client, such as Chrome DevTools (open `chrome://inspect`), VS Code, or any other inspector-capable tool, to set breakpoints in your route handlers and middleware, step through code, and inspect variables.

If you need to debug something that happens during startup, use `--inspect-brk` instead, which pauses execution on the first line until a debugger attaches. See the [Node.js debugging guide](https://nodejs.org/learn/getting-started/debugging) for details.

## [Debugging the HTTP layer](#debugging-the-http-layer)

Express runs on top of the Node.js `http` module, which has its own debugging facilities that work with any Express app.

Setting the `NODE_DEBUG` environment variable to `http` makes Node.js print internal logs from the HTTP layer, such as connection handling and socket events:

Terminal window

```
$ NODE_DEBUG=http node index.js
```

You can combine it with other subsystems, such as `net` or `stream`, in a comma-separated list. Be aware that this output can expose sensitive data such as authentication headers, so use it only in development.

## [Diagnostics channels](#diagnostics-channels)

Node.js publishes an event for every HTTP request through the [diagnostics\_channel](https://nodejs.org/api/diagnostics_channel.html#http) module, which you can subscribe to without patching Express or adding middleware:

index.cjs

```
const { subscribe } = require('node:diagnostics_channel');


subscribe('http.server.request.start', ({ request }) => {
  console.log(`${request.method} ${request.url}`);
});
```

index.mjs

```
import { subscribe } from 'node:diagnostics_channel';


subscribe('http.server.request.start', ({ request }) => {
  console.log(`${request.method} ${request.url}`);
});
```

Other built-in channels cover the rest of the request lifecycle, such as `http.server.response.finish`, and the client side of `http.request` calls. See the [diagnostics\_channel documentation](https://nodejs.org/api/diagnostics_channel.html#http) for the full list.

## [Advanced options](#advanced-options)

When running through Node.js, you can set a few environment variables that will change the behavior of the debug logging:

| Name                | Purpose                                           |
| ------------------- | ------------------------------------------------- |
| `DEBUG`             | Enables/disables specific debugging namespaces.   |
| `DEBUG_COLORS`      | Whether or not to use colors in the debug output. |
| `DEBUG_DEPTH`       | Object inspection depth.                          |
| `DEBUG_FD`          | File descriptor to write debug output to.         |
| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects.     |

### Note

The environment variables beginning with `DEBUG_` end up being converted into an Options object that gets used with `%o`/`%O` formatters. See the Node.js documentation for [`util.inspect()`](https://nodejs.org/api/util.html#utilinspectobject-options) for the complete list.

----
url: https://expressjs.com/en/5x/guide/overriding-express-api
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/guide/overriding-express-api.mdx)

# [Overriding the Express API](#overview)

The Express API consists of various methods and properties on the [request](/en/5x/api/request/) and [response](/en/5x/api/response/) objects. These are inherited by prototype. There are two extension points for the Express API:

1. The global prototypes at `express.request` and `express.response`.
2. App-specific prototypes at `app.request` and `app.response`.

Altering the global prototypes will affect all loaded Express apps in the same process. If desired, alterations can be made app-specific by only altering the app-specific prototypes after creating a new app.

## [Methods](#methods)

You can override the signature and behavior of existing methods with your own, by assigning a custom function.

Following is an example of overriding the behavior of [res.sendStatus](/en/5x/api/response/#ressendstatus).

```
app.response.sendStatus = function (statusCode, type, message) {
  // code is intentionally kept simple for demonstration purpose
  return this.contentType(type).status(statusCode).send(message);
};
```

```
import { type Response } from 'express';


// Broaden the type of sendStatus so call sites accept the new arguments.
declare module 'express-serve-static-core' {
  interface Response {
    sendStatus(statusCode: number, type: string, message: string): this;
  }
}


app.response.sendStatus = function (
  this: Response,
  statusCode: number,
  type: string,
  message: string
) {
  // code is intentionally kept simple for demonstration purpose
  return this.contentType(type).status(statusCode).send(message);
} as Response['sendStatus'];
```

The above implementation completely changes the original signature of `res.sendStatus`. It now accepts a status code, encoding type, and the message to be sent to the client.

In TypeScript, augmenting `express-serve-static-core` adds the new overload to the `Response` type so call sites such as `res.sendStatus(404, 'application/json', body)` type-check. The assignment is cast with `as Response['sendStatus']` because replacing a method with a different signature cannot be checked against the original declaration.

The overridden method may now be used this way:

```
res.sendStatus(404, 'application/json', '{"error":"resource not found"}');
```

```
Object.defineProperty(app.request, 'ip', {
  configurable: true,
  enumerable: true,
  get() {
    return this.get('Client-IP');
  },
});
```

```
import { type Request } from 'express';


Object.defineProperty(app.request, 'ip', {
  configurable: true,
  enumerable: true,
  get(this: Request) {
    return this.get('Client-IP');
  },
});
```

## [Extending the API in TypeScript](#extending-the-api-in-typescript)

The sections above override members that Express already provides. To add your own properties or methods to the request or response, describe them to TypeScript with [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) on the `Express` namespace. Put the augmentation in a `.d.ts` file that is part of your project. No `tsconfig.json` change is needed unless a custom `include` does not cover its location.

For example, an authentication middleware may attach a `user` to the request, and you might add a `sendError` helper to the response:

types/express.d.ts

```
interface User {
  id: string;
  name: string;
}


declare global {
  namespace Express {
    interface Request {
      user?: User;
    }
    interface Response {
      sendError(status: number, message: string): this;
    }
  }
}


export {};
```

The additions are now known throughout the application:

```
import { type Request, type Response, type NextFunction } from 'express';


app.use((req: Request, res: Response, next: NextFunction) => {
  req.user = { id: '1', name: 'Tobi' };
  next();
});


app.response.sendError = function (this: Response, status: number, message: string) {
  return this.status(status).json({ error: message });
};


app.get('/', (req: Request, res: Response) => {
  if (!req.user) {
    res.sendError(401, 'unauthorized');
    return;
  }
  res.send(req.user.name);
});
```

### Caution

Declare custom request properties as optional (`user?`). The type applies to every request, but TypeScript cannot know which middleware ran before a given handler, so a required property would be a false guarantee. Check for the value (as with `if (!req.user)` above) before relying on it.

Adding a new method needs no cast, unlike [overriding](#methods) an existing method with a different signature, because the method did not previously exist on the type.

## [Prototype](#prototype)

In order to provide the Express API, the request/response objects passed to Express (via `app(req, res)`, for example) need to inherit from the same prototype chain. By default, this is `http.IncomingRequest.prototype` for the request and `http.ServerResponse.prototype` for the response.

Unless necessary, it is recommended that this be done only at the application level, rather than globally. Also, take care that the prototype that is being used matches the functionality as closely as possible to the default prototypes.

```
// Use FakeRequest and FakeResponse in place of http.IncomingRequest and http.ServerResponse
// for the given app reference
Object.setPrototypeOf(Object.getPrototypeOf(app.request), FakeRequest.prototype);
Object.setPrototypeOf(Object.getPrototypeOf(app.response), FakeResponse.prototype);
```

----
url: https://expressjs.com/en/5x/starter/hello-world
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/starter/hello-world.mdx)

# [Hello world example](#overview)

### Note

Embedded below is essentially the simplest Express app you can create. It is a single file app — *not* what you’d get if you use the [Express generator](/en/5x/starter/generator/), which creates the scaffolding for a full app with numerous JavaScript files, Jade templates, and sub-directories for various purposes.

index.cjs

```
const express = require('express');
const app = express();
const port = 3000;


app.get('/', (req, res) => {
  res.send('Hello World!');
});


app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});
```

index.mjs

```
import express from 'express';


const app = express();
const port = 3000;


app.get('/', (req, res) => {
  res.send('Hello World!');
});


app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();
const port = 3000;


app.get('/', (req: Request, res: Response) => {
  res.send('Hello World!');
});


app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});
```

This app starts a server and listens on port 3000 for connections. The app responds with “Hello World!” for requests to the root URL (`/`) or *route*. For every other path, it will respond with a **404 Not Found**.

## [Running Locally](#running-locally)

First create a directory named `myapp`, change to it and run `npm init`. Then, install `express` as a dependency, as per the [installation guide](/en/5x/starter/installing/).

In the `myapp` directory, create a file named `app.js` and copy the code from the example above.

### Caution

The `req` (request) and `res` (response) are the exact same objects that Node provides, so you can invoke `req.pipe()`, `req.on('data', callback)`, and anything else you would do without Express involved.

Run the app with the following command:

Terminal window

```
$ node app.js
```

Then, load `http://localhost:3000/` in a browser to see the output.

----
url: https://expressjs.com/en/blog/2026-06-30-security-releases
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2026-06-30-security-releases)

security

# [June 2026 Security Releases](#overview)

Ulises GasconJune 30, 2026

[](https://x.com/intent/tweet?text=June%202026%20Security%20Releases\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-06-30-security-releases%2F)[](https://bsky.app/intent/compose?text=June%202026%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-06-30-security-releases%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-06-30-security-releases%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-06-30-security-releases%2F\&text=June%202026%20Security%20Releases)[](https://wa.me/?text=June%202026%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-06-30-security-releases%2F)[](/feed.xml)

The Express team has released [multer](https://www.npmjs.com/package/multer) 2.2.0 and [morgan](https://www.npmjs.com/package/morgan) 1.11.0, addressing three vulnerabilities across multipart parsing and access logging.

### Warning

We recommend upgrading to the latest versions of multer and morgan to secure your applications. If you have a `package-lock.json`, you can update the dependencies by running:

Terminal window

```
npm update multer morgan
```

The following vulnerabilities have been addressed:

* [CVE-2026-5079 in multer middleware (High)](#cve-2026-5079-in-multer-middleware-high)
* [CVE-2026-5078 in morgan middleware (Medium)](#cve-2026-5078-in-morgan-middleware-medium)
* [CVE-2026-5038 in multer middleware (Medium)](#cve-2026-5038-in-multer-middleware-medium)

## [CVE-2026-5079 in multer middleware (High)](#cve-2026-5079-in-multer-middleware-high)

**[multer](https://www.npmjs.com/package/multer) versions `>= 1.0.0, < 2.2.0` and `>= 3.0.0-alpha.1, < 3.0.0-alpha.2` are vulnerable to denial of service via deeply nested field names in multipart form data**

Multer uses the `append-field` dependency to parse bracket notation in field names such as `a[b][c]`. There is no limit on nesting depth, so an attacker can send a multipart form with field names that force allocation of deeply nested objects. With sufficient nesting, request handling consumes excessive memory and CPU, causing denial of service. The vulnerability affects all consumers that pass user-controlled multipart forms through multer’s parser.

**Affected versions**: `>= 1.0.0, < 2.2.0` and `>= 3.0.0-alpha.1, < 3.0.0-alpha.2`\
**Patched version**: `>= 2.2.0` (stable line) and `>= 3.0.0-alpha.2` (alpha line)

For more details, see [GHSA-72gw-mp4g-v24j](https://github.com/expressjs/multer/security/advisories/GHSA-72gw-mp4g-v24j).

## [CVE-2026-5078 in morgan middleware (Medium)](#cve-2026-5078-in-morgan-middleware-medium)

**[morgan](https://www.npmjs.com/package/morgan) versions `>= 1.2.0, <= 1.10.1` are vulnerable to log forging via unsanitized control characters in the `:remote-user` token**

Morgan’s `:remote-user` token writes the Basic auth username from the `Authorization` header to the log stream without neutralizing control characters. A crafted `Authorization: Basic` header containing CR/LF characters can inject forged log lines, corrupting the one-request-per-line structure of access logs. The built-in `combined`, `common`, `default`, and `short` formats are affected, as well as any custom format that includes `:remote-user`.

**Affected versions**: `>= 1.2.0, <= 1.10.1`\
**Patched version**: `>= 1.11.0`

For more details, see [GHSA-4vj7-5mj6-jm8m](https://github.com/expressjs/morgan/security/advisories/GHSA-4vj7-5mj6-jm8m).

## [CVE-2026-5038 in multer middleware (Medium)](#cve-2026-5038-in-multer-middleware-medium)

**[multer](https://www.npmjs.com/package/multer) versions `>= 2.0.0-alpha.1, < 2.2.0` and `>= 3.0.0-alpha.1, < 3.0.0-alpha.2` are vulnerable to denial of service via incomplete cleanup of aborted uploads**

When multer’s `diskStorage` engine is used, aborted or malformed multipart uploads leave orphaned partial files on disk. The cleanup path does not run on every error condition, so an attacker can fill the upload directory by repeatedly opening and dropping connections mid-upload. Over time this exhausts disk space, causing denial of service on the host.

**Affected versions**: `>= 2.0.0-alpha.1, < 2.2.0` and `>= 3.0.0-alpha.1, < 3.0.0-alpha.2`\
**Patched version**: `>= 2.2.0` (stable line) and `>= 3.0.0-alpha.2` (alpha line)

For more details, see [GHSA-3p4h-7m6x-2hcm](https://github.com/expressjs/multer/security/advisories/GHSA-3p4h-7m6x-2hcm).

***

We recommend upgrading to the latest versions of multer and morgan to secure your applications.

----
url: https://expressjs.com/en/blog
----

# Blog

Stay tuned for details on new releases, enhancements, and everything you need to know to make the most of your Express applications. Let's dive into what's new!

[Security](/en/blog/2026-09-30-security-releases)

## [September 2026 Security Releases](/en/blog/2026-09-30-security-releases)

[Ulises GasconSep 30, 2026](/en/blog/2026-09-30-security-releases)

[Security](/en/blog/2026-09-09-joining-the-openjs-cna-security-break)

## [Express is joining the OpenJS CNA coordinated break](/en/blog/2026-09-09-joining-the-openjs-cna-security-break)

[Express Security TeamSep 9, 2026](/en/blog/2026-09-09-joining-the-openjs-cna-security-break)

[Security](/en/blog/2026-08-31-security-releases)

## [August 2026 Security Releases](/en/blog/2026-08-31-security-releases)

[Ulises GasconAug 31, 2026](/en/blog/2026-08-31-security-releases)

[Security](/en/blog/2026-07-31-security-releases)

## [July 2026 Security Releases](/en/blog/2026-07-31-security-releases)

[Ulises GasconJul 31, 2026](/en/blog/2026-07-31-security-releases)

[Security](/en/blog/2026-06-30-security-releases)

## [June 2026 Security Releases](/en/blog/2026-06-30-security-releases)

[Ulises GasconJun 30, 2026](/en/blog/2026-06-30-security-releases)

[Security](/en/blog/2026-05-31-security-releases)

## [May 2026 Security Releases](/en/blog/2026-05-31-security-releases)

[Ulises GasconMay 31, 2026](/en/blog/2026-05-31-security-releases)

----
url: https://expressjs.com/en/resources/middleware/cors
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/cors.mdx)

# [cors middleware](#overview)

v2.8.6[GitHub](https://github.com/expressjs/cors)[Changelog](https://github.com/expressjs/cors/releases)[npm](https://www.npmjs.com/package/cors)

CORS is a [Node.js](https://nodejs.org/en/) middleware for [Express](/)/[Connect](https://github.com/senchalabs/connect) that sets [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS) response headers. These headers tell browsers which origins can read responses from your server.

### Note

**How CORS Works:** This package sets response headers—it doesn’t block requests. CORS is enforced by browsers: they check the headers and decide if JavaScript can read the response. Non-browser clients (curl, Postman, other servers) ignore CORS entirely. See the [MDN CORS guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS) for details.

* [Installation](#installation)

* [Usage](#usage)

  * [Simple Usage](#simple-usage-enable-all-cors-requests)
  * [Enable CORS for a Single Route](#enable-cors-for-a-single-route)
  * [Configuring CORS](#configuring-cors)
  * [Configuring CORS w/ Dynamic Origin](#configuring-cors-w-dynamic-origin)
  * [Enabling CORS Pre-Flight](#enabling-cors-pre-flight)
  * [Customizing CORS Settings Dynamically per Request](#customizing-cors-settings-dynamically-per-request)

* [Configuration Options](#configuration-options)

* [Common Misconceptions](#common-misconceptions)

* [License](#license)

* [Original Author](#original-author)

## [Installation](#installation)

This is a [Node.js](https://nodejs.org/en/) module available through the [npm registry](https://www.npmjs.com/). Installation is done using the [`npm install` command](https://docs.npmjs.com/downloading-and-installing-packages-locally):

Terminal window

```
npm install cors
```

Terminal window

```
yarn add cors
```

Terminal window

```
pnpm add cors
```

Terminal window

```
bun add cors
```

### Note

`cors` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/cors
```

Terminal window

```
yarn add --dev @types/cors
```

Terminal window

```
pnpm add --save-dev @types/cors
```

Terminal window

```
bun add --dev @types/cors
```

## [Usage](#usage)

### [Simple Usage (Enable *All* CORS Requests)](#simple-usage-enable-all-cors-requests)

```
var express = require('express');
var cors = require('cors');
var app = express();


// Adds headers: Access-Control-Allow-Origin: *
app.use(cors());


app.get('/products/:id', function (req, res, next) {
  res.json({ msg: 'Hello' });
});


app.listen(80, function () {
  console.log('web server listening on port 80');
});
```

### [Enable CORS for a Single Route](#enable-cors-for-a-single-route)

```
var express = require('express');
var cors = require('cors');
var app = express();


// Adds headers: Access-Control-Allow-Origin: *
app.get('/products/:id', cors(), function (req, res, next) {
  res.json({ msg: 'Hello' });
});


app.listen(80, function () {
  console.log('web server listening on port 80');
});
```

### [Configuring CORS](#configuring-cors)

See the [configuration options](#configuration-options) for details.

```
var express = require('express');
var cors = require('cors');
var app = express();


var corsOptions = {
  origin: 'http://example.com',
  optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
};


// Adds headers: Access-Control-Allow-Origin: http://example.com, Vary: Origin
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
  res.json({ msg: 'Hello' });
});


app.listen(80, function () {
  console.log('web server listening on port 80');
});
```

### [Configuring CORS w/ Dynamic Origin](#configuring-cors-w-dynamic-origin)

This module supports validating the origin dynamically using a function provided to the `origin` option. This function will be passed a string that is the origin (or `undefined` if the request has no origin), and a `callback` with the signature `callback(error, origin)`.

The `origin` argument to the callback can be any value allowed for the `origin` option of the middleware, except a function. See the [configuration options](#configuration-options) section for more information on all the possible value types.

This function is designed to allow the dynamic loading of allowed origin(s) from a backing datasource, like a database.

```
var express = require('express');
var cors = require('cors');
var app = express();


var corsOptions = {
  origin: function (origin, callback) {
    // db.loadOrigins is an example call to load
    // a list of origins from a backing database
    db.loadOrigins(function (error, origins) {
      callback(error, origins);
    });
  },
};


// Adds headers: Access-Control-Allow-Origin: <matched origin>, Vary: Origin
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
  res.json({ msg: 'Hello' });
});


app.listen(80, function () {
  console.log('web server listening on port 80');
});
```

### [Enabling CORS Pre-Flight](#enabling-cors-pre-flight)

Certain CORS requests are considered ‘complex’ and require an initial `OPTIONS` request (called the “pre-flight request”). An example of a ‘complex’ CORS request is one that uses an HTTP verb other than GET/HEAD/POST (such as DELETE) or that uses custom headers. To enable pre-flighting, you must add a new OPTIONS handler for the route you want to support:

```
var express = require('express');
var cors = require('cors');
var app = express();


app.options('/products/:id', cors()); // preflight for DELETE
app.delete('/products/:id', cors(), function (req, res, next) {
  res.json({ msg: 'Hello' });
});


app.listen(80, function () {
  console.log('web server listening on port 80');
});
```

You can also enable pre-flight across-the-board like so:

```
app.options('*', cors()); // include before other routes
```

NOTE: When using this middleware as an application level middleware (for example, `app.use(cors())`), pre-flight requests are already handled for all routes.

### [Customizing CORS Settings Dynamically per Request](#customizing-cors-settings-dynamically-per-request)

For APIs that require different CORS configurations for specific routes or requests, you can dynamically generate CORS options based on the incoming request. The `cors` middleware allows you to achieve this by passing a function instead of static options. This function is called for each incoming request and must use the callback pattern to return the appropriate CORS options.

The function accepts:

1. **`req`**:

   * The incoming request object.

2. **`callback(error, corsOptions)`**:

   * A function used to return the computed CORS options.

   * **Arguments**:

     * **`error`**: Pass `null` if there’s no error, or an error object to indicate a failure.
     * **`corsOptions`**: An object specifying the CORS policy for the current request.

Here’s an example that handles both public routes and restricted, credential-sensitive routes:

```
var dynamicCorsOptions = function (req, callback) {
  var corsOptions;
  if (req.path.startsWith('/auth/connect/')) {
    // Access-Control-Allow-Origin: http://mydomain.com, Access-Control-Allow-Credentials: true, Vary: Origin
    corsOptions = {
      origin: 'http://mydomain.com',
      credentials: true,
    };
  } else {
    // Access-Control-Allow-Origin: *
    corsOptions = { origin: '*' };
  }
  callback(null, corsOptions);
};


app.use(cors(dynamicCorsOptions));


app.get('/auth/connect/twitter', function (req, res) {
  res.send('Hello');
});


app.get('/public', function (req, res) {
  res.send('Hello');
});


app.listen(80, function () {
  console.log('web server listening on port 80');
});
```

## [Configuration Options](#configuration-options)

* `origin`: Configures the **Access-Control-Allow-Origin** CORS header. Possible values:

  * `Boolean` - set `origin` to `true` to reflect the [request origin](https://datatracker.ietf.org/doc/html/draft-abarth-origin-09), as defined by `req.header('Origin')`, or set it to `false` to disable CORS.

  * `String` - set `origin` to a specific origin. For example, if you set it to

    * `"http://example.com"` only requests from “<http://example.com>” will be allowed.
    * `"*"` for all domains to be allowed.

  * `RegExp` - set `origin` to a regular expression pattern which will be used to test the request origin. If it’s a match, the request origin will be reflected. For example the pattern `/example\.com$/` will reflect any request that is coming from an origin ending with “example.com”.

  * `Array` - set `origin` to an array of valid origins. Each origin can be a `String` or a `RegExp`. For example `["http://example1.com", /\.example2\.com$/]` will accept any request from “<http://example1.com>” or from a subdomain of “example2.com”.

  * `Function` - set `origin` to a function implementing some custom logic. The function takes the request origin as the first parameter and a callback (called as `callback(err, origin)`, where `origin` is a non-function value of the `origin` option) as the second.

* `methods`: Configures the **Access-Control-Allow-Methods** CORS header. Expects a comma-delimited string (ex: ‘GET,PUT,POST’) or an array (ex: `['GET', 'PUT', 'POST']`).

* `allowedHeaders`: Configures the **Access-Control-Allow-Headers** CORS header. Expects a comma-delimited string (ex: ‘Content-Type,Authorization’) or an array (ex: `['Content-Type', 'Authorization']`). If not specified, defaults to reflecting the headers specified in the request’s **Access-Control-Request-Headers** header.

* `exposedHeaders`: Configures the **Access-Control-Expose-Headers** CORS header. Expects a comma-delimited string (ex: ‘Content-Range,X-Content-Range’) or an array (ex: `['Content-Range', 'X-Content-Range']`). If not specified, no custom headers are exposed.

* `credentials`: Configures the **Access-Control-Allow-Credentials** CORS header. Set to `true` to pass the header, otherwise it is omitted.

* `maxAge`: Configures the **Access-Control-Max-Age** CORS header. Set to an integer to pass the header, otherwise it is omitted.

* `preflightContinue`: Pass the CORS preflight response to the next handler.

* `optionsSuccessStatus`: Provides a status code to use for successful `OPTIONS` requests, since some legacy browsers (IE11, various SmartTVs) choke on `204`.

The default configuration is the equivalent of:

```
{
  "origin": "*",
  "methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
  "preflightContinue": false,
  "optionsSuccessStatus": 204
}
```

## [Common Misconceptions](#common-misconceptions)

### [”CORS blocks requests from disallowed origins”](#cors-blocks-requests-from-disallowed-origins)

**No.** Your server receives and processes every request. CORS headers tell the browser whether JavaScript can read the response—not whether the request is allowed.

### [”CORS protects my API from unauthorized access”](#cors-protects-my-api-from-unauthorized-access)

**No.** CORS is not access control. Any HTTP client (curl, Postman, another server) can call your API regardless of CORS settings. Use authentication and authorization to protect your API.

### [”Setting `origin: 'http://example.com'` means only that domain can access my server”](#setting-origin-httpexamplecom-means-only-that-domain-can-access-my-server)

**No.** It means browsers will only let JavaScript from that origin read responses. The server still responds to all requests.

## [License](#license)

[MIT License](http://www.opensource.org/licenses/mit-license.php)

## [Original Author](#original-author)

[Troy Goode](https://github.com/TroyGoode) (<troygoode@gmail.com>)

----
url: https://expressjs.com/en/4x/guide/routing
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/guide/routing.mdx)

# [Routing](#overview)

*Routing* refers to how an application’s endpoints (URIs) respond to client requests. For an introduction to routing, see [Basic routing](/en/4x/starter/basic-routing/).

You define routing using methods of the Express `app` object that correspond to HTTP methods; for example, `app.get()` to handle GET requests and `app.post` to handle POST requests. For a full list, see [app.METHOD](/en/4x/api/application/#appmethod). You can also use [app.all()](/en/4x/api/application/#appall) to handle all HTTP methods and [app.use()](/en/4x/api/application/#appuse) to specify middleware as the callback function (See [Using middleware](/en/4x/guide/using-middleware/) for details).

These routing methods specify a callback function (sometimes called a “handler function”) that Express automatically runs when the application receives a request matching the specified route (endpoint) and HTTP method. In other words, the application “listens” for requests that match the specified route(s) and method(s), and when it detects a match, it calls the specified callback function.

In fact, the routing methods can have more than one callback function as arguments. With multiple callback functions, it is important to provide `next` as an argument to the callback function and then call `next()` within the body of the function to hand off control to the next callback.

The following code is an example of a very basic route.

index.cjs

```
const express = require('express');
const app = express();


// respond with "hello world" when a GET request is made to the homepage
app.get('/', (req, res) => {
  res.send('hello world');
});
```

index.mjs

```
import express from 'express';


const app = express();


// respond with "hello world" when a GET request is made to the homepage
app.get('/', (req, res) => {
  res.send('hello world');
});
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


// respond with "hello world" when a GET request is made to the homepage
app.get('/', (req: Request, res: Response) => {
  res.send('hello world');
});
```

## [Route methods](#route-methods)

A route method is derived from one of the HTTP methods, and is attached to an instance of the `express` class.

The following code is an example of routes that are defined for the `GET` and the `POST` methods to the root of the app.

```
// GET method route
app.get('/', (req, res) => {
  res.send('GET request to the homepage');
});


// POST method route
app.post('/', (req, res) => {
  res.send('POST request to the homepage');
});
```

```
import { type Request, type Response } from 'express';


// GET method route
app.get('/', (req: Request, res: Response) => {
  res.send('GET request to the homepage');
});


// POST method route
app.post('/', (req: Request, res: Response) => {
  res.send('POST request to the homepage');
});
```

Express supports methods that correspond to all HTTP request methods: `get`, `post`, and so on. For a full list, see [app.METHOD](/en/4x/api/application/#appmethod).

There is a special routing method, `app.all()`, used to load middleware functions at a path for *all* HTTP request methods. For example, the following handler is executed for requests to the route `"/secret"` whether using `GET`, `QUERY`, `POST`, `PUT`, `DELETE`, or any other HTTP request method supported in the [http module](https://nodejs.org/api/http.html#httpmethods).

```
app.all('/secret', (req, res, next) => {
  console.log('Accessing the secret section ...');
  next(); // pass control to the next handler
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.all('/secret', (req: Request, res: Response, next: NextFunction) => {
  console.log('Accessing the secret section ...');
  next(); // pass control to the next handler
});
```

## [Route paths](#route-paths)

Route paths, in combination with a request method, define the endpoints at which requests can be made. Route paths can be strings, string patterns, or regular expressions. They can also capture values from the URL, as described in [Route parameters](#route-parameters) below.

### Note

Express uses [path-to-regexp](https://www.npmjs.com/package/path-to-regexp) for matching the route paths; see the path-to-regexp documentation for all the possibilities in defining route paths. [Express Playground Router](https://bjohansebas.github.io/playground-router/) is a handy tool for testing basic Express routes, although it does not support pattern matching.

### [Route paths based on strings](#route-paths-based-on-strings)

### Warning

Query strings are not part of the route path.

This route path will match requests to the root route, `/`.

```
app.get('/', (req, res) => {
  res.send('root');
});
```

```
import { type Request, type Response } from 'express';


app.get('/', (req: Request, res: Response) => {
  res.send('root');
});
```

This route path will match requests to `/about`.

```
app.get('/about', (req, res) => {
  res.send('about');
});
```

```
import { type Request, type Response } from 'express';


app.get('/about', (req: Request, res: Response) => {
  res.send('about');
});
```

This route path will match requests to `/random.text`.

```
app.get('/random.text', (req, res) => {
  res.send('random.text');
});
```

```
import { type Request, type Response } from 'express';


app.get('/random.text', (req: Request, res: Response) => {
  res.send('random.text');
});
```

### [Route paths based on string patterns](#route-paths-based-on-string-patterns)

This route path will match `acd` and `abcd`.

```
app.get('/ab?cd', (req, res) => {
  res.send('ab?cd');
});
```

```
import { type Request, type Response } from 'express';


app.get('/ab?cd', (req: Request, res: Response) => {
  res.send('ab?cd');
});
```

This route path will match `abcd`, `abbcd`, `abbbcd`, and so on.

```
app.get('/ab+cd', (req, res) => {
  res.send('ab+cd');
});
```

```
import { type Request, type Response } from 'express';


app.get('/ab+cd', (req: Request, res: Response) => {
  res.send('ab+cd');
});
```

This route path will match `abcd`, `abxcd`, `abRANDOMcd`, `ab123cd`, and so on.

```
app.get('/ab*cd', (req, res) => {
  res.send('ab*cd');
});
```

```
import { type Request, type Response } from 'express';


app.get('/ab*cd', (req: Request, res: Response) => {
  res.send('ab*cd');
});
```

This route path will match `/abe` and `/abcde`.

```
app.get('/ab(cd)?e', (req, res) => {
  res.send('ab(cd)?e');
});
```

```
import { type Request, type Response } from 'express';


app.get('/ab(cd)?e', (req: Request, res: Response) => {
  res.send('ab(cd)?e');
});
```

A wildcard (`*`) on its own matches anything at its position, including entire subpaths. For example, this route path will match `/file/style.css` as well as `/file/javascripts/jquery.js`. Wildcards are unnamed, so the matched value is available as `req.params[0]` instead of a named parameter.

```
app.get('/file/*', (req, res) => {
  // GET /file/javascripts/jquery.js
  res.send(req.params[0]);
  // => 'javascripts/jquery.js'
});
```

```
import { type Request, type Response } from 'express';


app.get('/file/*', (req: Request, res: Response) => {
  // GET /file/javascripts/jquery.js
  res.send(req.params[0]);
  // => 'javascripts/jquery.js'
});
```

### [Route paths based on regular expressions](#route-paths-based-on-regular-expressions)

### Caution

Regular expression characters such as `$` need to be escaped with a `\`.

This route path will match anything with an “a” in it.

```
app.get(/a/, (req, res) => {
  res.send('/a/');
});
```

```
import { type Request, type Response } from 'express';


app.get(/a/, (req: Request, res: Response) => {
  res.send('/a/');
});
```

This route path will match `butterfly` and `dragonfly`, but not `butterflyman`, `dragonflyman`, and so on.

```
app.get(/.*fly$/, (req, res) => {
  res.send('/.*fly$/');
});
```

```
import { type Request, type Response } from 'express';


app.get(/.*fly$/, (req: Request, res: Response) => {
  res.send('/.*fly$/');
});
```

## [Route parameters](#route-parameters)

Route parameters are named URL segments that are used to capture the values specified at their position in the URL. The captured values are populated in the `req.params` object, with the name of the route parameter specified in the path as their respective keys.

```
Route path: /users/:userId/books/:bookId
Request URL: http://localhost:3000/users/34/books/8989
req.params: { "userId": "34", "bookId": "8989" }
```

To define routes with route parameters, simply specify the route parameters in the path of the route as shown below.

```
app.get('/users/:userId/books/:bookId', (req, res) => {
  res.send(req.params);
});
```

In TypeScript, `@types/express` infers the parameters from the route path, so in the handler above `req.params.userId` and `req.params.bookId` are already typed as `string` with no extra annotation. Reading a name that is not in the route (such as `req.params.other`) is a type error. You only need to annotate the parameters when the handler is defined separately from the route, because the type checker can no longer see the path. In that case, pass them as the first type argument of `Request`:

```
import { type Request, type Response } from 'express';


const sendParams = (req: Request<{ userId: string; bookId: string }>, res: Response) => {
  res.send(req.params);
};


app.get('/users/:userId/books/:bookId', sendParams);
```

### Caution

The name of route parameters must be made up of “word characters” (\[A-Za-z0-9\_]).

Since the hyphen (`-`) and the dot (`.`) are interpreted literally, they can be used along with route parameters for useful purposes.

```
Route path: /flights/:from-:to
Request URL: http://localhost:3000/flights/LAX-SFO
req.params: { "from": "LAX", "to": "SFO" }
```

```
Route path: /plantae/:genus.:species
Request URL: http://localhost:3000/plantae/Prunus.persica
req.params: { "genus": "Prunus", "species": "persica" }
```

To have more control over the exact string that can be matched by a route parameter, you can append a regular expression in parentheses (`()`):

```
Route path: /user/:userId(\d+)
Request URL: http://localhost:3000/user/42
req.params: {"userId": "42"}
```

### Warning

Because the regular expression is usually part of a literal string, be sure to escape any `\` characters with an additional backslash, for example `\\d+`.

### Warning

The [`*`](https://github.com/expressjs/express/issues/2495) character in regular expressions is not interpreted in the usual way. As a workaround, use `{0,}` instead of `*`.

Unlike named route parameters, wildcard (`*`) matches in [string patterns](#route-paths-based-on-string-patterns) and capture groups in regular expressions are unnamed: their values are available by position, as `req.params[0]`, `req.params[1]`, and so on.

```
Route path: /file/*/size/*
Request URL: http://localhost:3000/file/javascripts/jquery.js/size/large
req.params: { "0": "javascripts/jquery.js", "1": "large" }
```

## [Route handlers](#route-handlers)

You can provide multiple callback functions that behave like [middleware](/en/4x/guide/using-middleware/) to handle a request. The only exception is that these callbacks might invoke `next('route')` to bypass the remaining route callbacks. You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there’s no reason to proceed with the current route.

```
app.get('/user/:id', (req, res, next) => {
  if (req.params.id === '0') {
    return next('route');
  }
  res.send(`User ${req.params.id}`);
});


app.get('/user/:id', (req, res) => {
  res.send('Special handler for user ID 0');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get('/user/:id', (req: Request, res: Response, next: NextFunction) => {
  if (req.params.id === '0') {
    return next('route');
  }
  res.send(`User ${req.params.id}`);
});


app.get('/user/:id', (req: Request, res: Response) => {
  res.send('Special handler for user ID 0');
});
```

In this example:

* `GET /user/5` → handled by first route → sends “User 5”
* `GET /user/0` → first route calls `next('route')`, skipping to the next matching `/user/:id` route

Route handlers can be in the form of a function, an array of functions, or combinations of both, as shown in the following examples.

A single callback function can handle a route. For example:

```
app.get('/example/a', (req, res) => {
  res.send('Hello from A!');
});
```

```
import { type Request, type Response } from 'express';


app.get('/example/a', (req: Request, res: Response) => {
  res.send('Hello from A!');
});
```

More than one callback function can handle a route (make sure you specify the `next` object). For example:

```
app.get(
  '/example/b',
  (req, res, next) => {
    console.log('the response will be sent by the next function ...');
    next();
  },
  (req, res) => {
    res.send('Hello from B!');
  }
);
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get(
  '/example/b',
  (req: Request, res: Response, next: NextFunction) => {
    console.log('the response will be sent by the next function ...');
    next();
  },
  (req: Request, res: Response) => {
    res.send('Hello from B!');
  }
);
```

An array of callback functions can handle a route. For example:

```
const cb0 = function (req, res, next) {
  console.log('CB0');
  next();
};


const cb1 = function (req, res, next) {
  console.log('CB1');
  next();
};


const cb2 = function (req, res) {
  res.send('Hello from C!');
};


app.get('/example/c', [cb0, cb1, cb2]);
```

```
import { type Request, type Response, type NextFunction } from 'express';


const cb0 = function (req: Request, res: Response, next: NextFunction) {
  console.log('CB0');
  next();
};


const cb1 = function (req: Request, res: Response, next: NextFunction) {
  console.log('CB1');
  next();
};


const cb2 = function (req: Request, res: Response) {
  res.send('Hello from C!');
};


app.get('/example/c', [cb0, cb1, cb2]);
```

A combination of independent functions and arrays of functions can handle a route. For example:

```
const cb0 = function (req, res, next) {
  console.log('CB0');
  next();
};


const cb1 = function (req, res, next) {
  console.log('CB1');
  next();
};


app.get(
  '/example/d',
  [cb0, cb1],
  (req, res, next) => {
    console.log('the response will be sent by the next function ...');
    next();
  },
  (req, res) => {
    res.send('Hello from D!');
  }
);
```

```
import { type Request, type Response, type NextFunction } from 'express';


const cb0 = function (req: Request, res: Response, next: NextFunction) {
  console.log('CB0');
  next();
};


const cb1 = function (req: Request, res: Response, next: NextFunction) {
  console.log('CB1');
  next();
};


app.get(
  '/example/d',
  [cb0, cb1],
  (req: Request, res: Response, next: NextFunction) => {
    console.log('the response will be sent by the next function ...');
    next();
  },
  (req: Request, res: Response) => {
    res.send('Hello from D!');
  }
);
```

## [Response methods](#response-methods)

The methods on the [response object](/en/4x/api/response/) (`res`) in the following table can send a response to the client, and terminate the request-response cycle. If none of these methods are called from a route handler, the client request will be left hanging.

| Method                                                 | Description                                                                           |
| ------------------------------------------------------ | ------------------------------------------------------------------------------------- |
| [res.download()](/en/4x/api/response/#resdownload)     | Prompt a file to be downloaded.                                                       |
| [res.end()](/en/4x/api/response/#resend)               | End the response process.                                                             |
| [res.json()](/en/4x/api/response/#resjson)             | Send a JSON response.                                                                 |
| [res.jsonp()](/en/4x/api/response/#resjsonp)           | Send a JSON response with JSONP support.                                              |
| [res.redirect()](/en/4x/api/response/#resredirect)     | Redirect a request.                                                                   |
| [res.render()](/en/4x/api/response/#resrender)         | Render a view template.                                                               |
| [res.send()](/en/4x/api/response/#ressend)             | Send a response of various types.                                                     |
| [res.sendFile()](/en/4x/api/response/#ressendfile)     | Send a file as an octet stream.                                                       |
| [res.sendStatus()](/en/4x/api/response/#ressendstatus) | Set the response status code and send its string representation as the response body. |

## [app.route()](#approute)

You can create chainable route handlers for a route path by using `app.route()`. Because the path is specified in a single location, this helps to create modular routes and reduces redundancy and typos. For more information about routes, see the [Router() documentation](/en/4x/api/router/).

Here is an example of chained route handlers that are defined by using `app.route()`.

```
app
  .route('/book')
  .get((req, res) => {
    res.send('Get a random book');
  })
  .post((req, res) => {
    res.send('Add a book');
  })
  .put((req, res) => {
    res.send('Update the book');
  });
```

```
import { type Request, type Response } from 'express';


app
  .route('/book')
  .get((req: Request, res: Response) => {
    res.send('Get a random book');
  })
  .post((req: Request, res: Response) => {
    res.send('Add a book');
  })
  .put((req: Request, res: Response) => {
    res.send('Update the book');
  });
```

## [express.Router](#expressrouter)

Use the `express.Router` class to create modular, mountable route handlers. A `Router` instance is a complete middleware and routing system; for this reason, it is often referred to as a “mini-app”.

The following example creates a router as a module, loads a middleware function in it, defines some routes, and mounts the router module on a path in the main app.

Create a router file named `birds.js` in the app directory, with the following content:

birds.cjs

```
const express = require('express');
const router = express.Router();


// middleware that is specific to this router
const timeLog = (req, res, next) => {
  console.log('Time: ', Date.now());
  next();
};
router.use(timeLog);


// define the home page route
router.get('/', (req, res) => {
  res.send('Birds home page');
});
// define the about route
router.get('/about', (req, res) => {
  res.send('About birds');
});


module.exports = router;
```

birds.mjs

```
import express from 'express';


const router = express.Router();


// middleware that is specific to this router
const timeLog = (req, res, next) => {
  console.log('Time: ', Date.now());
  next();
};
router.use(timeLog);


// define the home page route
router.get('/', (req, res) => {
  res.send('Birds home page');
});
// define the about route
router.get('/about', (req, res) => {
  res.send('About birds');
});


export default router;
```

birds.ts

```
import express, { type Request, type Response, type NextFunction } from 'express';


const router = express.Router();


// middleware that is specific to this router
const timeLog = (req: Request, res: Response, next: NextFunction) => {
  console.log('Time: ', Date.now());
  next();
};
router.use(timeLog);


// define the home page route
router.get('/', (req: Request, res: Response) => {
  res.send('Birds home page');
});
// define the about route
router.get('/about', (req: Request, res: Response) => {
  res.send('About birds');
});


export default router;
```

Then, load the router module in the app:

index.cjs

```
const birds = require('./birds');


// ...


app.use('/birds', birds);
```

index.mjs

```
import birds from './birds';


// ...


app.use('/birds', birds);
```

The app will now be able to handle requests to `/birds` and `/birds/about`, as well as call the `timeLog` middleware function that is specific to the route.

But if the parent route `/birds` has path parameters, it will not be accessible by default from the sub-routes. To make it accessible, you will need to pass the `mergeParams` option to the [Router constructor](/en/4x/api/express/#expressrouter).

```
const router = express.Router({ mergeParams: true });
```

----
url: https://expressjs.com/en/4x/guide/behind-proxies
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/guide/behind-proxies.mdx)

# [Express behind proxies](#overview)

When running an Express app behind a reverse proxy, some of the Express APIs may return different values than expected. In order to adjust for this, the `trust proxy` application setting may be used to expose information provided by the reverse proxy in the Express APIs. The most common issue is express APIs that expose the client’s IP address may instead show an internal IP address of the reverse proxy.

### Note

When configuring the `trust proxy` setting, it is important to understand the exact setup of the reverse proxy. Since this setting will trust values provided in the request, it is important that the combination of the setting in Express matches how the reverse proxy operates.

The application setting `trust proxy` may be set to one of the values listed in the following table.

| Type         | Value                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Boolean      | If `true`, the client’s IP address is understood as the left-most entry in the `X-Forwarded-For` header.If `false`, the app is understood as directly facing the client and the client’s IP address is derived from `req.socket.remoteAddress`. This is the default setting.### WarningWhen setting to `true`, it is important to ensure that the last reverse proxy trusted is removing/overwriting all of the following HTTP headers: `X-Forwarded-For`, `X-Forwarded-Host`, and `X-Forwarded-Proto`, otherwise it may be possible for the client to provide any value.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| IP addresses | An IP address, subnet, or an array of IP addresses and subnets to trust as being a reverse proxy. The following list shows the pre-configured subnet names:- loopback - `127.0.0.1/8`, `::1/128`
- linklocal - `169.254.0.0/16`, `fe80::/10`
- uniquelocal - `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `fc00::/7`You can set IP addresses in any of the following ways:```
app.set('trust proxy', 'loopback'); // specify a single subnet
app.set('trust proxy', 'loopback, 123.123.123.123'); // specify a subnet and an address
app.set('trust proxy', 'loopback, linklocal, uniquelocal'); // specify multiple subnets as CSV
app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']); // specify multiple subnets as an array
```When specified, the IP addresses or the subnets are excluded from the address determination process, and the untrusted IP address nearest to the application server is determined as the client’s IP address. This works by checking if `req.socket.remoteAddress` is trusted. If so, then each address in `X-Forwarded-For` is checked from right to left until the first non-trusted address. |
| Number       | Use the address that is at most `n` number of hops away from the Express application. `req.socket.remoteAddress` is the first hop, and the rest are looked for in the `X-Forwarded-For` header from right to left. A value of `0` means that the first untrusted address would be `req.socket.remoteAddress`, i.e. there is no reverse proxy.### WarningWhen using this setting, it is important to ensure there are not multiple, different-length paths to the Express application such that the client can be less than the configured number of hops away, otherwise it may be possible for the client to provide any value.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| Function     | Custom trust implementation.```
app.set('trust proxy', (ip) => {
  if (ip === '127.0.0.1' || ip === '123.123.123.123')
    return true; // trusted IPs
  else return false;
});
``````
app.set('trust proxy', (ip: string) => {
  if (ip === '127.0.0.1' || ip === '123.123.123.123')
    return true; // trusted IPs
  else return false;
});
```                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |

Enabling `trust proxy` will have the following impact:

* The value of [req.hostname](/en/4x/api/request/#reqhostname) is derived from the value set in the `X-Forwarded-Host` header, which can be set by the client or by the proxy.

* `X-Forwarded-Proto` can be set by the reverse proxy to tell the app whether it is `https` or `http` or even an invalid name. This value is reflected by [req.protocol](/en/4x/api/request/#reqprotocol).

* The [req.ip](/en/4x/api/request/#reqip) and [req.ips](/en/4x/api/request/#reqips) values are populated based on the socket address and `X-Forwarded-For` header, starting at the first untrusted address.

The `trust proxy` setting is implemented using the [proxy-addr](https://www.npmjs.com/package/proxy-addr) package. For more information, see its documentation.

----
url: https://expressjs.com/en/resources/middleware/session
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/session.mdx)

# [session middleware](#overview)

v1.19.0[GitHub](https://github.com/expressjs/session)[Changelog](https://github.com/expressjs/session/releases)[npm](https://www.npmjs.com/package/express-session)

## [Installation](#installation)

This is a [Node.js](https://nodejs.org/en/) module available through the [npm registry](https://www.npmjs.com/). Installation is done using the [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):

Terminal window

```
npm install express-session
```

Terminal window

```
yarn add express-session
```

Terminal window

```
pnpm add express-session
```

Terminal window

```
bun add express-session
```

### Note

`express-session` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/express-session
```

Terminal window

```
yarn add --dev @types/express-session
```

Terminal window

```
pnpm add --save-dev @types/express-session
```

Terminal window

```
bun add --dev @types/express-session
```

## [API](#api)

```
var session = require('express-session');
```

### [session(options)](#sessionoptions)

Create a session middleware with the given `options`.

**Note** Session data is *not* saved in the cookie itself, just the session ID. Session data is stored server-side.

**Note** Since version 1.5.0, the [`cookie-parser` middleware](https://www.npmjs.com/package/cookie-parser) no longer needs to be used for this module to work. This module now directly reads and writes cookies on `req`/`res`. Using `cookie-parser` may result in issues if the `secret` is not the same between this module and `cookie-parser`.

**Warning** The default server-side session storage, `MemoryStore`, is *purposely* not designed for a production environment. It will leak memory under most conditions, does not scale past a single process, and is meant for debugging and developing.

For a list of stores, see [compatible session stores](#compatible-session-stores).

#### [Options](#options)

`express-session` accepts these properties in the options object.

##### [cookie](#cookie)

Settings object for the session ID cookie. The default value is `{ path: '/', httpOnly: true, secure: false, maxAge: null }`.

In addition to providing a static object, you can also pass a callback function to dynamically generate the cookie options for each request. The callback receives the `req` object as its argument and should return an object containing the cookie settings.

```
var app = express();
app.use(
  session({
    secret: 'keyboard cat',
    resave: false,
    saveUninitialized: true,
    cookie: function (req) {
      var match = req.url.match(/^\/([^/]+)/);
      return {
        path: match ? '/' + match[1] : '/',
        httpOnly: true,
        secure: req.secure || false,
        maxAge: 60000,
      };
    },
  })
);
```

The following are options that can be set in this object.

##### [cookie.domain](#cookiedomain)

Specifies the value for the `Domain` `Set-Cookie` attribute. By default, no domain is set, and most clients will consider the cookie to apply to only the current domain.

##### [cookie.expires](#cookieexpires)

Specifies the `Date` object to be the value for the `Expires` `Set-Cookie` attribute. By default, no expiration is set, and most clients will consider this a “non-persistent cookie” and will delete it on a condition like exiting a web browser application.

**Note** If both `expires` and `maxAge` are set in the options, then the last one defined in the object is what is used.

**Note** The `expires` option should not be set directly; instead only use the `maxAge` option.

##### [cookie.httpOnly](#cookiehttponly)

Specifies the `boolean` value for the `HttpOnly` `Set-Cookie` attribute. When truthy, the `HttpOnly` attribute is set, otherwise it is not. By default, the `HttpOnly` attribute is set.

**Note** be careful when setting this to `true`, as compliant clients will not allow client-side JavaScript to see the cookie in `document.cookie`.

##### [cookie.maxAge](#cookiemaxage)

Specifies the `number` (in milliseconds) to use when calculating the `Expires` `Set-Cookie` attribute. This is done by taking the current server time and adding `maxAge` milliseconds to the value to calculate an `Expires` datetime. By default, no maximum age is set.

**Note** If both `expires` and `maxAge` are set in the options, then the last one defined in the object is what is used.

##### [cookie.partitioned](#cookiepartitioned)

Specifies the `boolean` value for the [`Partitioned` `Set-Cookie`](https://tools.ietf.org/html/draft-cutler-httpbis-partitioned-cookies/) attribute. When truthy, the `Partitioned` attribute is set, otherwise it is not. By default, the `Partitioned` attribute is not set.

**Note** This is an attribute that has not yet been fully standardized, and may change in the future. This also means many clients may ignore this attribute until they understand it.

More information about can be found in [the proposal](https://github.com/privacycg/CHIPS).

##### [cookie.path](#cookiepath)

Specifies the value for the `Path` `Set-Cookie`. By default, this is set to `'/'`, which is the root path of the domain.

Since 1.19.1, path matching follows [RFC 6265 section 5.1.4](https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4). This means the session middleware will only activate when the request path is an exact match or falls under a segment boundary of the cookie path. For example, a cookie path of `/admin` will match `/admin` and `/admin/users` but will **not** match `/administrator`. Prior versions used a simple prefix check that did not enforce segment boundaries.

##### [cookie.priority](#cookiepriority)

Specifies the `string` to be the value for the [`Priority` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1).

* `'low'` will set the `Priority` attribute to `Low`.
* `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set.
* `'high'` will set the `Priority` attribute to `High`.

More information about the different priority levels can be found in [the specification](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1).

**Note** This is an attribute that has not yet been fully standardized, and may change in the future. This also means many clients may ignore this attribute until they understand it.

##### [cookie.sameSite](#cookiesamesite)

Specifies the `boolean` or `string` to be the value for the `SameSite` `Set-Cookie` attribute. By default, this is `false`.

* `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
* `false` will not set the `SameSite` attribute.
* `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.
* `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.
* `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
* `'auto'` will set the `SameSite` attribute to `None` for secure connections and `Lax` for non-secure connections.

More information about the different enforcement levels can be found in [the specification](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7).

**Note** This is an attribute that has not yet been fully standardized, and may change in the future. This also means many clients may ignore this attribute until they understand it.

**Note** There is a [draft spec](https://tools.ietf.org/html/draft-west-cookie-incrementalism-01) that requires that the `Secure` attribute be set to `true` when the `SameSite` attribute has been set to `'none'`. Some web browsers or other clients may be adopting this specification.

The `cookie.sameSite` option can also be set to the special value `'auto'` to have this setting automatically match the determined security of the connection. When the connection is secure (HTTPS), the `SameSite` attribute will be set to `None` to enable cross-site usage. When the connection is not secure (HTTP), the `SameSite` attribute will be set to `Lax` for better security while maintaining functionality. This is useful when the Express `"trust proxy"` setting is properly setup to simplify development vs production configuration, particularly for SAML authentication scenarios.

##### [cookie.secure](#cookiesecure)

Specifies the `boolean` value for the `Secure` `Set-Cookie` attribute. When truthy, the `Secure` attribute is set, otherwise it is not. By default, the `Secure` attribute is not set.

**Note** be careful when setting this to `true`, as compliant clients will not send the cookie back to the server in the future if the browser does not have an HTTPS connection.

Please note that `secure: true` is a **recommended** option. However, it requires an https-enabled website, i.e., HTTPS is necessary for secure cookies. If `secure` is set, and you access your site over HTTP, the cookie will not be set. If you have your node.js behind a proxy and are using `secure: true`, you need to set “trust proxy” in express:

```
var app = express();
app.set('trust proxy', 1); // trust first proxy
app.use(
  session({
    secret: 'keyboard cat',
    resave: false,
    saveUninitialized: true,
    cookie: { secure: true },
  })
);
```

For using secure cookies in production, but allowing for testing in development, the following is an example of enabling this setup based on `NODE_ENV` in express:

```
var app = express();
var sess = {
  secret: 'keyboard cat',
  cookie: {},
};


if (app.get('env') === 'production') {
  app.set('trust proxy', 1); // trust first proxy
  sess.cookie.secure = true; // serve secure cookies
}


app.use(session(sess));
```

The `cookie.secure` option can also be set to the special value `'auto'` to have this setting automatically match the determined security of the connection. Be careful when using this setting if the site is available both as HTTP and HTTPS, as once the cookie is set on HTTPS, it will no longer be visible over HTTP. This is useful when the Express `"trust proxy"` setting is properly setup to simplify development vs production configuration.

##### [genid](#genid)

Function to call to generate a new session ID. Provide a function that returns a string that will be used as a session ID. The function is given `req` as the first argument if you want to use some value attached to `req` when generating the ID.

The default value is a function which uses the `uid-safe` library to generate IDs.

**NOTE** be careful to generate unique IDs so your sessions do not conflict.

```
app.use(
  session({
    genid: function (req) {
      return genuuid(); // use UUIDs for session IDs
    },
    secret: 'keyboard cat',
  })
);
```

##### [name](#name)

The name of the session ID cookie to set in the response (and read from in the request).

The default value is `'connect.sid'`.

**Note** if you have multiple apps running on the same hostname (this is just the name, i.e. `localhost` or `127.0.0.1`; different schemes and ports do not name a different hostname), then you need to separate the session cookies from each other. The simplest method is to simply set different `name`s per app.

##### [proxy](#proxy)

Trust the reverse proxy when setting secure cookies (via the “X-Forwarded-Proto” header).

The default value is `undefined`.

* `true` The “X-Forwarded-Proto” header will be used.
* `false` All headers are ignored and the connection is considered secure only if there is a direct TLS/SSL connection.
* `undefined` Uses the “trust proxy” setting from express

##### [resave](#resave)

Forces the session to be saved back to the session store, even if the session was never modified during the request. Depending on your store this may be necessary, but it can also create race conditions where a client makes two parallel requests to your server and changes made to the session in one request may get overwritten when the other request ends, even if it made no changes (this behavior also depends on what store you’re using).

The default value is `true`, but using the default has been deprecated, as the default will change in the future. Please research into this setting and choose what is appropriate to your use-case. Typically, you’ll want `false`.

How do I know if this is necessary for my store? The best way to know is to check with your store if it implements the `touch` method. If it does, then you can safely set `resave: false`. If it does not implement the `touch` method and your store sets an expiration date on stored sessions, then you likely need `resave: true`.

##### [rolling](#rolling)

Force the session identifier cookie to be set on every response. The expiration is reset to the original [`maxAge`](#cookiemaxage), resetting the expiration countdown.

The default value is `false`.

With this enabled, the session identifier cookie will expire in [`maxAge`](#cookiemaxage) since the last response was sent instead of in [`maxAge`](#cookiemaxage) since the session was last modified by the server.

This is typically used in conjunction with short, non-session-length [`maxAge`](#cookiemaxage) values to provide a quick timeout of the session data with reduced potential of it occurring during on going server interactions.

**Note** When this option is set to `true` but the `saveUninitialized` option is set to `false`, the cookie will not be set on a response with an uninitialized session. This option only modifies the behavior when an existing session was loaded for the request.

##### [saveUninitialized](#saveuninitialized)

Forces a session that is “uninitialized” to be saved to the store. A session is uninitialized when it is new but not modified. Choosing `false` is useful for implementing login sessions, reducing server storage usage, or complying with laws that require permission before setting a cookie. Choosing `false` will also help with race conditions where a client makes multiple parallel requests without a session.

The default value is `true`, but using the default has been deprecated, as the default will change in the future. Please research into this setting and choose what is appropriate to your use-case.

**Note** if you are using Session in conjunction with PassportJS, Passport will add an empty Passport object to the session for use after a user is authenticated, which will be treated as a modification to the session, causing it to be saved. *This has been fixed in PassportJS 0.3.0*

##### [secret](#secret)

**Required option**

This is the secret used to sign the session ID cookie. The secret can be any type of value that is supported by Node.js `crypto.createHmac` (like a string or a `Buffer`). This can be either a single secret, or an array of multiple secrets. If an array of secrets is provided, only the first element will be used to sign the session ID cookie, while all the elements will be considered when verifying the signature in requests. The secret itself should be not easily parsed by a human and would best be a random set of characters. A best practice may include:

* The use of environment variables to store the secret, ensuring the secret itself does not exist in your repository.
* Periodic updates of the secret, while ensuring the previous secret is in the array.

Using a secret that cannot be guessed will reduce the ability to hijack a session to only guessing the session ID (as determined by the `genid` option).

Changing the secret value will invalidate all existing sessions. In order to rotate the secret without invalidating sessions, provide an array of secrets, with the new secret as first element of the array, and including previous secrets as the later elements.

**Note** HMAC-256 is used to sign the session ID. For this reason, the secret should contain at least 32 bytes of entropy.

##### [store](#store)

The session store instance, defaults to a new `MemoryStore` instance.

##### [unset](#unset)

Control the result of unsetting `req.session` (through `delete`, setting to `null`, etc.).

The default value is `'keep'`.

* `'destroy'` The session will be destroyed (deleted) when the response ends.
* `'keep'` The session in the store will be kept, but modifications made during the request are ignored and not saved.

### [req.session](#reqsession)

To store or access session data, simply use the request property `req.session`, which is (generally) serialized as JSON by the store, so nested objects are typically fine. For example below is a user-specific view counter:

```
// Use the session middleware
app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 } }));


// Access the session as req.session
app.get('/', function (req, res, next) {
  if (req.session.views) {
    req.session.views++;
    res.setHeader('Content-Type', 'text/html');
    res.write('<p>views: ' + req.session.views + '</p>');
    res.write('<p>expires in: ' + req.session.cookie.maxAge / 1000 + 's</p>');
    res.end();
  } else {
    req.session.views = 1;
    res.end('welcome to the session demo. refresh!');
  }
});
```

#### [Session.regenerate(callback)](#sessionregeneratecallback)

To regenerate the session simply invoke the method. Once complete, a new SID and `Session` instance will be initialized at `req.session` and the `callback` will be invoked.

```
req.session.regenerate(function (err) {
  // will have a new session here
});
```

#### [Session.destroy(callback)](#sessiondestroycallback)

Destroys the session and will unset the `req.session` property. Once complete, the `callback` will be invoked.

```
req.session.destroy(function (err) {
  // cannot access session here
});
```

#### [Session.reload(callback)](#sessionreloadcallback)

Reloads the session data from the store and re-populates the `req.session` object. Once complete, the `callback` will be invoked.

```
req.session.reload(function (err) {
  // session updated
});
```

#### [Session.save(callback)](#sessionsavecallback)

Save the session back to the store, replacing the contents on the store with the contents in memory (though a store may do something else—consult the store’s documentation for exact behavior).

This method is automatically called at the end of the HTTP response if the session data has been altered (though this behavior can be altered with various options in the middleware constructor). Because of this, typically this method does not need to be called.

There are some cases where it is useful to call this method, for example, redirects, long-lived requests or in WebSockets.

```
req.session.save(function (err) {
  // session saved
});
```

#### [Session.touch()](#sessiontouch)

Updates the `.maxAge` property. Typically this is not necessary to call, as the session middleware does this for you.

### [req.session.id](#reqsessionid)

Each session has a unique ID associated with it. This property is an alias of [`req.sessionID`](#reqsessionid-1) and cannot be modified. It has been added to make the session ID accessible from the `session` object.

### [req.session.cookie](#reqsessioncookie)

Each session has a unique cookie object accompany it. This allows you to alter the session cookie per visitor. For example we can set `req.session.cookie.expires` to `false` to enable the cookie to remain for only the duration of the user-agent.

#### [Cookie.maxAge](#cookiemaxage-1)

Alternatively `req.session.cookie.maxAge` will return the time remaining in milliseconds, which we may also re-assign a new value to adjust the `.expires` property appropriately. The following are essentially equivalent

```
var hour = 3600000;
req.session.cookie.expires = new Date(Date.now() + hour);
req.session.cookie.maxAge = hour;
```

For example when `maxAge` is set to `60000` (one minute), and 30 seconds has elapsed it will return `30000` until the current request has completed, at which time `req.session.touch()` is called to reset `req.session.cookie.maxAge` to its original value.

```
req.session.cookie.maxAge; // => 30000
```

#### [Cookie.originalMaxAge](#cookieoriginalmaxage)

The `req.session.cookie.originalMaxAge` property returns the original `maxAge` (time-to-live), in milliseconds, of the session cookie.

### [req.sessionID](#reqsessionid-1)

To get the ID of the loaded session, access the request property `req.sessionID`. This is simply a read-only value set when a session is loaded/created.

## [Session Store Implementation](#session-store-implementation)

Every session store *must* be an `EventEmitter` and implement specific methods. The following methods are the list of **required**, **recommended**, and **optional**.

* Required methods are ones that this module will always call on the store.
* Recommended methods are ones that this module will call on the store if available.
* Optional methods are ones this module does not call at all, but helps present uniform stores to users.

For an example implementation view the [connect-redis](http://github.com/visionmedia/connect-redis) repo.

### [store.all(callback)](#storeallcallback)

**Optional**

This optional method is used to get all sessions in the store as an array. The `callback` should be called as `callback(error, sessions)`.

### [store.destroy(sid, callback)](#storedestroysid-callback)

**Required**

This required method is used to destroy/delete a session from the store given a session ID (`sid`). The `callback` should be called as `callback(error)` once the session is destroyed.

### [store.clear(callback)](#storeclearcallback)

**Optional**

This optional method is used to delete all sessions from the store. The `callback` should be called as `callback(error)` once the store is cleared.

### [store.length(callback)](#storelengthcallback)

**Optional**

This optional method is used to get the count of all sessions in the store. The `callback` should be called as `callback(error, len)`.

### [store.get(sid, callback)](#storegetsid-callback)

**Required**

This required method is used to get a session from the store given a session ID (`sid`). The `callback` should be called as `callback(error, session)`.

The `session` argument should be a session if found, otherwise `null` or `undefined` if the session was not found (and there was no error). A special case is made when `error.code === 'ENOENT'` to act like `callback(null, null)`.

### [store.set(sid, session, callback)](#storesetsid-session-callback)

**Required**

This required method is used to upsert a session into the store given a session ID (`sid`) and session (`session`) object. The callback should be called as `callback(error)` once the session has been set in the store.

### [store.touch(sid, session, callback)](#storetouchsid-session-callback)

**Recommended**

This recommended method is used to “touch” a given session given a session ID (`sid`) and session (`session`) object. The `callback` should be called as `callback(error)` once the session has been touched.

This is primarily used when the store will automatically delete idle sessions and this method is used to signal to the store the given session is active, potentially resetting the idle timer.

## [Compatible Session Stores](#compatible-session-stores)

The following modules implement a session store that is compatible with this module. Please make a PR to add additional modules :)

[!\[★\]\[aerospike-session-store-image\] aerospike-session-store](https://www.npmjs.com/package/aerospike-session-store) A session store using [Aerospike](http://www.aerospike.com/).

[!\[★\]\[better-sqlite3-session-store-image\] better-sqlite3-session-store](https://www.npmjs.com/package/better-sqlite3-session-store) A session store based on [better-sqlite3](https://github.com/JoshuaWise/better-sqlite3).

[!\[★\]\[cassandra-store-image\] cassandra-store](https://www.npmjs.com/package/cassandra-store) An Apache Cassandra-based session store.

[!\[★\]\[cluster-store-image\] cluster-store](https://www.npmjs.com/package/cluster-store) A wrapper for using in-process / embedded stores - such as SQLite (via knex), leveldb, files, or memory - with node cluster (desirable for Raspberry Pi 2 and other multi-core embedded devices).

[!\[★\]\[connect-arango-image\] connect-arango](https://www.npmjs.com/package/connect-arango) An ArangoDB-based session store.

[!\[★\]\[connect-azuretables-image\] connect-azuretables](https://www.npmjs.com/package/connect-azuretables) An [Azure Table Storage](https://azure.microsoft.com/en-gb/services/storage/tables/)-based session store.

[!\[★\]\[connect-cloudant-store-image\] connect-cloudant-store](https://www.npmjs.com/package/connect-cloudant-store) An [IBM Cloudant](https://cloudant.com/)-based session store.

[!\[★\]\[connect-cosmosdb-image\] connect-cosmosdb](https://www.npmjs.com/package/connect-cosmosdb) An Azure [Cosmos DB](https://azure.microsoft.com/en-us/products/cosmos-db/)-based session store.

[!\[★\]\[connect-couchbase-image\] connect-couchbase](https://www.npmjs.com/package/connect-couchbase) A [couchbase](http://www.couchbase.com/)-based session store.

[!\[★\]\[connect-datacache-image\] connect-datacache](https://www.npmjs.com/package/connect-datacache) An [IBM Bluemix Data Cache](http://www.ibm.com/cloud-computing/bluemix/)-based session store.

[!\[★\]\[@google-cloud/connect-datastore-image\] @google-cloud/connect-datastore](https://www.npmjs.com/package/@google-cloud/connect-datastore) A [Google Cloud Datastore](https://cloud.google.com/datastore/docs/concepts/overview)-based session store.

[!\[★\]\[connect-db2-image\] connect-db2](https://www.npmjs.com/package/connect-db2) An IBM DB2-based session store built using [ibm\_db](https://www.npmjs.com/package/ibm_db) module.

[!\[★\]\[connect-dynamodb-image\] connect-dynamodb](https://www.npmjs.com/package/connect-dynamodb) A DynamoDB-based session store.

[!\[★\]\[@google-cloud/connect-firestore-image\] @google-cloud/connect-firestore](https://www.npmjs.com/package/@google-cloud/connect-firestore) A [Google Cloud Firestore](https://cloud.google.com/firestore/docs/overview)-based session store.

[!\[★\]\[connect-hazelcast-image\] connect-hazelcast](https://www.npmjs.com/package/connect-hazelcast) Hazelcast session store for Connect and Express.

[!\[★\]\[connect-loki-image\] connect-loki](https://www.npmjs.com/package/connect-loki) A Loki.js-based session store.

[!\[★\]\[connect-lowdb-image\] connect-lowdb](https://www.npmjs.com/package/connect-lowdb) A lowdb-based session store.

[!\[★\]\[connect-memcached-image\] connect-memcached](https://www.npmjs.com/package/connect-memcached) A memcached-based session store.

[!\[★\]\[connect-memjs-image\] connect-memjs](https://www.npmjs.com/package/connect-memjs) A memcached-based session store using [memjs](https://www.npmjs.com/package/memjs) as the memcached client.

[!\[★\]\[connect-ml-image\] connect-ml](https://www.npmjs.com/package/connect-ml) A MarkLogic Server-based session store.

[!\[★\]\[connect-monetdb-image\] connect-monetdb](https://www.npmjs.com/package/connect-monetdb) A MonetDB-based session store.

[!\[★\]\[connect-mongo-image\] connect-mongo](https://www.npmjs.com/package/connect-mongo) A MongoDB-based session store.

[!\[★\]\[connect-mongodb-session-image\] connect-mongodb-session](https://www.npmjs.com/package/connect-mongodb-session) Lightweight MongoDB-based session store built and maintained by MongoDB.

[!\[★\]\[connect-mssql-v2-image\] connect-mssql-v2](https://www.npmjs.com/package/connect-mssql-v2) A Microsoft SQL Server-based session store based on [connect-mssql](https://www.npmjs.com/package/connect-mssql).

[!\[★\]\[connect-neo4j-image\] connect-neo4j](https://www.npmjs.com/package/connect-neo4j) A [Neo4j](https://neo4j.com)-based session store.

[!\[★\]\[connect-ottoman-image\] connect-ottoman](https://www.npmjs.com/package/connect-ottoman) A [couchbase ottoman](http://www.couchbase.com/)-based session store.

[!\[★\]\[connect-pg-simple-image\] connect-pg-simple](https://www.npmjs.com/package/connect-pg-simple) A PostgreSQL-based session store.

[!\[★\]\[connect-redis-image\] connect-redis](https://www.npmjs.com/package/connect-redis) A Redis-based session store.

[!\[★\]\[connect-session-firebase-image\] connect-session-firebase](https://www.npmjs.com/package/connect-session-firebase) A session store based on the [Firebase Realtime Database](https://firebase.google.com/docs/database/)

[!\[★\]\[connect-session-knex-image\] connect-session-knex](https://www.npmjs.com/package/connect-session-knex) A session store using [Knex.js](http://knexjs.org/), which is a SQL query builder for PostgreSQL, MySQL, MariaDB, SQLite3, and Oracle.

[!\[★\]\[connect-session-sequelize-image\] connect-session-sequelize](https://www.npmjs.com/package/connect-session-sequelize) A session store using [Sequelize.js](https://sequelize.org/), which is a Node.js / io.js ORM for PostgreSQL, MySQL, SQLite and MSSQL.

[!\[★\]\[connect-sqlite3-image\] connect-sqlite3](https://www.npmjs.com/package/connect-sqlite3) A [SQLite3](https://github.com/mapbox/node-sqlite3) session store modeled after the TJ’s `connect-redis` store.

[!\[★\]\[connect-typeorm-image\] connect-typeorm](https://www.npmjs.com/package/connect-typeorm) A [TypeORM](https://github.com/typeorm/typeorm)-based session store.

[!\[★\]\[couchdb-expression-image\] couchdb-expression](https://www.npmjs.com/package/couchdb-expression) A [CouchDB](https://couchdb.apache.org/)-based session store.

[!\[★\]\[dynamodb-store-image\] dynamodb-store](https://www.npmjs.com/package/dynamodb-store) A DynamoDB-based session store.

[!\[★\]\[express-etcd-image\] express-etcd](https://www.npmjs.com/package/express-etcd) An [etcd](https://github.com/stianeikeland/node-etcd) based session store.

[!\[★\]\[express-mysql-session-image\] express-mysql-session](https://www.npmjs.com/package/express-mysql-session) A session store using native [MySQL](https://www.mysql.com/) via the [node-mysql](https://github.com/felixge/node-mysql) module.

[!\[★\]\[express-nedb-session-image\] express-nedb-session](https://www.npmjs.com/package/express-nedb-session) A NeDB-based session store.

[!\[★\]\[express-oracle-session-image\] express-oracle-session](https://www.npmjs.com/package/express-oracle-session) A session store using native [oracle](https://www.oracle.com/) via the [node-oracledb](https://www.npmjs.com/package/oracledb) module.

[!\[★\]\[express-session-cache-manager-image\] express-session-cache-manager](https://www.npmjs.com/package/express-session-cache-manager) A store that implements [cache-manager](https://www.npmjs.com/package/cache-manager), which supports a [variety of storage types](https://www.npmjs.com/package/cache-manager#store-engines).

[!\[★\]\[express-session-etcd3-image\] express-session-etcd3](https://www.npmjs.com/package/express-session-etcd3) An [etcd3](https://github.com/mixer/etcd3) based session store.

[!\[★\]\[express-session-level-image\] express-session-level](https://www.npmjs.com/package/express-session-level) A [LevelDB](https://github.com/Level/levelup) based session store.

[!\[★\]\[express-session-rsdb-image\] express-session-rsdb](https://www.npmjs.com/package/express-session-rsdb) Session store based on Rocket-Store: A very simple, super fast and yet powerful, flat file database.

[!\[★\]\[express-sessions-image\] express-sessions](https://www.npmjs.com/package/express-sessions) A session store supporting both MongoDB and Redis.

[!\[★\]\[firestore-store-image\] firestore-store](https://www.npmjs.com/package/firestore-store) A [Firestore](https://github.com/hendrysadrak/firestore-store)-based session store.

[!\[★\]\[fortune-session-image\] fortune-session](https://www.npmjs.com/package/fortune-session) A [Fortune.js](https://github.com/fortunejs/fortune) based session store. Supports all backends supported by Fortune (MongoDB, Redis, Postgres, NeDB).

[!\[★\]\[hazelcast-store-image\] hazelcast-store](https://www.npmjs.com/package/hazelcast-store) A Hazelcast-based session store built on the [Hazelcast Node Client](https://www.npmjs.com/package/hazelcast-client).

[!\[★\]\[level-session-store-image\] level-session-store](https://www.npmjs.com/package/level-session-store) A LevelDB-based session store.

[!\[★\]\[lowdb-session-store-image\] lowdb-session-store](https://www.npmjs.com/package/lowdb-session-store) A [lowdb](https://www.npmjs.com/package/lowdb)-based session store.

[!\[★\]\[medea-session-store-image\] medea-session-store](https://www.npmjs.com/package/medea-session-store) A Medea-based session store.

[!\[★\]\[memorystore-image\] memorystore](https://www.npmjs.com/package/memorystore) A memory session store made for production.

[!\[★\]\[mssql-session-store-image\] mssql-session-store](https://www.npmjs.com/package/mssql-session-store) A SQL Server-based session store.

[!\[★\]\[nedb-session-store-image\] nedb-session-store](https://www.npmjs.com/package/nedb-session-store) An alternate NeDB-based (either in-memory or file-persisted) session store.

[!\[★\]\[@quixo3/prisma-session-store-image\] @quixo3/prisma-session-store](https://www.npmjs.com/package/@quixo3/prisma-session-store) A session store for the [Prisma Framework](https://www.prisma.io).

[!\[★\]\[restsession-image\] restsession](https://www.npmjs.com/package/restsession) Store sessions utilizing a RESTful API

[!\[★\]\[sequelstore-connect-image\] sequelstore-connect](https://www.npmjs.com/package/sequelstore-connect) A session store using [Sequelize.js](https://sequelize.org/).

[!\[★\]\[session-file-store-image\] session-file-store](https://www.npmjs.com/package/session-file-store) A file system-based session store.

[!\[★\]\[session-pouchdb-store-image\] session-pouchdb-store](https://www.npmjs.com/package/session-pouchdb-store) Session store for PouchDB / CouchDB. Accepts embedded, custom, or remote PouchDB instance and realtime synchronization.

[!\[★\]\[@databunker/session-store-image\] @databunker/session-store](https://www.npmjs.com/package/@databunker/session-store) A [Databunker](https://databunker.org/)-based encrypted session store.

[!\[★\]\[sessionstore-image\] sessionstore](https://www.npmjs.com/package/sessionstore) A session store that works with various databases.

[!\[★\]\[tch-nedb-session-image\] tch-nedb-session](https://www.npmjs.com/package/tch-nedb-session) A file system session store based on NeDB.

## [Examples](#examples)

### [View counter](#view-counter)

A simple example using `express-session` to store page views for a user.

```
var express = require('express');
var parseurl = require('parseurl');
var session = require('express-session');


var app = express();


app.use(
  session({
    secret: 'keyboard cat',
    resave: false,
    saveUninitialized: true,
  })
);


app.use(function (req, res, next) {
  if (!req.session.views) {
    req.session.views = {};
  }


  // get the url pathname
  var pathname = parseurl(req).pathname;


  // count the views
  req.session.views[pathname] = (req.session.views[pathname] || 0) + 1;


  next();
});


app.get('/foo', function (req, res, next) {
  res.send('you viewed this page ' + req.session.views['/foo'] + ' times');
});


app.get('/bar', function (req, res, next) {
  res.send('you viewed this page ' + req.session.views['/bar'] + ' times');
});


app.listen(3000);
```

### [User login](#user-login)

A simple example using `express-session` to keep a user log in session.

```
var escapeHtml = require('escape-html');
var express = require('express');
var session = require('express-session');


var app = express();


app.use(
  session({
    secret: 'keyboard cat',
    resave: false,
    saveUninitialized: true,
  })
);


// middleware to test if authenticated
function isAuthenticated(req, res, next) {
  if (req.session.user) next();
  else next('route');
}


app.get('/', isAuthenticated, function (req, res) {
  // this is only called when there is an authentication user due to isAuthenticated
  res.send('hello, ' + escapeHtml(req.session.user) + '!' + ' <a href="/logout">Logout</a>');
});


app.get('/', function (req, res) {
  res.send(
    '<form action="/login" method="post">' +
      'Username: <input name="user"><br />' +
      'Password: <input name="pass" type="password"><br />' +
      '<input type="submit" text="Login"></form>'
  );
});


app.post('/login', express.urlencoded({ extended: false }), function (req, res) {
  // login logic to validate req.body.user and req.body.pass
  // would be implemented here. for this example any combo works


  // regenerate the session, which is good practice to help
  // guard against forms of session fixation
  req.session.regenerate(function (err) {
    if (err) next(err);


    // store user information in session, typically a user id
    req.session.user = req.body.user;


    // save the session before redirection to ensure page
    // load does not happen before session is saved
    req.session.save(function (err) {
      if (err) return next(err);
      res.redirect('/');
    });
  });
});


app.get('/logout', function (req, res, next) {
  // logout logic


  // clear the user from the session object and save.
  // this will ensure that re-using the old session id
  // does not have a logged in user
  req.session.user = null;
  req.session.save(function (err) {
    if (err) next(err);


    // regenerate the session, which is good practice to help
    // guard against forms of session fixation
    req.session.regenerate(function (err) {
      if (err) next(err);
      res.redirect('/');
    });
  });
});


app.listen(3000);
```

## [Debugging](#debugging)

This module uses the [debug](https://www.npmjs.com/package/debug) module internally to log information about session operations.

To see all the internal logs, set the `DEBUG` environment variable to `express-session` when launching your app (`npm start`, in this example):

Terminal window

```
$ DEBUG=express-session npm start
```

On Windows, use the corresponding command;

Terminal window

```
> set DEBUG=express-session & npm start
```

## [License](#license)

[MIT](https://github.com/expressjs/session/blob/HEAD/LICENSE)

----
url: https://expressjs.com/en/resources/contributing
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/contributing.mdx)

# [Contributing to Express](#overview)

Express is an [OpenJS Foundation](https://openjsf.org/) project spread across three GitHub organizations: [expressjs](https://github.com/expressjs), [pillarjs](https://github.com/pillarjs), and [jshttp](https://github.com/jshttp). All contributions are welcome, whether it’s reporting bugs, improving documentation, or submitting code. The guidelines below describe how the project operates and how you can get involved.

## [Technical committee](#technical-committee)

The Express technical committee consists of active project members, and guides development and maintenance of the Express project. For more information, see [Express Community - Technical committee](/en/resources/community/#technical-committee).

## [Community contributing guide](#community-contributing-guide)

The goal of this document is to create a contribution process that:

* Encourages new contributions.
* Encourages contributors to remain involved.
* Avoids unnecessary processes and bureaucracy whenever possible.
* Creates a transparent decision making process that makes it clear how contributors can be involved in decision making.

### [Vocabulary](#vocabulary)

* A **Contributor** is any individual creating or commenting on an issue or pull request.
* A **Committer** is a subset of contributors who have been given write access to the repository.
* A **Project Captain** is the lead maintainer of a repository.
* A **TC (Technical Committee)** is a group of committers representing the required technical expertise to resolve rare disputes.
* A **Triager** is a subset of contributors who have been given triage access to the repository.

### [Logging Issues](#logging-issues)

Log an issue for any question or problem you might have. When in doubt, log an issue, and any additional policies about what to include will be provided in the responses. The only exception is security disclosures which should be sent privately.

Committers may direct you to another repository, ask for additional clarifications, and add appropriate metadata before the issue is addressed.

Please be courteous and respectful. Every participant is expected to follow the project’s Code of Conduct.

### [Contributions](#contributions)

Any change to resources in this repository must be through pull requests. This applies to all changes to documentation, code, binary files, etc. Even long term committers and TC members must use pull requests.

No pull request can be merged without being reviewed.

For non-trivial contributions, pull requests should sit for at least 36 hours to ensure that contributors in other timezones have time to review. Consideration should also be given to weekends and other holiday periods to ensure active committers all have reasonable time to become involved in the discussion and review process if they wish.

The default for each contribution is that it is accepted once no committer has an objection. During a review, committers may also request that a specific contributor who is most versed in a particular area gives a “LGTM” before the PR can be merged. There is no additional “sign off” process for contributions to land. Once all issues brought by committers are addressed it can be landed by any committer.

In the case of an objection being raised in a pull request by another committer, all involved committers should seek to arrive at a consensus by way of addressing concerns being expressed by discussion, compromise on the proposed change, or withdrawal of the proposed change.

If a contribution is controversial and committers cannot agree about how to get it to land or if it should land then it should be escalated to the TC. TC members should regularly discuss pending contributions in order to find a resolution. It is expected that only a small minority of issues be brought to the TC for resolution and that discussion and compromise among committers be the default resolution mechanism.

### [Becoming a Triager](#becoming-a-triager)

Anyone can become a triager! Read more about the process of being a triager in [the triage process document](https://github.com/expressjs/discussions/blob/HEAD/docs/contributing/triager-guide.md).

Currently, any existing [organization member](https://github.com/orgs/expressjs/people) can nominate a new triager. If you are interested in becoming a triager, our best advice is to actively participate in the community by helping triaging issues and pull requests. As well we recommend to engage in other community activities like attending the TC meetings, and participating in the Slack discussions. If you feel ready and have been helping triage some issues, reach out to an active member of the organization to ask if they’d be willing to support you. If they agree, they can create a pull request to formalize your nomination. In the case of an objection to the nomination, the triage team is responsible for working with the individuals involved and finding a resolution.

You can also reach out to any of the [organization members](https://github.com/orgs/expressjs/people) if you have questions or need guidance.

### [Becoming a Committer](#becoming-a-committer)

All contributors who have landed significant and valuable contributions should be onboarded in a timely manner, and added as a committer, and be given write access to the repository.

Committers are expected to follow this policy and continue to send pull requests, go through proper review, and have other committers merge their pull requests.

### [TC Process](#tc-process)

The TC uses a “consensus seeking” process for issues that are escalated to the TC. The group tries to find a resolution that has no open objections among TC members. If a consensus cannot be reached that has no objections then a majority wins vote is called. It is also expected that the majority of decisions made by the TC are via a consensus seeking process and that voting is only used as a last-resort.

Resolution may involve returning the issue to project captains with suggestions on how to move forward towards a consensus. It is not expected that a meeting of the TC will resolve all issues on its agenda during that meeting and may prefer to continue the discussion happening among the project captains.

Members can be added to the TC at any time. Any TC member can nominate another committer to the TC and the TC uses its standard consensus seeking process to evaluate whether or not to add this new member. The TC will consist of a minimum of 3 active members and a maximum of 10. If the TC should drop below 5 members the active TC members should nominate someone new. If a TC member is stepping down, they are encouraged (but not required) to nominate someone to take their place.

TC members will be added as admin’s on the Github orgs, npm orgs, and other resources as necessary to be effective in the role.

To remain “active” a TC member should have participation within the last 12 months and miss no more than six consecutive TC meetings. Our goal is to increase participation, not punish people for any lack of participation, this guideline should be only be used as such (replace an inactive member with a new active one, for example). Members who do not meet this are expected to step down. If A TC member does not step down, an issue can be opened in the discussions repo to move them to inactive status. TC members who step down or are removed due to inactivity will be moved into inactive status.

Inactive status members can become active members by self nomination if the TC is not already larger than the maximum of 10. They will also be given preference if, while at max size, an active member steps down.

### [Project Captains](#project-captains)

The Express TC can designate captains for individual projects/repos in the organizations. These captains are responsible for being the primary day-to-day maintainers of the repo on a technical and community front. Repo captains are empowered with repo ownership and package publication rights. When there are conflicts, especially on topics that effect the Express project at large, captains are responsible to raise it up to the TC and drive those conflicts to resolution. Captains are also responsible for making sure community members follow the community guidelines, maintaining the repo and the published package, as well as in providing user support.

Like TC members, Repo captains are a subset of committers.

To become a captain for a project the candidate is expected to participate in that project for at least 6 months as a committer prior to the request. They should have helped with code contributions as well as triaging issues. They are also required to have 2FA enabled on both their GitHub and npm accounts.

Any TC member or an existing captain on the **same** repo can nominate another committer to the captain role. To do so, they should submit a PR to this document, updating the **Active Project Captains** section (while maintaining the sort order) with the project name, the nominee’s GitHub handle, and their npm username (if different).

* Repos can have as many captains as make sense for the scope of work.
* A TC member or an existing repo captain **on the same project** can nominate a new captain. Repo captains from other projects should not nominate captains for a different project.

The PR will require at least 2 approvals from TC members and 2 weeks hold time to allow for comment and/or dissent. When the PR is merged, a TC member will add them to the proper GitHub/npm groups.

#### [Active Projects and Captains](#active-projects-and-captains)

The list can be found at <https://github.com/expressjs/discussions/blob/HEAD/docs/contributing/captains_and_committers.md#active-projects-and-members>

#### [Current Initiative Captains](#current-initiative-captains)

The list can be found at <https://github.com/expressjs/discussions/blob/HEAD/docs/contributing/captains_and_committers.md#current-initiative-captains>

### [Inactivity and Emeritus Policy for Any Role](#inactivity-and-emeritus-policy-for-any-role)

To support the health and continuity of the project, all individuals holding a role within the community (such as Triager, Committer, WG member, Project Captain, or TC member) are encouraged to maintain active participation.

Inactivity is defined as the absence of meaningful involvement in the project—such as contributions, code reviews, triage, meeting attendance, or discussion participation—for a continuous period of 6 months.

#### [Exceptions](#exceptions)

Anyone may request a temporary leave from active participation due to personal or professional reasons. In such cases, the individual should inform the relevant team or the Technical Committee (TC). During this time, the inactivity policy is paused, and the individual will not be flagged as inactive.

#### [Inactivity Process](#inactivity-process)

* If someone is deemed inactive, the individual may be transitioned to an emeritus role that reflects their past contributions. A best effort will be made to inform them that this has occurred. They may request to be reinstated when they are ready to be active again.
* The emeritus status helps preserve a clear record of contributors who have meaningfully shaped the project over time.

#### [Accountability](#accountability)

* The Technical Committee (TC) and the respective captains of each package/team are responsible for assessing activity levels and enacting this policy fairly and transparently, in coordination with other relevant teams.
* In case of disagreement, the situation can be discussed and resolved by consensus within the TC or appropriate team.

### [Developer’s Certificate of Origin 1.1](#developers-certificate-of-origin-11)

```
By making a contribution to this project, I certify that:


 (a) The contribution was created in whole or in part by me and I
     have the right to submit it under the open source license
     indicated in the file; or


 (b) The contribution is based upon previous work that, to the best
     of my knowledge, is covered under an appropriate open source
     license and I have the right under that license to submit that
     work with modifications, whether created in whole or in part
     by me, under the same open source license (unless I am
     permitted to submit under a different license), as indicated
     in the file; or


 (c) The contribution was provided directly to me by some other
     person who certified (a), (b) or (c) and I have not modified
     it.


 (d) I understand and agree that this project and the contribution
     are public and that a record of the contribution (including all
     personal information I submit with it, including my sign-off) is
     maintained indefinitely and may be redistributed consistent with
     this project or the open source license(s) involved.
```

## [Collaborator’s guide](#collaborators-guide)

### [Website Issues](#website-issues)

Open issues for the expressjs.com website in <https://github.com/expressjs/expressjs.com>.

For issues in other Express managed repos (everything in `expressjs`, `pillarjs` or `jshttp` other than `expressjs/express`), be sure to check their contributing guide and open issues and PRs in the appropriate repository.

### [PRs and Code contributions](#prs-and-code-contributions)

* Tests must pass.
* Follow the [JavaScript Standard Style](https://standardjs.com/) and `npm run lint`.
* If you fix a bug, add a test.

### [Branches](#branches)

Use the `master` branch for bug fixes or minor work that is intended for the current release stream.

Use the correspondingly named branch, e.g. `6.x`, for anything intended for a future release of Express.

### [Steps for contributing](#steps-for-contributing)

1. Create an issue for the bug you want to fix or the feature that you want to add.
2. Create your own fork on GitHub, then checkout your fork.
3. Write your code in your local copy. It’s good practice to create a branch for each new issue you work on, although not compulsory.
4. To run the test suite, first install the dependencies by running `npm install`, then run `npm test`.
5. Ensure your code is linted by running `npm run lint` — fix any issue you see listed.
6. If the tests pass, you can commit your changes to your fork and then create a pull request from there. Make sure to reference your issue from the pull request comments by including the issue number e.g. `#123`.

### [Issues which are questions](#issues-which-are-questions)

We will typically close any vague issues or questions that are specific to some app you are writing. Please double check the docs and other references before being trigger happy with posting a question issue.

Things that will help get your question issue looked at:

* Full and runnable JS code.
* Clear description of the problem or unexpected behavior.
* Clear description of the expected result.
* Steps you have taken to debug it yourself.

If you post a question and do not outline the above items or make it easy for us to understand and reproduce your issue, it will be closed.

If your question meets all of the above requirements but you do not believe it needs to be looked at by the maintainers (for example, if you are just looking for community input) please open it as a discussion topic instead of an issue. If you are unsure and open an issue, we may move it to discussions if we triage them and decide they do not need high visibility or maintainer input.

## [Security Policies and Procedures](#security-policies-and-procedures)

This document outlines security procedures and general policies for the Express project.

* [Reporting a Bug or Security Vulnerability](#reporting-a-bug-or-security-vulnerability)
* [Disclosure Policy](#disclosure-policy)
* [Comments on this Policy](#comments-on-this-policy)
* [The Express Threat Model](#the-express-threat-model)

### [Reporting a Bug or Security Vulnerability](#reporting-a-bug-or-security-vulnerability)

### Note

Before reporting a vulnerability, please review the [Express Threat Model](#the-express-threat-model) to check if the issue falls within Express’s security scope.

The Express team and community take all security vulnerabilities seriously. Thank you for improving the security of Express and related projects. We appreciate your efforts in responsible disclosure and will make every effort to acknowledge your contributions.

A [Security triage team member](https://github.com/expressjs/security-wg#security-triage-team-expressjssecurity-triage) or [the repo captain](https://github.com/expressjs/discussions/blob/master/docs/contributing/captains_and_committers.md) will acknowledge your report as soon as possible. These timelines may extend when our triage volunteers are away on holiday, particularly at the end of the year.

After the initial reply to your report, the security team will endeavor to keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.

### Note

You can find more information about our process in [this guide](https://github.com/expressjs/security-wg/blob/main/docs/incident_response_plan.md)

#### [Reporting Security Bugs via GitHub Security Advisory (Preferred)](#reporting-security-bugs-via-github-security-advisory-preferred)

The preferred way to report security vulnerabilities is through [GitHub Security Advisories](https://github.com/advisories). This allows us to collaborate on a fix while maintaining the confidentiality of the report.

To report a vulnerability ([docs](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability)):

1. Visit the **Security** tab of the affected repository on GitHub.
2. Click **Report a vulnerability** and follow the provided steps.

This process applies to any repositories within the Express ecosystem. If you are unsure whether a repository falls under this policy, feel free to reach out via email.

#### [Reporting via Email](#reporting-via-email)

If you prefer, you can also report security issues by emailing `express-security@lists.openjsf.org`.

To ensure a timely response, please include all relevant details directly in the email body rather than linking to external sources or attaching files.

The lead maintainer will acknowledge your email within 48 hours and provide an initial response outlining the next steps. The security team will keep you updated on the progress and may request additional details.

#### [Third-Party Modules](#third-party-modules)

If the security issue pertains to a third-party module that is not directly maintained within the Express ecosystem, please report it to the maintainers of that module.

### [Disclosure Policy](#disclosure-policy)

When the security team receives a security bug report, they will assign it to a primary handler. This person will coordinate the fix and release process, involving the following steps:

* Confirm the problem and determine the affected versions.
* Audit code to find any potential similar problems.
* Prepare fixes for all releases still under maintenance. These fixes will be released as fast as possible to npm.

### [Comments on this Policy](#comments-on-this-policy)

If you have suggestions on how this process could be improved please submit a pull request.

### [The Express Threat Model](#the-express-threat-model)

The Express threat model defines the boundaries of what the framework considers its security responsibility. It establishes which elements are trusted (such as the developer, the runtime environment, and application code) versus untrusted (such as data from network connections). Issues arising from trusted elements are considered out of scope, while Express is responsible for safely handling untrusted data.

Many commonly reported concerns fall outside Express’s security scope and are the responsibility of the application developer. Such as prototype pollution from unsanitized user input, misconfigured static file serving, or issues in third-party dependencies.

For complete details, see the [Express Threat Model](https://github.com/expressjs/security-wg/blob/main/docs/ThreatModel.md).

----
url: https://expressjs.com/en/resources/middleware/method-override
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/method-override.mdx)

# [method-override middleware](#overview)

v3.0.0[GitHub](https://github.com/expressjs/method-override)[Changelog](https://github.com/expressjs/method-override/releases)[npm](https://www.npmjs.com/package/method-override)

Lets you use HTTP verbs such as PUT or DELETE in places where the client doesn’t support it.

## [Install](#install)

This is a [Node.js](https://nodejs.org/en/) module available through the [npm registry](https://www.npmjs.com/). Installation is done using the [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):

Terminal window

```
npm install method-override
```

Terminal window

```
yarn add method-override
```

Terminal window

```
pnpm add method-override
```

Terminal window

```
bun add method-override
```

### Note

`method-override` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/method-override
```

Terminal window

```
yarn add --dev @types/method-override
```

Terminal window

```
pnpm add --save-dev @types/method-override
```

Terminal window

```
bun add --dev @types/method-override
```

## [API](#api)

**NOTE** It is very important that this module is used **before** any module that needs to know the method of the request (for example, it *must* be used prior to the `csurf` module).

### [methodOverride(getter, options)](#methodoverridegetter-options)

Create a new middleware function to override the `req.method` property with a new value. This value will be pulled from the provided `getter`.

* `getter` - The getter to use to look up the overridden request method for the request. (default: `X-HTTP-Method-Override`)
* `options.methods` - The allowed methods the original request must be in to check for a method override value. (default: `['POST']`)

If the found method is supported by node.js core, then `req.method` will be set to this value, as if it has originally been that value. The previous `req.method` value will be stored in `req.originalMethod`.

#### [getter](#getter)

This is the method of getting the override value from the request. If a function is provided, the `req` is passed as the first argument, the `res` as the second argument and the method is expected to be returned. If a string is provided, the string is used to look up the method with the following rules:

* If the string starts with `X-`, then it is treated as the name of a header and that header is used for the method override. If the request contains the same header multiple times, the first occurrence is used.
* All other strings are treated as a key in the URL query string.

#### [options.methods](#optionsmethods)

This allows the specification of what methods(s) the request *MUST* be in in order to check for the method override value. This defaults to only `POST` methods, which is the only method the override should arrive in. More methods may be specified here, but it may introduce security issues and cause weird behavior when requests travel through caches. This value is an array of methods in upper-case. `null` can be specified to allow all methods.

## [Examples](#examples)

### [override using a header](#override-using-a-header)

To use a header to override the method, specify the header name as a string argument to the `methodOverride` function. To then make the call, send a `POST` request to a URL with the overridden method as the value of that header. This method of using a header would typically be used in conjunction with `XMLHttpRequest` on implementations that do not support the method you are trying to use.

```
const express = require('express');
const methodOverride = require('method-override');
const app = express();


// override with the X-HTTP-Method-Override header in the request
app.use(methodOverride('X-HTTP-Method-Override'));
```

Example call with header override using `XMLHttpRequest`:

```
const xhr = new XMLHttpRequest();
xhr.onload = onload;
xhr.open('post', '/resource', true);
xhr.setRequestHeader('X-HTTP-Method-Override', 'DELETE');
xhr.send();


function onload() {
  alert('got response: ' + this.responseText);
}
```

### [override using a query value](#override-using-a-query-value)

To use a query string value to override the method, specify the query string key as a string argument to the `methodOverride` function. To then make the call, send a `POST` request to a URL with the overridden method as the value of that query string key. This method of using a query value would typically be used in conjunction with plain HTML `<form>` elements when trying to support legacy browsers but still use newer methods.

```
const express = require('express');
const methodOverride = require('method-override');
const app = express();


// override with POST having ?_method=DELETE
app.use(methodOverride('_method'));
```

Example call with query override using HTML `<form>`:

```
<form method="POST" action="/resource?_method=DELETE">
  <button type="submit">Delete resource</button>
</form>
```

### [multiple format support](#multiple-format-support)

```
const express = require('express');
const methodOverride = require('method-override');
const app = express();


// override with different headers; last one takes precedence
app.use(methodOverride('X-HTTP-Method')); //          Microsoft
app.use(methodOverride('X-HTTP-Method-Override')); // Google/GData
app.use(methodOverride('X-Method-Override')); //      IBM
```

### [custom logic](#custom-logic)

You can implement any kind of custom logic with a function for the `getter`. The following implements the logic for looking in `req.body` that was in `method-override@1`:

```
const bodyParser = require('body-parser');
const express = require('express');
const methodOverride = require('method-override');
const app = express();


// NOTE: when using req.body, you must fully parse the request body
//       before you call methodOverride() in your middleware stack,
//       otherwise req.body will not be populated.
app.use(bodyParser.urlencoded());
app.use(
  methodOverride(function (req, res) {
    if (req.body && typeof req.body === 'object' && '_method' in req.body) {
      // look in urlencoded POST bodies and delete it
      const method = req.body._method;
      delete req.body._method;
      return method;
    }
  })
);
```

Example call with query override using HTML `<form>`:

```
{/* enctype must be set to the type you will parse before methodOverride() */}
<form method="POST" action="/resource" enctype="application/x-www-form-urlencoded">
  <input type="hidden" name="_method" value="DELETE" />
  <button type="submit">Delete resource</button>
</form>
```

## [License](#license)

[MIT](https://github.com/expressjs/method-override/blob/HEAD/LICENSE)

----
url: https://expressjs.com/en/3x/api/middleware/
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/3x/api/middleware/index.mdx)

# [Middleware](#overview)

Express 3.x includes a number of built-in middleware functions that can be used to handle common tasks such as parsing request bodies, handling cookies, and more. These middleware functions are available as properties on the Express module and can be added to your application using `app.use()`.

### [basicAuth()](#basicauth)

Basic Authentication middleware, populating `req.user` with the username.

Simple username and password:

```
app.use(express.basicAuth('username', 'password'));
```

Callback verification:

```
app.use(
  express.basicAuth(function (user, pass) {
    return user === 'tj' && pass === 'wahoo';
  })
);
```

Async callback verification, accepting `fn(err, user)`, in this case `req.user` will be the user object passed.

```
app.use(
  express.basicAuth(function (user, pass, fn) {
    User.authenticate({ user: user, pass: pass }, fn);
  })
);
```

### [bodyParser()](#bodyparser)

Request body parsing middleware supporting JSON, urlencoded, and multipart requests. This middleware is simply a wrapper for the `json()`, `urlencoded()`, and `multipart()` middleware.

```
app.use(express.bodyParser());


// is equivalent to:
app.use(express.json());
app.use(express.urlencoded());
app.use(express.multipart());
```

For security sake, it’s better to disable file upload if your application doesn’t need it. To do this, use only the needed middleware, i.e. don’t use the `bodyParser` and `multipart()` middleware:

```
app.use(express.json());
app.use(express.urlencoded());
```

If your application needs file upload you should set up

[a strategy for dealing with those files](https://groups.google.com/d/msg/express-js/iP2VyhkypHo/5AXQiYN3RPcJ)

.

### [compress()](#compress)

Compress response data with gzip / deflate. This middleware should be placed “high” within the stack to ensure all responses may be compressed.

```
app.use(express.logger());
app.use(express.compress());
app.use(express.methodOverride());
app.use(express.bodyParser());
```

### [cookieParser()](#cookieparser)

Parses the Cookie header field and populates `req.cookies` with an object keyed by the cookie names. Optionally you may enabled signed cookie support by passing a `secret` string.

```
app.use(express.cookieParser());
app.use(express.cookieParser('some secret'));
```

### [cookieSession()](#cookiesession)

Provides cookie-based sessions, and populates `req.session`. This middleware takes the following options:

* `key` cookie name defaulting to `connect.sess`
* `secret` prevents cookie tampering
* `cookie` session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: null }`
* `proxy` trust the reverse proxy when setting secure cookies (via “x-forwarded-proto”)

```
app.use(express.cookieSession());
```

To clear a cookie simply assign the session to null before responding:

```
req.session = null;
```

### [csrf()](#csrf)

CSRF protection middleware.

By default this middleware generates a token named “\_csrf” which should be added to requests which mutate state, within a hidden form field, query-string etc. This token is validated against `req.csrfToken()`.

The default `value` function checks `req.body` generated by the `bodyParser()` middleware, `req.query` generated by `query()`, and the “X-CSRF-Token” header field.

This middleware requires session support, thus should be added somewhere below `session()`.

### [directory()](#directory)

Directory serving middleware, serves the given `path`. This middleware may be paired with `static()` to serve files, providing a full-featured file browser.

```
app.use(express.directory('public'));
app.use(express.static('public'));
```

This middleware accepts the following options:

* `hidden` display hidden (dot) files. Defaults to false.
* `icons` display icons. Defaults to false.
* `filter` Apply this filter function to files. Defaults to false.

----
url: https://expressjs.com/en/3x/api/response
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/3x/api/response/index.mdx)

# [API Response Overview](#overview)

The `res` object is an enhanced version of Node’s own response object and supports all [built-in fields and methods](https://nodejs.org/api/http.html#class-httpserverresponse).

## [Properties](#properties)

The `res` object contains a number of properties that provide information about the HTTP response.

### [res.charset](#rescharset)

Assign the charset. Defaults to “utf-8”.

```
res.charset = 'value';
res.send('<p>some html</p>');
// => Content-Type: text/html; charset=value
```

### [res.locals](#reslocals)

Response local variables are scoped to the request, thus only available to the view(s) rendered during that request / response cycle, if any. Otherwise this API is identical to [app.locals](/en/3x/api/application/#applocals).

This object is useful for exposing request-level information such as the request pathname, authenticated user, user settings etcetera.

```
app.use(function (req, res, next) {
  res.locals.user = req.user;
  res.locals.authenticated = !req.user.anonymous;
  next();
});
```

### [res.req](#resreq)

This property holds a reference to the [request object](/en/3x/api/request/) that relates to this response object.

## [Methods](#methods)

The `res` object contains a number of methods that can be used to send responses, set headers, and more.

### [res.attachment(\[filename\])](#resattachmentfilename)

Sets the Content-Disposition header field to “attachment”. If a `filename` is given then the Content-Type will be automatically set based on the extname via `res.type()`, and the Content-Disposition’s “filename=” parameter will be set.

```
res.attachment();
// Content-Disposition: attachment


res.attachment('path/to/logo.png');
// Content-Disposition: attachment; filename="logo.png"
// Content-Type: image/png
```

### [res.clearCookie(name, \[options\])](#resclearcookiename-options)

Clear cookie `name`. The `path` option defaults to ”/“.

```
res.cookie('name', 'tobi', { path: '/admin' });
res.clearCookie('name', { path: '/admin' });
```

### [res.cookie(name, value, \[options\])](#rescookiename-value-options)

Set cookie `name` to `value`, which may be a string or object converted to JSON. The `path` option defaults to ”/”.

```
res.cookie('name', 'tobi', { domain: '.example.com', path: '/admin', secure: true });
res.cookie('remember_me', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
```

The `maxAge` option is a convenience option for setting “expires” relative to the current time in milliseconds. The following is equivalent to the previous example.

```
res.cookie('remember_me', '1', { maxAge: 900000, httpOnly: true });
```

An object may be passed which is then serialized as JSON, which is automatically parsed by the `bodyParser()` middleware.

```
res.cookie('cart', { items: [1, 2, 3] });
res.cookie('cart', { items: [1, 2, 3] }, { maxAge: 900000 });
```

Signed cookies are also supported through this method. Simply pass the `signed` option. When given `res.cookie()` will use the secret passed to `express.cookieParser(secret)` to sign the value.

```
res.cookie('name', 'tobi', { signed: true });
```

Later you may access this value through the [req.signedCookie](/en/3x/api/request/#reqsignedcookies) object.

### [res.download(path, \[filename\], \[fn\])](#resdownloadpath-filename-fn)

Transfer the file at `path` as an “attachment”, typically browsers will prompt the user for download. The Content-Disposition “filename=” parameter, aka the one that will appear in the browser dialog is set to `path` by default, however you may provide an override `filename`.

When an error has occurred or transfer is complete the optional callback `fn` is invoked. This method uses [res.sendfile()](#ressendfilepath-options-fn) to transfer the file.

```
res.download('/report-12345.pdf');


res.download('/report-12345.pdf', 'report.pdf');


res.download('/report-12345.pdf', 'report.pdf', function (err) {
  if (err) {
    // handle error, keep in mind the response may be partially-sent
    // so check res.headerSent
  } else {
    // decrement a download credit etc
  }
});
```

### [res.format(object)](#resformatobject)

Performs content-negotiation on the request Accept header field when present. This method uses `req.accepted`, an array of acceptable types ordered by their quality values, otherwise the first callback is invoked. When no match is performed the server responds with 406 “Not Acceptable”, or invokes the `default` callback.

The Content-Type is set for you when a callback is selected, however you may alter this within the callback using `res.set()` or `res.type()` etcetera.

The following example would respond with `{ "message": "hey" }` when the Accept header field is set to “application/json” or “*/json”, however if ”*/\*” is given then “hey” will be the response.

```
res.format({
  'text/plain': function () {
    res.send('hey');
  },


  'text/html': function () {
    res.send('<p>hey</p>');
  },


  'application/json': function () {
    res.send({ message: 'hey' });
  },
});
```

In addition to canonicalized MIME types you may also use extnames mapped to these types, providing a slightly less verbose implementation:

```
res.format({
  text: function () {
    res.send('hey');
  },


  html: function () {
    res.send('<p>hey</p>');
  },


  json: function () {
    res.send({ message: 'hey' });
  },
});
```

### [res.get(field)](#resgetfield)

Get the case-insensitive response header `field`.

```
res.get('Content-Type');
// => "text/plain"
```

### [res.json(\[status|body\], \[body\])](#resjsonstatusbody-body)

Send a JSON response. This method is identical to `res.send()` when an object or array is passed, however it may be used for explicit JSON conversion of non-objects (null, undefined, etc), though these are technically not valid JSON.

```
res.json(null);
res.json({ user: 'tobi' });
res.json(500, { error: 'message' });
```

### [res.jsonp(\[status|body\], \[body\])](#resjsonpstatusbody-body)

Send a JSON response with JSONP support. This method is identical to `res.json()` however opts-in to JSONP callback support.

```
res.jsonp(null);
// => null


res.jsonp({ user: 'tobi' });
// => { "user": "tobi" }


res.jsonp(500, { error: 'message' });
// => { "error": "message" }
```

By default the JSONP callback name is simply `callback`, however you may alter this with the [jsonp callback name](/en/3x/api/application/#settings) setting. The following are some examples of JSONP responses using the same code:

```
// ?callback=foo
res.jsonp({ user: 'tobi' });
// => foo({ "user": "tobi" })


app.set('jsonp callback name', 'cb');


// ?cb=foo
res.jsonp(500, { error: 'message' });
// => foo({ "error": "message" })
```

### [res.links(links)](#reslinkslinks)

Join the given `links` to populate the “Link” response header field.

```
res.links({
  next: 'http://api.example.com/users?page=2',
  last: 'http://api.example.com/users?page=5',
});
```

p yields:

```
Link: <http://api.example.com/users?page=2> rel="next",
      <http://api.example.com/users?page=5> rel="last"
```

### [res.location()](#reslocation)

Set the location header.

```
res.location('/foo/bar');
res.location('foo/bar');
res.location('http://example.com');
res.location('../login');
res.location('back');
```

You can use the same kind of `urls` as in `res.redirect()`.

For example, if your application is mounted at `/blog`, the following would set the `location` header to `/blog/admin`:

```
res.location('admin');
```

### [res.redirect(\[status\], url)](#resredirectstatus-url)

Redirect to the given `url` with optional `status` code defaulting to 302 “Found”.

```
res.redirect('/foo/bar');
res.redirect('http://example.com');
res.redirect(301, 'http://example.com');
res.redirect('../login');
```

Express supports a few forms of redirection, first being a fully qualified URI for redirecting to a different site:

```
res.redirect('https://google.com');
```

The second form is the pathname-relative redirect, for example if you were on `http://example.com/admin/post/new`, the following redirect to `/admin` would land you at `http://example.com/admin`:

```
res.redirect('/admin');
```

This next redirect is relative to the `mount` point of the application. For example if you have a blog application mounted at `/blog`, ideally it has no knowledge of where it was mounted, so where a redirect of `/admin/post/new` would simply give you `http://example.com/admin/post/new`, the following mount-relative redirect would give you `http://example.com/blog/admin/post/new`:

```
res.redirect('admin/post/new');
```

Pathname relative redirects are also possible. If you were on `http://example.com/admin/post/new`, the following redirect would land you at `http//example.com/admin/post`:

```
res.redirect('..');
```

The final special-case is a `back` redirect, redirecting back to the Referer (or Referrer), defaulting to `/` when missing.

```
res.redirect('back');
```

### [res.render(view, \[locals\], callback)](#resrenderview-locals-callback)

Render a `view` with a callback responding with the rendered string. When an error occurs `next(err)` is invoked internally. When a callback is provided both the possible error and rendered string are passed, and no automated response is performed.

```
res.render('index', function (err, html) {
  // ...
});


res.render('user', { name: 'Tobi' }, function (err, html) {
  // ...
});
```

### [res.send(\[body|status\], \[body\])](#ressendbodystatus-body)

Send a response.

```
res.send(Buffer.from('whoop'));
res.send({ some: 'json' });
res.send('<p>some html</p>');
res.send(404, 'Sorry, we cannot find that!');
res.send(500, { error: 'something blew up' });
res.send(200);
```

This method performs a myriad of useful tasks for simple non-streaming responses such as automatically assigning the Content-Length unless previously defined and providing automatic *HEAD* and HTTP cache freshness support.

When a `Buffer` is given the Content-Type is set to “application/octet-stream” unless previously defined as shown below:

```
res.set('Content-Type', 'text/html');
res.send(Buffer.from('<p>some html</p>'));
```

When a `String` is given the Content-Type is set defaulted to “text/html”:

```
res.send('<p>some html</p>');
```

When an `Array` or `Object` is given Express will respond with the JSON representation:

```
res.send({ user: 'tobi' });
res.send([1, 2, 3]);
```

Finally when a `Number` is given without any of the previously mentioned bodies, then a response body string is assigned for you. For example 200 will respond will the text “OK”, and 404 “Not Found” and so on.

```
res.send(200);
res.send(404);
res.send(500);
```

### [res.sendfile(path, \[options\], \[fn\]\])](#ressendfilepath-options-fn)

Transfer the file at the given `path`.

Automatically defaults the Content-Type response header field based on the filename’s extension. The callback `fn(err)` is invoked when the transfer is complete or when an error occurs.

Options:

* `maxAge` in milliseconds defaulting to 0
* `root` root directory for relative filenames

This method provides fine-grained support for file serving as illustrated in the following example:

```
app.get('/user/:uid/photos/:file', function (req, res) {
  var uid = req.params.uid;
  var file = req.params.file;


  req.user.mayViewFilesFrom(uid, function (yes) {
    if (yes) {
      res.sendfile('/uploads/' + uid + '/' + file);
    } else {
      res.send(403, 'Sorry! you cant see that.');
    }
  });
});
```

### [res.set(field, \[value\])](#ressetfield-value)

Set header `field` to `value`, or pass an object to set multiple fields at once.

```
res.set('Content-Type', 'text/plain');


res.set({
  'Content-Type': 'text/plain',
  'Content-Length': '123',
  ETag: '12345',
});
```

Aliased as `res.header(field, [value])`.

### [res.status(code)](#resstatuscode)

Chainable alias of node’s `res.statusCode=`.

```
res.status(404).sendfile('path/to/404.png');
```

### [res.type(type)](#restypetype)

Sets the Content-Type to the mime lookup of `type`, or when ”/” is present the Content-Type is simply set to this literal value.

```
res.type('.html');
res.type('html');
res.type('json');
res.type('application/json');
res.type('png');
```

p Aliased as `res.contentType(type)`.

----
url: https://expressjs.com/en/blog/2024-10-22-security-audit-milestone-achievement
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2024-10-22-security-audit-milestone-achievement)

securityannouncements

# [Express.js Security Audit: A Milestone Achievement](#overview)

Express Technical CommitteeOctober 22, 2024

[](https://x.com/intent/tweet?text=Express.js%20Security%20Audit%3A%20A%20Milestone%20Achievement\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-10-22-security-audit-milestone-achievement%2F)[](https://bsky.app/intent/compose?text=Express.js%20Security%20Audit%3A%20A%20Milestone%20Achievement%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-10-22-security-audit-milestone-achievement%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-10-22-security-audit-milestone-achievement%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-10-22-security-audit-milestone-achievement%2F\&text=Express.js%20Security%20Audit%3A%20A%20Milestone%20Achievement)[](https://wa.me/?text=Express.js%20Security%20Audit%3A%20A%20Milestone%20Achievement%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-10-22-security-audit-milestone-achievement%2F)[](/feed.xml)

We are thrilled to announce the successful completion of a comprehensive security audit for Express.js, conducted by [Ada Logics](https://adalogics.com/) and facilitated by [OSTIF](https://ostif.org/). This extensive review of our framework and its core components marks a significant milestone in our commitment to ensuring the security and reliability of Express.js for our community.

## [A Collaborative Effort](#a-collaborative-effort)

This audit was made possible through the collaboration between [the Express Security Working Group](https://github.com/expressjs/security-wg), Ada Logics, OSTIF, and the [OpenJS Foundation](https://openjsf.org/). Our focus was on thoroughly evaluating the Express.js codebase, including its dependencies and core libraries. The primary goal was to identify any potential security vulnerabilities and to strengthen the overall security posture of the framework.

### [Key Highlights of the Audit](#key-highlights-of-the-audit)

* **Audit Duration**: Conducted in April and May 2024.
* **Scope**: Core Express.js codebase and critical dependencies, such as `body-parser`, `basic-auth-connect`, `serve-static`, and more.
* **Findings**: A total of 5 security vulnerabilities were identified, all of which have been addressed and patched.
* **Severity**: Issues ranged from moderate to high severity, impacting components like `res.redirect` and `serve-static`.

## [A Closer Look at the Findings](#a-closer-look-at-the-findings)

The audit identified several vulnerabilities, including potential Cross-Site Scripting (XSS) risks and a Denial of Service (DoS) vulnerability in the `body-parser` middleware. Here are the key CVEs reported:

* **CVE-2024-43796**: XSS in `res.redirect`—fixed in versions >= 4.20.0 and >= 5.0.0.
* **CVE-2024-45590**: DoS in `body-parser`—patched in version >= 1.20.3.
* **CVE-2024-47178**: Timing vulnerability in `basic-auth-connect`—patched in version >= 1.1.0.
* **CVE-2024-43799**: XSS in the `send` utility module—patched in version >= 0.19.0.
* **CVE-2024-43800**: XSS in `serve-static`—fixed in versions >= 1.16.0 and >= 2.1.0.

Each of these vulnerabilities was promptly addressed by our dedicated [security triage team](https://github.com/expressjs/security-wg?tab=readme-ov-file#security-triage-team), ensuring that users remain protected against known threats.

For full details on the audit results, you can access the [official audit report here](https://ostif.org/wp-content/uploads/2024/10/expressjs-2024-security-audit-report.pdf).

## [A Commitment to Transparency and Security](#a-commitment-to-transparency-and-security)

At Express, security is a top priority, and we believe in the importance of transparency when it comes to vulnerabilities and their resolution. This audit not only highlights our proactive approach but also reinforces our ongoing commitment to building a secure web framework for all.

We strongly recommend all users update to the latest versions of the affected packages to benefit from the recent security fixes. For more information on the patches and how to upgrade, please refer to our [September 2024 Security Release announcement](/en/blog/2024-09-29-security-releases/).

## [A Word of Thanks](#a-word-of-thanks)

This audit would not have been possible without the efforts and expertise of many individuals and organizations. We want to extend our gratitude to:

* The team at Ada Logics for their diligent review and insights.
* OSTIF for their coordination and support throughout the audit process.
* The OpenJS Foundation for sponsoring this important initiative.
* Our Express.js community, who continue to support and trust us with their projects.
* [Jordan Harband](https://github.com/ljharb) for his amazing support while we needed changes in [qs](https://www.npmjs.com/package/qs).

Together, we’ve made Express.js stronger, more resilient, and ready for the challenges ahead. We look forward to continuing to serve our community with a focus on excellence and security.

Thank you for being a part of this journey with us!

----
url: https://expressjs.com/en/5x/starter/generator
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/starter/generator.mdx)

# [Express application generator](#overview)

Use the application generator tool, `express-generator`, to quickly create an application skeleton.

You can run the application generator with the `npx` command (available in Node.js 8.2.0).

Terminal window

```
$ npx express-generator
```

For earlier Node versions, install the application generator as a global npm package and then launch it:

Terminal window

```
$ npm install -g express-generator
$ express
```

Display the command options with the `-h` option:

Terminal window

```
$ express -h


  Usage: express [options] [dir]


  Options:


    -h, --help          output usage information
        --version       output the version number
    -e, --ejs           add ejs engine support
        --hbs           add handlebars engine support
        --pug           add pug engine support
    -H, --hogan         add hogan.js engine support
        --no-view       generate without view engine
    -v, --view <engine> add view <engine> support (ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
    -c, --css <engine>  add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)
        --git           add .gitignore
    -f, --force         force on non-empty directory
```

For example, the following creates an Express app named *myapp*. The app will be created in a folder named *myapp* in the current working directory and the view engine will be set to [Pug](https://pugjs.org/ "Pug documentation"):

Terminal window

```
$ express --view=pug myapp


   create : myapp
   create : myapp/package.json
   create : myapp/app.js
   create : myapp/public
   create : myapp/public/javascripts
   create : myapp/public/images
   create : myapp/routes
   create : myapp/routes/index.js
   create : myapp/routes/users.js
   create : myapp/public/stylesheets
   create : myapp/public/stylesheets/style.css
   create : myapp/views
   create : myapp/views/index.pug
   create : myapp/views/layout.pug
   create : myapp/views/error.pug
   create : myapp/bin
   create : myapp/bin/www
```

Then install dependencies:

Terminal window

```
$ cd myapp
$ npm install
```

On MacOS or Linux, run the app with this command:

Terminal window

```
$ DEBUG=myapp:* npm start
```

On Windows Command Prompt, use this command:

Terminal window

```
> set DEBUG=myapp:* & npm start
```

On Windows PowerShell, use this command:

Terminal window

```
PS> $env:DEBUG='myapp:*'; npm start
```

Then, load `http://localhost:3000/` in your browser to access the app.

The generated app has the following directory structure:

Terminal window

```
.
├── app.js
├── bin
│   └── www
├── package.json
├── public
│   ├── images
│   ├── javascripts
│   └── stylesheets
│       └── style.css
├── routes
│   ├── index.js
│   └── users.js
└── views
    ├── error.pug
    ├── index.pug
    └── layout.pug


7 directories, 9 files
```

### Note

The app structure created by the generator is just one of many ways to structure Express apps. Feel free to use this structure or modify it to best suit your needs.

----
url: https://expressjs.com/en/5x/starter/basic-routing
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/starter/basic-routing.mdx)

# [Basic routing](#overview)

*Routing* refers to determining how an application responds to a client request to a particular endpoint, which is a URI (or path) and a specific HTTP request method (GET, POST, and so on).

Each route can have one or more handler functions, which are executed when the route is matched.

Route definition takes the following structure:

```
app.METHOD(PATH, HANDLER);
```

Where:

* `app` is an instance of `express`.
* `METHOD` is an [HTTP request method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods), in lowercase.
* `PATH` is a path on the server.
* `HANDLER` is the function executed when the route is matched.

### Caution

This tutorial assumes that an instance of `express` named `app` is created and the server is running. If you are not familiar with creating an app and starting it, see the [Hello world example](/en/5x/starter/hello-world/).

The following examples illustrate defining simple routes.

Respond with `Hello World!` on the homepage:

```
app.get('/', (req, res) => {
  res.send('Hello World!');
});
```

```
import { type Request, type Response } from 'express';


app.get('/', (req: Request, res: Response) => {
  res.send('Hello World!');
});
```

Respond to a POST request on the root route (`/`), the application’s home page:

```
app.post('/', (req, res) => {
  res.send('Got a POST request');
});
```

```
import { type Request, type Response } from 'express';


app.post('/', (req: Request, res: Response) => {
  res.send('Got a POST request');
});
```

Respond to a PUT request to the `/user` route:

```
app.put('/user', (req, res) => {
  res.send('Got a PUT request at /user');
});
```

```
import { type Request, type Response } from 'express';


app.put('/user', (req: Request, res: Response) => {
  res.send('Got a PUT request at /user');
});
```

Respond to a DELETE request to the `/user` route:

```
app.delete('/user', (req, res) => {
  res.send('Got a DELETE request at /user');
});
```

```
import { type Request, type Response } from 'express';


app.delete('/user', (req: Request, res: Response) => {
  res.send('Got a DELETE request at /user');
});
```

----
url: https://expressjs.com/en/4x/advanced/developing-template-engines
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/advanced/developing-template-engines.mdx)

# [Developing template engines for Express](#overview)

Use the `app.engine(ext, callback)` method to create your own template engine. `ext` refers to the file extension, and `callback` is the template engine function, which accepts the following items as parameters: the location of the file, the options object, and the callback function.

The following code is an example of implementing a very simple template engine for rendering `.ntl` files.

```
const fs = require('fs'); // this engine requires the fs module
app.engine('ntl', (filePath, options, callback) => {
  // define the template engine
  fs.readFile(filePath, (err, content) => {
    if (err) return callback(err);
    // this is an extremely simple template engine
    const rendered = content
      .toString()
      .replace('#title#', `<title>${options.title}</title>`)
      .replace('#message#', `<h1>${options.message}</h1>`);
    return callback(null, rendered);
  });
});
app.set('views', './views'); // specify the views directory
app.set('view engine', 'ntl'); // register the template engine
```

```
import fs from 'fs'; // this engine requires the fs module
app.engine(
  'ntl',
  (
    filePath: string,
    options: Record<string, any>,
    callback: (e: any, rendered?: string) => void
  ) => {
    // define the template engine
    fs.readFile(filePath, (err, content) => {
      if (err) return callback(err);
      // this is an extremely simple template engine
      const rendered = content
        .toString()
        .replace('#title#', `<title>${options.title}</title>`)
        .replace('#message#', `<h1>${options.message}</h1>`);
      return callback(null, rendered);
    });
  }
);
app.set('views', './views'); // specify the views directory
app.set('view engine', 'ntl'); // register the template engine
```

Your app will now be able to render `.ntl` files. Create a file named `index.ntl` in the `views` directory with the following content.

```
#title#
#message#
```

Then, create the following route in your app.

```
app.get('/', (req, res) => {
  res.render('index', { title: 'Hey', message: 'Hello there!' });
});
```

When you make a request to the home page, `index.ntl` will be rendered as HTML.

----
url: https://expressjs.com/en/5x/api/request
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/5x/api/request/index.mdx)

# [Request Object](#overview)

The `req` object represents the HTTP request and has properties for the request query string, parameters, body, HTTP headers, and so on. In this documentation and by convention, the object is always referred to as `req` (and the HTTP response is `res`) but its actual name is determined by the parameters to the callback function in which you’re working.

For example:

```
app.get('/user/:id', (req, res) => {
  res.send(`user ${req.params.id}`);
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/:id', (req: Request, res: Response) => {
  res.send(`user ${req.params.id}`);
});
```

But you could just as well have:

```
app.get('/user/:id', (request, response) => {
  response.send(`user ${request.params.id}`);
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/:id', (request: Request, response: Response) => {
  response.send(`user ${request.params.id}`);
});
```

The `req` object is an enhanced version of Node’s own request object and supports all [built-in fields and methods](https://nodejs.org/api/http.html#class-httpincomingmessage).

## [Properties](#properties)

The `req` object contains a number of properties that provide information about the HTTP request, such as headers, query parameters, and more.

### [req.app](#reqapp)

Type:`Application`

This property holds a reference to the instance of the Express application that is using the middleware.

If you follow the pattern in which you create a module that just exports a middleware function and `require()` it in your main file, then the middleware can access the Express instance via `req.app`

For example:

index.cjs

```
app.get('/viewdirectory', require('./mymiddleware.cjs'));
```

index.mjs

```
import mymiddleware from './mymiddleware.mjs';


app.get('/viewdirectory', mymiddleware);
```

And the middleware module itself:

mymiddleware.cjs

```
module.exports = (req, res) => {
  res.send(`The views directory is ${req.app.get('views')}`);
};
```

mymiddleware.mjs

```
export default (req, res) => {
  res.send(`The views directory is ${req.app.get('views')}`);
};
```

mymiddleware.ts

```
import { type Request, type Response } from 'express';


export default (req: Request, res: Response) => {
  res.send(`The views directory is ${req.app.get('views')}`);
};
```

### [req.baseUrl](#reqbaseurl)

Type:`String`

The URL path on which a router instance was mounted.

The `req.baseUrl` property is similar to the [mountpath](/en/5x/api/application/#appmountpath) property of the `app` object, except `app.mountpath` returns the matched path pattern(s).

For example:

```
const greet = express.Router();


greet.get('/jp', (req, res) => {
  console.log(req.baseUrl); // /greet
  res.send('Konnichiwa!');
});


app.use('/greet', greet); // load the router on '/greet'
```

```
import express, { type Request, type Response } from 'express';


const greet = express.Router();


greet.get('/jp', (req: Request, res: Response) => {
  console.log(req.baseUrl); // /greet
  res.send('Konnichiwa!');
});


app.use('/greet', greet); // load the router on '/greet'
```

Even if you use a path pattern or a set of path patterns to load the router, the `baseUrl` property returns the matched string, not the pattern(s). In the following example, the `greet` router is loaded on two path patterns.

```
app.use(['/gre:"param"t', '/hel{l}o'], greet); // load the router on '/gre:"param"t' and '/hel{l}o'
```

When a request is made to `/greet/jp`, `req.baseUrl` is “/greet”. When a request is made to `/hello/jp`, `req.baseUrl` is “/hello”.

### [req.body](#reqbody)

Type:`Object`

Contains key-value pairs of data submitted in the request body. By default, it is `undefined`, and is populated when you use body-parsing middleware such as [`express.json()`](/en/5x/api/express/#expressjson) or [`express.urlencoded()`](/en/5x/api/express/#expressurlencoded).

### Warning

As `req.body`’s shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, `req.body.foo.toString()` may fail in multiple ways, for example `foo` may not be there or may not be a string, and `toString` may not be a function and instead a string or other user-input.

The following example shows how to use body-parsing middleware to populate `req.body`.

index.cjs

```
const express = require('express');


const app = express();


app.use(express.json()); // for parsing application/json
app.use(express.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded


app.post('/profile', (req, res, next) => {
  console.log(req.body);
  res.json(req.body);
});
```

index.mjs

```
import express from 'express';


const app = express();


app.use(express.json()); // for parsing application/json
app.use(express.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded


app.post('/profile', (req, res, next) => {
  console.log(req.body);
  res.json(req.body);
});
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();


app.use(express.json()); // for parsing application/json
app.use(express.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded


app.post('/profile', (req: Request, res: Response, next: NextFunction) => {
  console.log(req.body);
  res.json(req.body);
});
```

### [req.cookies](#reqcookies)

Type:`Object`

When using [cookie-parser](https://www.npmjs.com/package/cookie-parser) middleware, this property is an object that contains cookies sent by the request. If the request contains no cookies, it defaults to `{}`.

```
// Cookie: name=tj
console.dir(req.cookies.name);
// => "tj"
```

```
console.dir(req.fresh);
// => true
```

### [req.host](#reqhost)

Type:`String`

Contains the host derived from the `Host` HTTP header.

When the [`trust proxy` setting](/en/5x/api/application/#application-settings) does not evaluate to `false`, this property will instead get the value from the `X-Forwarded-Host` header field. This header can be set by the client or by the proxy.

If there is more than one `X-Forwarded-Host` header in the request, the value of the first header is used. This includes a single header with comma-separated values, in which the first value is used.

```
// Host: "example.com:3000"
console.dir(req.host);
// => 'example.com:3000'


// Host: "[::1]:3000"
console.dir(req.host);
// => '[::1]:3000'
```

### [req.hostname](#reqhostname)

Type:`String`

Contains the hostname derived from the `Host` HTTP header.

When the [`trust proxy` setting](/en/5x/api/application/#options-for-trust-proxy-setting) does not evaluate to `false`, this property will instead get the value from the `X-Forwarded-Host` header field. This header can be set by the client or by the proxy.

If there is more than one `X-Forwarded-Host` header in the request, the value of the first header is used. This includes a single header with comma-separated values, in which the first value is used.

```
// Host: "example.com:3000"
console.dir(req.hostname);
// => 'example.com'
```

### [req.ip](#reqip)

Type:`String`

Contains the remote IP address of the request.

When the [`trust proxy` setting](/en/5x/api/application/#options-for-trust-proxy-setting) does not evaluate to `false`, the value of this property is derived from the left-most entry in the `X-Forwarded-For` header. This header can be set by the client or by the proxy.

```
console.dir(req.ip);
// => "127.0.0.1"
```

### [req.ips](#reqips)

Type:`String[]`

When the [`trust proxy` setting](/en/5x/api/application/#options-for-trust-proxy-setting) does not evaluate to `false`, this property contains an array of IP addresses specified in the `X-Forwarded-For` request header. Otherwise, it contains an empty array. This header can be set by the client or by the proxy.

For example, if `X-Forwarded-For` is `client, proxy1, proxy2`, `req.ips` would be `["client", "proxy1", "proxy2"]`, where `proxy2` is the furthest downstream.

```
// normal request, or `trust proxy` disabled (the default)
console.dir(req.ips);
// => []


// app.set('trust proxy', true) and
// request header `X-Forwarded-For: client, proxy1, proxy2`
console.dir(req.ips);
// => ['client', 'proxy1', 'proxy2']
```

### [req.method](#reqmethod)

Type:`String`

Contains a string corresponding to the HTTP method of the request: `GET`, `POST`, `PUT`, and so on.

```
app.use((req, res, next) => {
  console.dir(req.method);
  // => 'GET'
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use((req: Request, res: Response, next: NextFunction) => {
  console.dir(req.method);
  // => 'GET'
  next();
});
```

### [req.originalUrl](#reqoriginalurl)

Type:`String`

### Caution

`req.url` is not a native Express property, it is inherited from Node’s [http module](https://nodejs.org/api/http.html#messageurl).

This property is much like `req.url`; however, it retains the original request URL, allowing you to rewrite `req.url` freely for internal routing purposes. For example, the “mounting” feature of [app.use()](/en/5x/api/application/#appuse) will rewrite `req.url` to strip the mount point.

```
// GET /search?q=something
console.dir(req.originalUrl);
// => "/search?q=something"
```

`req.originalUrl` is available both in middleware and router objects, and is a combination of `req.baseUrl` and `req.url`. Consider following example:

```
// GET 'http://www.example.com/admin/new?sort=desc'
app.use('/admin', (req, res, next) => {
  console.dir(req.originalUrl); // '/admin/new?sort=desc'
  console.dir(req.baseUrl); // '/admin'
  console.dir(req.path); // '/new'
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


// GET 'http://www.example.com/admin/new?sort=desc'
app.use('/admin', (req: Request, res: Response, next: NextFunction) => {
  console.dir(req.originalUrl); // '/admin/new?sort=desc'
  console.dir(req.baseUrl); // '/admin'
  console.dir(req.path); // '/new'
  next();
});
```

### [req.params](#reqparams)

Type:`Object`

This property is an object containing properties mapped to the [named route “parameters”](/en/5x/guide/routing/#route-parameters). For example, if you have the route `/user/:name`, then the “name” property is available as `req.params.name`. This object defaults to `Object.create(null)` when using string paths, but remains a standard object with a normal prototype when the path is defined with a regular expression.

```
// GET /user/tj
console.dir(req.params.name);
// => "tj"
```

Properties corresponding to wildcard parameters are arrays containing separate path segments split on `/`:

```
app.get('/files/*file', (req, res) => {
  console.dir(req.params.file);
  // GET /files/note.txt
  // => [ 'note.txt' ]
  // GET /files/images/image.png
  // => [ 'images', 'image.png' ]
});
```

```
import { type Request, type Response } from 'express';


app.get('/files/*file', (req: Request, res: Response) => {
  console.dir(req.params.file);
  // GET /files/note.txt
  // => [ 'note.txt' ]
  // GET /files/images/image.png
  // => [ 'images', 'image.png' ]
});
```

Parameters defined in [optional segments](/en/5x/guide/routing/#optional-segments) that are not present in the request URL are omitted from `req.params` entirely.

When you use a regular expression for the route definition, capture groups are provided as integer keys using `req.params[n]`, where `n` is the nth capture group.

```
app.use(/^\/file\/(.*)$/, (req, res) => {
  // GET /file/javascripts/jquery.js
  console.dir(req.params[0]);
  // => "javascripts/jquery.js"
});
```

```
import { type Request, type Response } from 'express';


app.use(/^\/file\/(.*)$/, (req: Request, res: Response) => {
  // GET /file/javascripts/jquery.js
  console.dir(req.params[0]);
  // => "javascripts/jquery.js"
});
```

Named capturing groups in regular expressions behave like named route parameters. For example the group from `/^\/file\/(?<path>.*)$/` expression is available as `req.params.path`.

If you need to make changes to a key in `req.params`, use the [app.param](/en/5x/api/application/#appparam) handler. Changes are applicable only to [parameters](/en/5x/guide/routing/#route-parameters) already defined in the route path.

Any changes made to the `req.params` object in a middleware or route handler will be reset.

### Note

Express automatically decodes the values in `req.params` (using `decodeURIComponent`).

### [req.path](#reqpath)

Type:`String`

Contains the path part of the request URL.

```
// example.com/users?sort=desc
console.dir(req.path);
// => "/users"
```

### Note

When called from a middleware, the mount point is not included in `req.path`. See [app.use()](/en/5x/api/application/#appuse) for more details.

### [req.protocol](#reqprotocol)

Type:`String`

Contains the request protocol string: either `http` or (for TLS requests) `https`.

When the [`trust proxy` setting](/en/5x/api/application/#options-for-trust-proxy-setting) does not evaluate to `false`, this property will use the value of the `X-Forwarded-Proto` header field if present. This header can be set by the client or by the proxy.

```
console.dir(req.protocol);
// => "http"
```

### [req.query](#reqquery)

Type:`Object`

This property is an object containing a property for each query string parameter in the route. When [query parser](/en/5x/api/application/#application-settings) is set to disabled, it is an empty object `{}`, otherwise it is the result of the configured query parser.

### Warning

As `req.query`’s shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, `req.query.foo.toString()` may fail in multiple ways, for example `foo` may not be there or may not be a string, and `toString` may not be a function and instead a string or other user-input.

The value of this property can be configured with the [query parser application setting](/en/5x/api/application/#application-settings) to work how your application needs it. A very popular query string parser is the [`qs` module](https://www.npmjs.com/package/qs), and this is used by default. The `qs` module is very configurable with many settings, and it may be desirable to use different settings than the default to populate `req.query`:

index.cjs

```
const qs = require('qs');
app.set('query parser', (str) =>
  qs.parse(str, {
    /* custom options */
  })
);
```

index.mjs

```
import qs from 'qs';


app.set('query parser', (str) =>
  qs.parse(str, {
    /* custom options */
  })
);
```

index.ts

```
import qs from 'qs';


app.set('query parser', (str: string) =>
  qs.parse(str, {
    /* custom options */
  })
);
```

Check out the [query parser application setting](/en/5x/api/application/#application-settings) documentation for other customization options.

### [req.res](#reqres)

Type:`Response`

This property holds a reference to the [response object](/en/5x/api/response/) that relates to this request object.

```
app.get('/', (req, res) => {
  console.dir(req.res === res);
  // => true
  res.send('OK');
});
```

```
import { type Request, type Response } from 'express';


app.get('/', (req: Request, res: Response) => {
  console.dir(req.res === res);
  // => true
  res.send('OK');
});
```

### [req.route](#reqroute)

Type:`Route`

Contains the currently-matched route (a `Route` object). For example:

```
app.get('/user/{:id}', (req, res) => {
  console.dir(req.route, { depth: null });
  res.send('GET');
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/{:id}', (req: Request, res: Response) => {
  console.dir(req.route, { depth: null });
  res.send('GET');
});
```

Example output from the previous snippet:

```
Route {
  path: '/user/{:id}',
  stack: [
    Layer {
      handle: [Function (anonymous)],
      keys: [],
      name: '<anonymous>',
      params: undefined,
      path: undefined,
      slash: false,
      matchers: [ [Function: match] ],
      method: 'get'
    }
  ],
  methods: [Object: null prototype] { get: true }
}
```

### [req.secure](#reqsecure)

Type:`Boolean`

A Boolean property that is true if a TLS connection is established. Equivalent to the following:

```
req.protocol === 'https';
```

### [req.signedCookies](#reqsignedcookies)

Type:`Object`

When using [cookie-parser](https://www.npmjs.com/package/cookie-parser) middleware, this property contains signed cookies sent by the request, unsigned and ready for use. Signed cookies reside in a different object to show developer intent; otherwise, a malicious attack could be placed on `req.cookie` values (which are easy to spoof). Note that signing a cookie does not make it “hidden” or encrypted; but simply prevents tampering (because the secret used to sign is private).

If no signed cookies are sent, the property defaults to `{}`.

```
// Cookie: user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
console.dir(req.signedCookies.user);
// => "tobi"
```

For more information, issues, or concerns, see [cookie-parser](https://github.com/expressjs/cookie-parser).

### [req.stale](#reqstale)

Type:`Boolean`

Indicates whether the request is “stale,” and is the opposite of `req.fresh`. For more information, see [req.fresh](#reqfresh).

```
console.dir(req.stale);
// => true
```

### [req.subdomains](#reqsubdomains)

Type:`String[]`

An array of subdomains in the domain name of the request.

```
// Host: "tobi.ferrets.example.com"
console.dir(req.subdomains);
// => ["ferrets", "tobi"]
```

The application property `subdomain offset`, which defaults to 2, is used for determining the beginning of the subdomain segments. To change this behavior, change its value using [app.set](/en/5x/api/application/#appset).

### [req.xhr](#reqxhr)

Type:`Boolean`

A Boolean property that is `true` if the request’s `X-Requested-With` header field is “XMLHttpRequest”, indicating that the request was issued by a client library such as jQuery.

```
console.dir(req.xhr);
// => true
```

```
// Accept: text/html
req.accepts('html');
// => "html"


// Accept: text/*, application/json
req.accepts('html');
// => "html"
req.accepts('text/html');
// => "text/html"
req.accepts(['json', 'text']);
// => "json"
req.accepts('application/json');
// => "application/json"


// Accept: text/*, application/json
req.accepts('image/png');
req.accepts('png');
// => false


// Accept: text/*;q=.5, application/json
req.accepts(['html', 'json']);
// => "json"
```

```
// Accept-Charset: utf-8, iso-8859-1;q=0.5
req.acceptsCharsets('utf-8', 'iso-8859-1');
// => 'utf-8'


req.acceptsCharsets('us-ascii');
// => false
```

For more information, or if you have issues or concerns, see [accepts](https://github.com/expressjs/accepts).

```
// Accept-Encoding: gzip, deflate
req.acceptsEncodings('gzip', 'deflate');
// => 'gzip'


req.acceptsEncodings('br');
// => false
```

For more information, or if you have issues or concerns, see [accepts](https://github.com/expressjs/accepts).

```
// Accept-Language: en;q=0.8, es
req.acceptsLanguages('en', 'es');
// => 'es'


req.acceptsLanguages();
// => ['es', 'en']
```

For more information, or if you have issues or concerns, see [accepts](https://github.com/expressjs/accepts).

Express (5.x) source: [request.js line 172](https://github.com/expressjs/express/blob/v5.1.0/lib/request.js#L172)

Accepts (2.0) source: [index.js line 195](https://github.com/jshttp/accepts/blob/2.0.0/index.js#L195)

```
req.get('Content-Type');
// => "text/plain"


req.get('content-type');
// => "text/plain"


req.get('Something');
// => undefined
```

```
// With Content-Type: text/html; charset=utf-8
req.is('html'); // => 'html'
req.is('text/html'); // => 'text/html'
req.is('text/*'); // => 'text/*'


// When Content-Type is application/json
req.is('json'); // => 'json'
req.is('application/json'); // => 'application/json'
req.is('application/*'); // => 'application/*'


// Using arrays
// When Content-Type is application/json
req.is(['json', 'html']); // => 'json'


// Using multiple arguments
// When Content-Type is application/json
req.is('json', 'html'); // => 'json'


req.is('html'); // => false
req.is(['xml', 'yaml']); // => false
req.is('xml', 'yaml'); // => false
```

For more information, or if you have issues or concerns, see [type-is](https://github.com/expressjs/type-is).

```
// parse header from request
const range = req.range(1000);


// the type of the range
if (range.type === 'bytes') {
  // the ranges
  range.forEach((r) => {
    // do something with r.start and r.end
  });
}
```

----
url: https://expressjs.com/en/5x/api
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/5x/api.mdx)

# [5.x API Reference](#overview)

This section provides an overview of the modules and APIs available in Express 5.x for building web applications and HTTP services.

index.cjs

```
const express = require('express');
const app = express();


app.get('/', (req, res) => {
  res.send('hello world');
});


app.listen(3000);
```

index.mjs

```
import express from 'express';


const app = express();


app.get('/', (req, res) => {
  res.send('hello world');
});


app.listen(3000);
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


app.get('/', (req: Request, res: Response) => {
  res.send('hello world');
});


app.listen(3000);
```

### Note

Express 5.x requires **Node.js 18 or higher**.

With express v5.x, you can define routes, configure middleware, and start handling HTTP requests using the application instance created by the `express()` function. The API is organized into the following sections:

### [express()](/en/5x/api/express/)

[Learn about the express() function, which creates an Express application.](/en/5x/api/express/)

### [Application Object](/en/5x/api/application/)

[Learn about the properties and methods of the Express 5.x application object.](/en/5x/api/application/)

### [Request Object](/en/5x/api/request/)

[Learn about the properties and methods of the Express 5.x request object.](/en/5x/api/request/)

### [Response Object](/en/5x/api/response/)

[Learn about the properties and methods of the Express 5.x response object.](/en/5x/api/response/)

### [Router](/en/5x/api/router/)

[Learn about the properties and methods of the Express 5.x router.](/en/5x/api/router/)

----
url: https://expressjs.com/en/blog/2024-10-01-herodevs-partnership-announcement
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2024-10-01-herodevs-partnership-announcement)

announcements

# [Express Never Ending Support Launched by HeroDevs and Express.js](#overview)

Express Technical CommitteeOctober 1, 2024

[](https://x.com/intent/tweet?text=Express%20Never%20Ending%20Support%20Launched%20by%20HeroDevs%20and%20Express.js\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-10-01-herodevs-partnership-announcement%2F)[](https://bsky.app/intent/compose?text=Express%20Never%20Ending%20Support%20Launched%20by%20HeroDevs%20and%20Express.js%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-10-01-herodevs-partnership-announcement%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-10-01-herodevs-partnership-announcement%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-10-01-herodevs-partnership-announcement%2F\&text=Express%20Never%20Ending%20Support%20Launched%20by%20HeroDevs%20and%20Express.js)[](https://wa.me/?text=Express%20Never%20Ending%20Support%20Launched%20by%20HeroDevs%20and%20Express.js%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-10-01-herodevs-partnership-announcement%2F)[](/feed.xml)

The Express.js team is pleased to announce a partnership with HeroDevs to launch [Express Never-Ending Support (NES)](https://www.herodevs.com/support/express-nes), providing long-term support for applications built with legacy Express. This collaboration ensures that developers relying on older versions of the framework will continue to receive critical security and compatibility updates, allowing them to maintain and scale their applications securely, even after the framework’s official end-of-life.

Express.js is known for its minimalistic design and flexibility, offering developers a powerful yet lightweight framework for building web and mobile applications. Its extensive set of HTTP utility methods and middleware have made creating APIs both efficient and scalable—qualities that have made it a go-to choice for Node.js developers over the years.

However, Express.js v3.x reached its end-of-life in July 2015, leaving many businesses and developers in need of support to keep their applications secure and compliant.

> “We’re grateful to see HeroDevs stepping in to provide extended long-term support for Express
>
> Express NES ensures that the many businesses and developers who rely on Express can continue using it safely and securely, even years after its original end-of-life. This kind of ongoing commitment to the open-source ecosystem is crucial, and we’re excited to see the benefits it brings to the developer community.” — said a spokesperson for the Express Technical Committee.

Express NES is designed as a drop-in replacement for legacy versions of Express.js, offering security patches, compatibility updates and compliance fixes. This solution ensures that developers can remain on legacy Express.js without becoming vulnerable to security risks and compliance issues.

> “We’re thrilled to introduce Express NES as part of our continued mission to support the sustainability of key open-source tools
>
> Our partnership with OpenJS has enabled us to meet the needs of developers still relying on older versions of critical frameworks. Express NES ensures that they can continue building and maintaining their applications without the risk of security vulnerabilities or loss of compliance.” — Joe Eames, VP of Partnership at HeroDevs.

For more information on Express NES and how to get started, visit [HeroDevs’ website](https://www.herodevs.com/support/express-nes).

----
url: https://expressjs.com/en/resources/middleware/
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/index.mdx)

# [Express middleware](#overview)

The Express middleware modules listed here are maintained by the [Expressjs team](https://github.com/orgs/expressjs/people).

| Middleware module                                            | Description                                                                                         |
| ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------- |
| [body-parser](/en/resources/middleware/body-parser/)         | Parse HTTP request body.                                                                            |
| [compression](/en/resources/middleware/compression/)         | Compress HTTP responses.                                                                            |
| [cookie-parser](/en/resources/middleware/cookie-parser/)     | Parse cookie header and populate `req.cookies`. See also [cookies](https://github.com/jed/cookies). |
| [cookie-session](/en/resources/middleware/cookie-session/)   | Establish cookie-based sessions.                                                                    |
| [cors](/en/resources/middleware/cors/)                       | Enable cross-origin resource sharing (CORS) with various options.                                   |
| [errorhandler](/en/resources/middleware/errorhandler/)       | Development error-handling/debugging.                                                               |
| [method-override](/en/resources/middleware/method-override/) | Override HTTP methods using header.                                                                 |
| [morgan](/en/resources/middleware/morgan/)                   | HTTP request logger.                                                                                |
| [multer](/en/resources/middleware/multer/)                   | Handle multi-part form data.                                                                        |
| [response-time](/en/resources/middleware/response-time/)     | Record HTTP response time.                                                                          |
| [serve-favicon](/en/resources/middleware/serve-favicon/)     | Serve a favicon.                                                                                    |
| [serve-index](/en/resources/middleware/serve-index/)         | Serve directory listing for a given path.                                                           |
| [serve-static](/en/resources/middleware/serve-static/)       | Serve static files.                                                                                 |
| [session](/en/resources/middleware/session/)                 | Establish server-based sessions (development only).                                                 |
| [timeout](/en/resources/middleware/timeout/)                 | Set a timeout period for HTTP request processing.                                                   |
| [vhost](/en/resources/middleware/vhost/)                     | Create virtual domains.                                                                             |

## [Additional middleware modules](#additional-middleware-modules)

These are some additional popular middleware modules.

### Warning

This information refers to third-party sites, products, or modules that are not maintained by the Expressjs team. Listing here does not constitute an endorsement or recommendation from the Expressjs project team.

| Middleware module                                   | Description                                                                                                                                  |
| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| [helmet](https://github.com/helmetjs/helmet)        | Helps secure your apps by setting various HTTP headers.                                                                                      |
| [passport](https://github.com/jaredhanson/passport) | Authentication using “strategies” such as OAuth, OpenID and many others. See [passportjs.org](https://passportjs.org/) for more information. |

----
url: https://expressjs.com/en/blog/2025-07-31-security-releases
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2025-07-31-security-releases)

security

# [July 2025 Security Releases](#overview)

Ulises GascónJuly 31, 2025

[](https://x.com/intent/tweet?text=July%202025%20Security%20Releases\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-07-31-security-releases%2F)[](https://bsky.app/intent/compose?text=July%202025%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-07-31-security-releases%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-07-31-security-releases%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-07-31-security-releases%2F\&text=July%202025%20Security%20Releases)[](https://wa.me/?text=July%202025%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-07-31-security-releases%2F)[](/feed.xml)

The Express team has released a new patch version of [Multer](https://www.npmjs.com/package/multer) addressing a high-severity security vulnerability, and a new minor version of [on-headers](https://www.npmjs.com/package/on-headers) addressing a low-severity security vulnerability.

### Warning

We recommend upgrading to the latest version of Multer and On-headers immediately to secure your applications.

The following vulnerabilities have been addressed:

* [High severity vulnerability CVE-2025-7338 in Multer middleware](#high-severity-vulnerability-cve-2025-7338-in-multer-middleware)
* [Low severity vulnerability CVE-2025-7339 in On-header middleware](#low-severity-vulnerability-cve-2025-7339-in-on-header-middleware)

## [High severity vulnerability CVE-2025-7338 in Multer middleware](#high-severity-vulnerability-cve-2025-7338-in-multer-middleware)

**[Multer](https://www.npmjs.com/package/multer) versions `>=1.4.4-lts.1` and `<2.0.2` are vulnerable to denial of service via unhandled exception from malformed request.**

This request causes an unhandled exception, leading to a crash of the process.

**Affected versions**: `>=1.4.4-lts.1, <2.0.2`\
**Patched version**: `2.0.2`

For more details, see [GHSA-fjgf-rc76-4x9p](https://github.com/expressjs/multer/security/advisories/GHSA-fjgf-rc76-4x9p).

## [Low severity vulnerability CVE-2025-7339 in On-header middleware](#low-severity-vulnerability-cve-2025-7339-in-on-header-middleware)

**[On-headers](https://www.npmjs.com/package/on-headers) versions `<1.1.0` is vulnerable to http response header manipulation**

A bug in on-headers versions `<1.1.0` may result in response headers being inadvertently modified when an array is passed to `response.writeHead()`

**Affected versions**: `<1.1.0`\
**Patched version**: `1.1.0`

For more details, see [GHSA-76c9-3jph-rj3q](https://github.com/jshttp/on-headers/security/advisories/GHSA-76c9-3jph-rj3q).

***

We recommend upgrading to the latest version of Multer and On-headers immediately to secure your applications.

----
url: https://expressjs.com/en/blog/2025-05-19-security-releases
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2025-05-19-security-releases)

security

# [May 2025 Security Releases](#overview)

Ulises GascónMay 19, 2025

[](https://x.com/intent/tweet?text=May%202025%20Security%20Releases\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-05-19-security-releases%2F)[](https://bsky.app/intent/compose?text=May%202025%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-05-19-security-releases%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-05-19-security-releases%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-05-19-security-releases%2F\&text=May%202025%20Security%20Releases)[](https://wa.me/?text=May%202025%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-05-19-security-releases%2F)[](/feed.xml)

The Express team has released a new major version of [Multer](https://www.npmjs.com/package/multer) addressing two high-severity security vulnerabilities. This update improves the reliability and security of handling file uploads in Express applications.

### Warning

We strongly recommend that you upgrade to Multer v2.0.0 or later as soon as possible.

The following vulnerabilities have been addressed:

* [High severity vulnerability CVE-2025-47935 in Multer middleware](#high-severity-vulnerability-cve-2025-47935-in-multer-middleware)
* [High severity vulnerability CVE-2025-47944 in Multer middleware](#high-severity-vulnerability-cve-2025-47944-in-multer-middleware)

## [High severity vulnerability CVE-2025-47935 in Multer middleware](#high-severity-vulnerability-cve-2025-47935-in-multer-middleware)

**[Multer](https://www.npmjs.com/package/multer) versions `<2.0.0` are vulnerable to denial of service due to a memory leak caused by improper stream handling.**

When the HTTP request stream emits an error, the internal `busboy` stream is not closed, violating Node.js stream safety guidance.

This leads to unclosed streams accumulating over time, consuming memory and file descriptors. Under sustained or repeated failure conditions, this can result in denial of service, requiring manual server restarts to recover. All users of Multer handling file uploads are potentially impacted.

**Affected versions**: `<2.0.0`\
**Patched version**: `>=2.0.0`

For more details, see [GHSA-44fp-w29j-9vj5](https://github.com/expressjs/multer/security/advisories/GHSA-44fp-w29j-9vj5).

## [High severity vulnerability CVE-2025-47944 in Multer middleware](#high-severity-vulnerability-cve-2025-47944-in-multer-middleware)

**[Multer](https://www.npmjs.com/package/multer) versions `>=1.4.4-lts.1` and `<2.0.0` are vulnerable to a denial of service via a malformed multipart request.**

A specially crafted request can cause an unhandled exception inside Multer, resulting in a crash of the server process.

**Affected versions**: `>=1.4.4-lts.1` and `<2.0.0`\
**Patched version**: `>=2.0.0`

For more details, see [GHSA-4pg4-qvpc-4q3h](https://github.com/expressjs/multer/security/advisories/GHSA-4pg4-qvpc-4q3h).

***

**Multer v2.0.0** also introduces a breaking change:

* The minimum supported Node.js version is now **10.16.0**.

We recommend upgrading to the latest version of Multer immediately to secure your applications.

----
url: https://expressjs.com/en/3x/api/application
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/3x/api/application/index.mdx)

# [Application Object](#overview)

The `app` object conventionally denotes the Express application. Create it by calling the top-level `express()` function exported by the Express module:

```
var express = require('express');
var app = express();


app.get('/', function (req, res) {
  res.send('hello world');
});


app.listen(3000);
```

## [Properties](#properties)

### [app.locals](#applocals)

Application local variables are provided to all templates rendered within the application. This is useful for providing helper functions to templates, as well as app-level data.

```
app.locals.title = 'My App';
app.locals.strftime = require('strftime');
```

The `app.locals` object is a JavaScript `Function`, which when invoked with an object will merge properties into itself, providing a simple way to expose existing objects as local variables.

```
app.locals({
  title: 'My App',
  phone: '1-250-858-9990',
  email: 'me@myapp.com',
});


console.log(app.locals.title);
// => 'My App'


console.log(app.locals.email);
// => 'me@myapp.com'
```

A consequence of the `app.locals` Object being ultimately a Javascript Function Object is that you must not reuse existing (native) named properties for your own variable names, such as `name, apply, bind, call, arguments, length, constructor`.

```
app.locals({ name: 'My App' });


console.log(app.locals.name);
// => return 'app.locals' in place of 'My App' (app.locals is a Function !)
// => if name's variable is used in a template, a ReferenceError will be returned.
```

The full list of native named properties can be found in many specifications. The [JavaScript specification](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference) introduced original properties, some of which still recognized by modern engines, and the [EcmaScript specification](https://262.ecma-international.org/5.1/) then built on it and normalized the set of properties, adding new ones and removing deprecated ones. Check out properties for Functions and Objects if interested.

By default Express exposes only a single app-level local variable, `settings`.

```
app.set('title', 'My App');
// use settings.title in a view
```

### [app.routes](#approutes)

The `app.routes` object houses all of the routes defined mapped by the associated HTTP verb. This object may be used for introspection capabilities, for example Express uses this internally not only for routing but to provide default

OPTIONS behavior unless `app.options()` is used. Your application or framework may also remove routes by simply by removing them from this object.

The output of `console.log(app.routes)`:

```
{ get:
   [ { path: '/',
       method: 'get',
       callbacks: [Object],
       keys: [],
       regexp: /^\/\/?$/i },
     { path: '/user/:id',
       method: 'get',
       callbacks: [Object],
       keys: [{ name: 'id', optional: false }],
       regexp: /^\/user\/(?:([^\/]+?))\/?$/i } ],
  delete:
   [ { path: '/user/:id',
       method: 'delete',
       callbacks: [Object],
       keys: [Object],
       regexp: /^\/user\/(?:([^\/]+?))\/?$/i } ] }
```

### [settings](#settings)

The following settings are provided to alter how Express will behave:

* `env` Environment mode, defaults to process.env.NODE\_ENV or “development”
* `trust proxy` Enables reverse proxy support, disabled by default
* `jsonp callback name` Changes the default callback name of ?callback=
* `json replacer` JSON replacer callback, null by default
* `json spaces` JSON response spaces for formatting, defaults to 2 in development, 0 in production
* `case sensitive routing` Enable case sensitivity, disabled by default, treating “/Foo” and “/foo” as the same
* `strict routing` Enable strict routing, by default “/foo” and “/foo/” are treated the same by the router
* `view cache` Enables view template compilation caching, enabled in production by default
* `view engine` The default engine extension to use when omitted
* `views` The view directory path, defaulting to “process.cwd() + ‘/views‘“

## [Methods](#methods)

### [app.set(name, value)](#appsetname-value)

Assigns setting `name` to `value`.

```
app.set('title', 'My Site');
app.get('title');
// => "My Site"
```

### [app.get(name)](#appgetname)

Get setting `name` value.

```
app.get('title');
// => undefined


app.set('title', 'My Site');
app.get('title');
// => "My Site"
```

### [app.enable(name)](#appenablename)

Set setting `name` to `true`.

```
app.enable('trust proxy');
app.get('trust proxy');
// => true
```

### [app.disable(name)](#appdisablename)

Set setting `name` to `false`.

```
app.disable('trust proxy');
app.get('trust proxy');
// => false
```

### [app.enabled(name)](#appenabledname)

Check if setting `name` is enabled.

```
app.enabled('trust proxy');
// => false


app.enable('trust proxy');
app.enabled('trust proxy');
// => true
```

### [app.disabled(name)](#appdisabledname)

Check if setting `name` is disabled.

```
app.disabled('trust proxy');
// => true


app.enable('trust proxy');
app.disabled('trust proxy');
// => false
```

### [app.configure(\[env\], callback)](#appconfigureenv-callback)

Conditionally invoke `callback` when `env` matches `app.get('env')`, aka `process.env.NODE_ENV`. This method remains for legacy reasons, and is effectively an `if` statement as illustrated in the following snippets. These functions are *not* required in order to use `app.set()` and other configuration methods.

```
// all environments
app.configure(function () {
  app.set('title', 'My Application');
});


// development only
app.configure('development', function () {
  app.set('db uri', 'localhost/dev');
});


// production only
app.configure('production', function () {
  app.set('db uri', 'n.n.n.n/prod');
});
```

Is effectively sugar for:

```
// all environments
app.set('title', 'My Application');


// development only
if (app.get('env') === 'development') {
  app.set('db uri', 'localhost/dev');
}


// production only
if (app.get('env') === 'production') {
  app.set('db uri', 'n.n.n.n/prod');
}
```

### [app.use(\[path\], function)](#appusepath-function)

Use the given middleware `function`, with optional mount `path`, defaulting to ”/”.

```
var express = require('express');
var app = express();


// simple logger
app.use(function (req, res, next) {
  console.log('%s %s', req.method, req.url);
  next();
});


// respond
app.use(function (req, res, next) {
  res.send('Hello World');
});


app.listen(3000);
```

The “mount” path is stripped and is **not** visible to the middleware `function`. The main effect of this feature is that mounted middleware may operate without code changes regardless of its “prefix” pathname.

### Caution

A route will match any path that follows its path immediately with either a “`/`” or a “`.`”. For example: `app.use('/apple', ...)` will match */apple*, */apple/images*, */apple/images/news*, */apple.html*, */apple.html.txt*, and so on.

Here’s a concrete example, take the typical use-case of serving files in ./public using the `express.static()` middleware:

```
// GET /javascripts/jquery.js
// GET /style.css
// GET /favicon.ico
app.use(express.static(path.join(__dirname, 'public')));
```

Say for example you wanted to prefix all static files with “/static”, you could use the “mounting” feature to support this. Mounted middleware functions are *not* invoked unless the `req.url` contains this prefix, at which point it is stripped when the function is invoked. This affects this function only, subsequent middleware will see `req.url` with “/static” included unless they are mounted as well.

```
// GET /static/javascripts/jquery.js
// GET /static/style.css
// GET /static/favicon.ico
app.use('/static', express.static(path.join(__dirname, 'public')));
```

The order of which middleware are “defined” using `app.use()` is very important, they are invoked sequentially, thus this defines middleware precedence. For example usually `express.logger()` is the very first middleware you would use, logging every request:

```
app.use(express.logger());
app.use(express.static(path.join(__dirname, 'public')));
app.use(function (req, res) {
  res.send('Hello');
});
```

Now suppose you wanted to ignore logging requests for static files, but to continue logging routes and middleware defined after `logger()`, you would simply move `static()` above:

```
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.logger());
app.use(function (req, res) {
  res.send('Hello');
});
```

Another concrete example would be serving files from multiple directories, giving precedence to ”./public” over the others:

```
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'files')));
app.use(express.static(path.join(__dirname, 'uploads')));
```

### [app.engine(ext, callback)](#appengineext-callback)

Register the given template engine `callback` as `ext`

By default will `require()` the engine based on the file extension. For example if you try to render a “foo.jade” file Express will invoke the following internally, and cache the `require()` on subsequent calls to increase performance.

```
app.engine('jade', require('jade').__express);
```

For engines that do not provide `.__express` out of the box - or if you wish to “map” a different extension to the template engine you may use this method. For example mapping the EJS template engine to “.html” files:

```
app.engine('html', require('ejs').renderFile);
```

In this case EJS provides a `.renderFile()` method with the same signature that Express expects: `(path, options, callback)`, though note that it aliases this method as `ejs.__express` internally so if you’re using “.ejs” extensions you don’t need to do anything.

Some template engines do not follow this convention, the

[consolidate.js](https://github.com/visionmedia/consolidate.js) library was created to map all of node’s popular template engines to follow this convention, thus allowing them to work seamlessly within Express.

```
var engines = require('consolidate');
app.engine('haml', engines.haml);
app.engine('html', engines.hogan);
```

### [app.param(\[name\], callback)](#appparamname-callback)

Map logic to route parameters. For example when `:user` is present in a route path you may map user loading logic to automatically provide `req.user` to the route, or perform validations on the parameter input.

The following snippet illustrates how the `callback` is much like middleware, thus supporting async operations, however providing the additional value of the parameter, here named as `id`. An attempt to load the user is then performed, assigning `req.user`, otherwise passing an error to `next(err)`.

```
app.param('user', function (req, res, next, id) {
  User.find(id, function (err, user) {
    if (err) {
      next(err);
    } else if (user) {
      req.user = user;
      next();
    } else {
      next(new Error('failed to load user'));
    }
  });
});
```

Alternatively you may pass only a `callback`, in which case you have the opportunity to alter the `app.param()` API. For example the [express-params](http://github.com/expressjs/express-params) defines the following callback which allows you to restrict parameters to a given regular expression.

This example is a bit more advanced, checking if the second argument is a regular expression, returning the callback which acts much like the “user” param example.

```
app.param(function (name, fn) {
  if (fn instanceof RegExp) {
    return function (req, res, next, val) {
      var captures;
      if ((captures = fn.exec(String(val)))) {
        req.params[name] = captures;
        next();
      } else {
        next('route');
      }
    };
  }
});
```

The method could now be used to effectively validate parameters, or also parse them to provide capture groups:

```
app.param('id', /^\d+$/);


app.get('/user/:id', function (req, res) {
  res.send('user ' + req.params.id);
});


app.param('range', /^(\w+)\.\.(\w+)?$/);


app.get('/range/:range', function (req, res) {
  var range = req.params.range;
  res.send('from ' + range[1] + ' to ' + range[2]);
});
```

### [app.VERB(path, \[callback…\], callback)](#appverbpath-callback-callback)

The `app.VERB()` methods provide the routing functionality in Express, where **VERB** is one of the HTTP verbs, such as `app.post()`. Multiple callbacks may be given, all are treated equally, and behave just like middleware, with the one exception that these callbacks may invoke `next('route')` to bypass the remaining route callback(s). This mechanism can be used to perform pre-conditions on a route then pass control to subsequent routes when there is no reason to proceed with the route matched.

The following snippet illustrates the most simple route definition possible. Express translates the path strings to regular expressions, used internally to match incoming requests. Query strings are *not* considered when performing these matches, for example “GET /” would match the following route, as would “GET /?name=tobi”.

```
app.get('/', function (req, res) {
  res.send('hello world');
});
```

Regular expressions may also be used, and can be useful if you have very specific restraints, for example the following would match “GET /commits/71dbb9c” as well as “GET /commits/71dbb9c..4c084f9”.

```
app.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/, function (req, res) {
  var from = req.params[0];
  var to = req.params[1] || 'HEAD';
  res.send('commit range ' + from + '..' + to);
});
```

Several callbacks may also be passed, useful for re-using middleware that load resources, perform validations, etc.

```
app.get('/user/:id', user.load, function () {
  // ...
});
```

These callbacks may be passed within arrays as well, these arrays are simply flattened when passed:

```
var middleware = [loadForum, loadThread];


app.get('/forum/:fid/thread/:tid', middleware, function () {
  // ...
});


app.post('/forum/:fid/thread/:tid', middleware, function () {
  // ...
});
```

### [app.all(path, \[callback…\], callback)](#appallpath-callback-callback)

This method functions just like the `app.VERB()` methods, however it matches all HTTP verbs.

This method is extremely useful for mapping “global” logic for specific path prefixes or arbitrary matches. For example if you placed the following route at the top of all other route definitions, it would require that all routes from that point on would require authentication, and automatically load a user. Keep in mind that these callbacks do not have to act as end points, `loadUser` can perform a task, then `next()` to continue matching subsequent routes.

```
app.all('*', requireAuthentication, loadUser);
```

Or the equivalent:

```
app.all('*', requireAuthentication);
app.all('*', loadUser);
```

Another great example of this is white-listed “global” functionality. Here the example is much like before, however only restricting paths prefixed with “/api”:

```
app.all('/api/*', requireAuthentication);
```

### [app.render(view, \[options\], callback)](#apprenderview-options-callback)

Render a `view` with a callback responding with the rendered string. This is the app-level variant of `res.render()`, and otherwise behaves the same way.

```
app.render('email', function (err, html) {
  // ...
});


app.render('email', { name: 'Tobi' }, function (err, html) {
  // ...
});
```

### [app.listen()](#applisten)

Bind and listen for connections on the given host and port, this method is identical to node’s [http.Server#listen()](https://nodejs.org/api/http.html#serverlisten).

```
var express = require('express');
var app = express();
app.listen(3000);
```

The `app` returned by `express()` is in fact a JavaScript `Function`, designed to be passed to node’s http servers as a callback to handle requests. This allows you to provide both HTTP and HTTPS versions of your app with the same codebase easily, as the app does not inherit from these, it is simply a callback:

```
var express = require('express');
var https = require('https');
var http = require('http');
var app = express();


http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
```

The `app.listen()` method is simply a convenience method defined as, if you wish to use HTTPS or provide both, use the technique above.

```
app.listen = function () {
  var server = http.createServer(this);
  return server.listen.apply(server, arguments);
};
```

----
url: https://expressjs.com/en/guide/migrating-5
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/guide/migrating-5.mdx)

# [Upgrade to Express v5](#overview)

Express 5 is not very different from Express 4; although it maintains the same basic API, there are still changes that break compatibility with the previous version. Therefore, an application built with Express 4 might not work if you update it to use Express 5.

## [Installation](#installation)

To install this version, you need to have a **Node.js version 18 or higher**. Then, execute the following command in your application directory:

Terminal window

```
npm install "express@5"
```

Terminal window

```
yarn add "express@5"
```

Terminal window

```
pnpm add "express@5"
```

Terminal window

```
bun add "express@5"
```

You can then run your automated tests to see what fails, and fix problems according to the updates listed below. After addressing test failures, run your app to see what errors occur. You’ll find out right away if the app uses any methods or properties that are not supported.

## [Express 5 Codemods](#express-5-codemods)

To help you migrate your express server, we have created a set of codemods that will help you automatically update your code to the latest version of Express.

Run the following command for run all the codemods available:

Terminal window

```
npx codemod@latest @expressjs/v5-migration-recipe
```

Terminal window

```
yarn dlx codemod@latest @expressjs/v5-migration-recipe
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/v5-migration-recipe
```

Terminal window

```
bunx codemod@latest @expressjs/v5-migration-recipe
```

If you want to run a specific codemod, you can run the following command:

Terminal window

```
npx codemod@latest @expressjs/name-of-the-codemod
```

Terminal window

```
yarn dlx codemod@latest @expressjs/name-of-the-codemod
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/name-of-the-codemod
```

Terminal window

```
bunx codemod@latest @expressjs/name-of-the-codemod
```

You can find the list of available codemods [here](https://codemod.link/express).

## [Removed methods and properties](#removed-methods-and-properties)

If you use any of these methods or properties in your app, it will crash. So, you’ll need to change your app after you update to version 5.

### [app.del()](#appdel)

Express 5 no longer supports the `app.del()` function. If you use this function, an error is thrown. For registering HTTP DELETE routes, use the `app.delete()` function instead.

Initially, `del` was used instead of `delete`, because `delete` is a reserved keyword in JavaScript. However, as of ECMAScript 6, `delete` and other reserved keywords can legally be used as property names.

#### [How to update](#how-to-update)

You can automatically update your code by running the following command:

Terminal window

```
npx codemod@latest @expressjs/route-del-to-delete
```

Terminal window

```
yarn dlx codemod@latest @expressjs/route-del-to-delete
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/route-del-to-delete
```

Terminal window

```
bunx codemod@latest @expressjs/route-del-to-delete
```

Or you can update your code manually:

```
app.del('/user/:id', (req, res) => {
app.delete('/user/:id', (req, res) => {
  res.send(`DELETE /user/${req.params.id}`);
});
```

### [app.param(fn)](#appparamfn)

The `app.param(fn)` signature was used for modifying the behavior of the `app.param(name, fn)` function. It has been deprecated since v4.11.0, and Express 5 no longer supports it at all.

### [Pluralized method names](#pluralized-method-names)

The following method names have been pluralized. In Express 4, using the old methods resulted in a deprecation warning. Express 5 no longer supports them at all:

`req.acceptsCharset()` is replaced by `req.acceptsCharsets()`.

`req.acceptsEncoding()` is replaced by `req.acceptsEncodings()`.

`req.acceptsLanguage()` is replaced by `req.acceptsLanguages()`.

#### [How to update](#how-to-update-1)

You can automatically update your code by running the following command:

Terminal window

```
npx codemod@latest @expressjs/pluralize-method-names
```

Terminal window

```
yarn dlx codemod@latest @expressjs/pluralize-method-names
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/pluralize-method-names
```

Terminal window

```
bunx codemod@latest @expressjs/pluralize-method-names
```

Or you can update your code manually:

```
app.all('/', (req, res) => {
  req.acceptsCharset('utf-8');
  req.acceptsEncoding('br');
  req.acceptsLanguage('en');
  req.acceptsCharsets('utf-8');
  req.acceptsEncodings('br');
  req.acceptsLanguages('en');


  // ...
});
```

### [Leading colon (:) in the name for app.param(name, fn)](#leading-colon--in-the-name-for-appparamname-fn)

A leading colon character (:) in the name for the `app.param(name, fn)` function is a remnant of Express 3, and for the sake of backwards compatibility, Express 4 supported it with a deprecation notice. Express 5 will silently ignore it and use the name parameter without prefixing it with a colon.

This should not affect your code if you follow the Express 4 documentation of [app.param](/en/4x/api/application/#appparam), as it makes no mention of the leading colon.

### [req.param(name)](#reqparamname)

This potentially confusing and dangerous method of retrieving form data has been removed. You will now need to specifically look for the submitted parameter name in the `req.params`, `req.body`, or `req.query` object.

#### [How to update](#how-to-update-2)

You can automatically update your code by running the following command:

Terminal window

```
npx codemod@latest @expressjs/explicit-request-params
```

Terminal window

```
yarn dlx codemod@latest @expressjs/explicit-request-params
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/explicit-request-params
```

Terminal window

```
bunx codemod@latest @expressjs/explicit-request-params
```

Or you can update your code manually:

```
app.post('/user', (req, res) => {
  const id = req.param('id');
  const body = req.param('body');
  const query = req.param('query');
  const id = req.params.id;
  const body = req.body;
  const query = req.query;


  // ...
});
```

### [res.json(obj, status)](#resjsonobj-status)

Express 5 no longer supports the signature `res.json(obj, status)`. Instead, set the status and then chain it to the `res.json()` method like this: `res.status(status).json(obj)`.

#### [How to update](#how-to-update-3)

You can automatically update your code by running the following command:

Terminal window

```
npx codemod@latest @expressjs/status-send-order
```

Terminal window

```
yarn dlx codemod@latest @expressjs/status-send-order
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/status-send-order
```

Terminal window

```
bunx codemod@latest @expressjs/status-send-order
```

Or you can update your code manually:

```
app.post('/user', (req, res) => {
  res.json({ name: 'Ruben' }, 201);
  res.status(201).json({ name: 'Ruben' });
});
```

### [res.jsonp(obj, status)](#resjsonpobj-status)

Express 5 no longer supports the signature `res.jsonp(obj, status)`. Instead, set the status and then chain it to the `res.jsonp()` method like this: `res.status(status).jsonp(obj)`.

#### [How to update](#how-to-update-4)

You can automatically update your code by running the following command:

Terminal window

```
npx codemod@latest @expressjs/status-send-order
```

Terminal window

```
yarn dlx codemod@latest @expressjs/status-send-order
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/status-send-order
```

Terminal window

```
bunx codemod@latest @expressjs/status-send-order
```

Or you can update your code manually:

```
app.post('/user', (req, res) => {
  res.jsonp({ name: 'Ruben' }, 201);
  res.status(201).jsonp({ name: 'Ruben' });
});
```

### [res.redirect(url, status)](#resredirecturl-status)

Express 5 no longer supports the signature `res.redirect(url, status)`. Instead, use the following signature: `res.redirect(status, url)`.

#### [How to update](#how-to-update-5)

You can automatically update your code by running the following command:

Terminal window

```
npx codemod@latest @expressjs/redirect-arg-order
```

Terminal window

```
yarn dlx codemod@latest @expressjs/redirect-arg-order
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/redirect-arg-order
```

Terminal window

```
bunx codemod@latest @expressjs/redirect-arg-order
```

Or you can update your code manually:

```
app.get('/user', (req, res) => {
  res.redirect('/users', 302);
  res.redirect(302, '/users');
});


// A redirect that relies on the default 302 status is unaffected
app.get('/admin', (req, res) => {
  res.redirect('/dashboard');
});
```

### [res.redirect(‘back’) and res.location(‘back’)](#resredirectback-and-reslocationback)

Express 5 no longer supports the magic string `back` in the `res.redirect()` and `res.location()` methods. Instead, use the `req.get('Referrer') || '/'` value to redirect back to the previous page. In Express 4, the `res.redirect('back')` and `res.location('back')` methods were deprecated.

#### [How to update](#how-to-update-6)

You can automatically update your code by running the following command:

Terminal window

```
npx codemod@latest @expressjs/back-redirect-deprecated
```

Terminal window

```
yarn dlx codemod@latest @expressjs/back-redirect-deprecated
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/back-redirect-deprecated
```

Terminal window

```
bunx codemod@latest @expressjs/back-redirect-deprecated
```

Or you can update your code manually:

```
app.get('/user', (req, res) => {
  res.redirect('back');
  res.redirect(req.get('Referrer') || '/');
});
```

### [res.send(body, status)](#ressendbody-status)

Express 5 no longer supports the signature `res.send(obj, status)`. Instead, set the status and then chain it to the `res.send()` method like this: `res.status(status).send(obj)`.

#### [How to update](#how-to-update-7)

You can automatically update your code by running the following command:

Terminal window

```
npx codemod@latest @expressjs/status-send-order
```

Terminal window

```
yarn dlx codemod@latest @expressjs/status-send-order
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/status-send-order
```

Terminal window

```
bunx codemod@latest @expressjs/status-send-order
```

Or you can update your code manually:

```
app.get('/user', (req, res) => {
  res.send({ name: 'Ruben' }, 200);
  res.status(200).send({ name: 'Ruben' });
});
```

### [res.send(status)](#ressendstatus)

Express 5 no longer supports the signature `res.send(status)`, where `status` is a number. Instead, use the `res.sendStatus(statusCode)` function, which sets the HTTP response header status code and sends the text version of the code: “Not Found”, “Internal Server Error”, and so on. If you need to send a number by using the `res.send()` function, quote the number to convert it to a string, so that Express does not interpret it as an attempt to use the unsupported old signature.

#### [How to update](#how-to-update-8)

You can automatically update your code by running the following command:

Terminal window

```
npx codemod@latest @expressjs/status-send-order
```

Terminal window

```
yarn dlx codemod@latest @expressjs/status-send-order
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/status-send-order
```

Terminal window

```
bunx codemod@latest @expressjs/status-send-order
```

Or you can update your code manually:

```
app.get('/user', (req, res) => {
  res.send(200);
  res.sendStatus(200);
});
```

### [res.sendfile()](#ressendfile)

The `res.sendfile()` function has been replaced by a camel-cased version `res.sendFile()` in Express 5.

#### [How to update](#how-to-update-9)

You can automatically update your code by running the following command:

Terminal window

```
npx codemod@latest @expressjs/camelcase-sendfile
```

Terminal window

```
yarn dlx codemod@latest @expressjs/camelcase-sendfile
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/camelcase-sendfile
```

Terminal window

```
bunx codemod@latest @expressjs/camelcase-sendfile
```

Or you can update your code manually:

```
app.get('/user', (req, res) => {
  res.sendfile('/path/to/file');
  res.sendFile('/path/to/file');
});
```

### [res.sendFile() options](#ressendfile-options)

The `hidden` and `from` options for `res.sendFile()` are no longer supported. Use `dotfiles` and `root` instead.

The `dotfiles` option applies to hidden directories in the path as well as hidden files. For example, a file served from an absolute path like `/var/www/app/.cache/index.html` now requires `dotfiles: 'allow'`, even though `index.html` is not a dotfile. In Express 4 a hidden directory in the path was served by default; Express 5 returns `404` unless you opt in.

This check only applies to the part of the path that `send` evaluates. When you pass a `root`, only the portion relative to `root` is checked, so a hidden directory inside `root` is unaffected.

#### [How to update](#how-to-update-10)

You can automatically update your code by running the following command:

Terminal window

```
npx codemod@latest @expressjs/sendfile-options
```

Terminal window

```
yarn dlx codemod@latest @expressjs/sendfile-options
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/sendfile-options
```

Terminal window

```
bunx codemod@latest @expressjs/sendfile-options
```

Or you can update your code manually:

```
app.get('/files/:name', (req, res) => {
  res.sendFile(req.params.name, { hidden: true, from: '/uploads' });
  res.sendFile(req.params.name, { dotfiles: 'allow', root: '/uploads' });
});
```

If you serve an absolute path that contains a hidden directory, opt in with `dotfiles: 'allow'` or use `root` so the hidden segment is not part of the evaluated path:

```
app.get('/build', (req, res) => {
  res.sendFile('/var/www/app/.cache/index.html');
  res.sendFile('/var/www/app/.cache/index.html', { dotfiles: 'allow' });
  // or: res.sendFile('index.html', { root: '/var/www/app/.cache' });
});
```

### [express.static() options](#expressstatic-options)

The `hidden` and `from` options for `express.static()` are no longer supported. Use `dotfiles` and `root` instead. Note that `from` was never documented in the API but was accepted as an alias for `root`. The default value of `dotfiles` is now `"ignore"`.

The `dotfiles` check now also applies to hidden **directories** in the request path, not just hidden files. A request like `GET /.well-known/acme-challenge/...` that was served by default in Express 4 now returns `404` unless you set `dotfiles: 'allow'`. This only affects the part of the path relative to the configured `root`; a hidden directory in `root` itself is unaffected.

#### [How to update](#how-to-update-11)

You can automatically update your code by running the following command:

Terminal window

```
npx codemod@latest @expressjs/static-dotfiles
```

Terminal window

```
yarn dlx codemod@latest @expressjs/static-dotfiles
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/static-dotfiles
```

Terminal window

```
bunx codemod@latest @expressjs/static-dotfiles
```

Or you can update your code manually:

```
const express = require('express');
const app = express();


app.use(express.static('public', { hidden: true }));
app.use(express.static('public', { dotfiles: 'allow' }));
```

If you rely on serving a hidden directory such as `.well-known` (for example, ACME/Let’s Encrypt challenges), opt in explicitly. This is needed even if you never used the `hidden` option:

```
app.use(express.static('public'));
app.use(express.static('public', { dotfiles: 'allow' }));
```

### [router.param(fn)](#routerparamfn)

The `router.param(fn)` signature was used for modifying the behavior of the `router.param(name, fn)` function. It has been deprecated since v4.11.0, and Express 5 no longer supports it at all.

### [express.static.mime](#expressstaticmime)

In Express 5, `mime` is no longer an exported property of the `static` field. Use the [`mime-types` package](https://github.com/jshttp/mime-types) to work with MIME type values.

#### [How to update](#how-to-update-12)

You can automatically update your code by running the following command:

Terminal window

```
npx codemod@latest @expressjs/static-mime
```

Terminal window

```
yarn dlx codemod@latest @expressjs/static-mime
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/static-mime
```

Terminal window

```
bunx codemod@latest @expressjs/static-mime
```

Or you can update your code manually:

```
express.static.mime.lookup('json');
const mime = require('mime-types');
mime.lookup('json');
```

### [MIME type changes](#mime-type-changes)

Several MIME types have changed due to updates in [`mime-db`](https://github.com/jshttp/mime-db). These changes only affect `express.static()` and `res.sendFile()`. For a full list of changes, see the [`mime-db` changelog](https://github.com/jshttp/mime-db/blob/HEAD/HISTORY.md).

Express 4 uses `mime-db` version **1.52.0**, while Express 5 uses newer versions that reflect updates to IANA and other MIME type specifications. The most notable change is that JavaScript files (`.js`) are now served as `text/javascript` instead of `application/javascript`.

In Express 5, changes to MIME types from `mime-db` updates are not considered breaking changes, so be careful when updating your dependencies as MIME types may change between minor or patch versions.

### [express:router debug logs](#expressrouter-debug-logs)

Router handling logic is now performed by a separate dependency ([`router`](https://github.com/pillarjs/router)) maintained by the Express team, so debug logs have moved to a different namespace. Before Express 5.1, these debug logs did not exist. To get them, update to a recent Express 5 version or update the `router` package in your `package-lock.json`:

| v4                         | v5                                  |
| -------------------------- | ----------------------------------- |
| `express:router`           | `router`                            |
| `express:router:layer`     | `router:layer`                      |
| `express:router:route`     | `router:route`                      |
| `express:*` (includes all) | `express:*` + `router` + `router:*` |

#### [How to update](#how-to-update-13)

```
DEBUG=express:* node index.js
DEBUG=express:*,router,router:* node index.js
```

## [Changed](#changed)

These APIs still exist but their behavior has changed. Review these changes to make sure your app works as expected.

### [Path route matching syntax](#path-route-matching-syntax)

Path route matching syntax is when a string is supplied as the first parameter to the `app.all()`, `app.use()`, `app.METHOD()`, `router.all()`, `router.METHOD()`, and `router.use()` APIs. The following changes have been made to how the path string is matched to an incoming request:

* The wildcard `*` must have a name, matching the behavior of parameters `:`, use `/*splat` instead of `/*`

  ```
  app.get('/*', async (req, res) => {
  app.get('/*splat', async (req, res) => {
    res.send('ok');
  });
  ```

  ### Note

  `*splat` matches any path without the root path. If you need to match the root path as well `/`, you can use `/{*splat}`, wrapping the wildcard in braces.

  ```
  app.get('/{*splat}', async (req, res) => {
    res.send('ok');
  });
  ```

* The optional character `?` is no longer supported, use braces instead.

  ```
  app.get('/:file.:ext?', async (req, res) => {
  app.get('/:file{.:ext}', async (req, res) => {
    res.send('ok');
  });
  ```

* Regexp characters are not supported. For example:

  ```
  app.get('/[discussion|page]/:slug', async (req, res) => {
  app.get(['/discussion/:slug', '/page/:slug'], async (req, res) => {
    res.status(200).send('ok');
  });
  ```

* Some characters have been reserved to avoid confusion during upgrade (`()[]?+!`), use `\` to escape them.

* Parameter names now support valid JavaScript identifiers, or quoted like `:"this"`.

### [Rejected promises handled from middleware and handlers](#rejected-promises-handled-from-middleware-and-handlers)

Request middleware and handlers that return rejected promises are now handled by forwarding the rejected value as an `Error` to the error handling middleware. This means that using `async` functions as middleware and handlers are easier than ever. When an error is thrown in an `async` function or a rejected promise is `await`ed inside an async function, those errors will be passed to the error handler as if calling `next(err)`.

Details of how Express handles errors is covered in the [error handling documentation](/en/5x/guide/error-handling/).

#### [How to update](#how-to-update-14)

You can now use `async/await` directly without manually catching errors. If `getUserById` throws an error or rejects, `next` will be called automatically with the rejected value.

```
app.get('/user/:id', (req, res, next) => {
  getUserById(req.params.id)
    .then((user) => res.send(user))
    .catch(next);
});
app.get('/user/:id', async (req, res) => {
  const user = await getUserById(req.params.id);
  res.send(user);
});
```

### [express.urlencoded](#expressurlencoded)

The `express.urlencoded` method makes the `extended` option `false` by default.

#### [How to update](#how-to-update-15)

If your application relies on the `extended` behavior, explicitly set it to `true`:

```
app.use(express.urlencoded());
app.use(express.urlencoded({ extended: true }));
```

### [express.static dotfiles](#expressstatic-dotfiles)

The `express.static` middleware’s `dotfiles` option now defaults to `"ignore"`. In Express 4, dotfiles were served by default. As a result, files inside a directory that starts with a dot (`.`), such as `.well-known`, will no longer be accessible and will return a **404 Not Found** error. This can break functionality that depends on serving dot-directories, such as Android App Links and Apple Universal Links.

#### [How to update](#how-to-update-16)

Serve specific dot-directories explicitly using the `dotfiles: "allow"` option. This allows you to safely serve only the intended dot-directories while keeping the default secure behavior for other dotfiles.

```
app.use('/.well-known', express.static('public/.well-known', { dotfiles: 'allow' }));
app.use(express.static('public'));
```

### [router.param() with an array of names](#routerparam-with-an-array-of-names)

`router.param(name, fn)` no longer accepts an array for `name`. In Express 4 an array was accepted silently; in Express 5, passing anything other than a string throws `TypeError: argument name must be a string`. (Note that `app.param()` still accepts an array of names.)

#### [How to update](#how-to-update-17)

Register each parameter name with its own `router.param()` call:

```
router.param(['id', 'page'], (req, res, next, value) => {
  // ...
});
const loadParam = (req, res, next, value) => {
  // ...
};
router.param('id', loadParam);
router.param('page', loadParam);
```

### [app.listen](#applisten)

In Express 5, the `app.listen` method will invoke the user-provided callback function (if provided) when the server receives an error event. In Express 4, such errors would be thrown. This change shifts error-handling responsibility to the callback function in Express 5. If there is an error, it will be passed to the callback as an argument. For example:

```
const server = app.listen(8080, '0.0.0.0', (error) => {
  if (error) {
    throw error; // e.g. EADDRINUSE
  }
  console.log(`Listening on ${JSON.stringify(server.address())}`);
});
```

### [app.router](#approuter)

The `app.router` object, which was removed in Express 4, has made a comeback in Express 5. In the new version, this object is a just a reference to the base Express router, unlike in Express 3, where an app had to explicitly load it.

### [req.body](#reqbody)

The `req.body` property returns `undefined` when the body has not been parsed. In Express 4, it returns `{}` by default.

```
app.post('/user', (req, res) => {
  console.dir(req.body);
  // Express 4
  // => {}
  // Express 5
  // => undefined
});
```

### [req.host](#reqhost)

In Express 4, the `req.host` function incorrectly stripped off the port number if it was present. In Express 5, the port number is maintained.

### [req.params](#reqparams)

The `req.params` object now has a **null prototype** when using string paths. However, if the path is defined with a regular expression, `req.params` remains a standard object with a normal prototype. Additionally, there are two important behavioral changes:

**Wildcard parameters are now arrays:**

Wildcards (e.g., `/*splat`) capture path segments as an array instead of a single string.

```
app.get('/*splat', (req, res) => {
  // GET /foo/bar
  console.dir(req.params);
  // => [Object: null prototype] { splat: [ 'foo', 'bar' ] }
});
```

**Unmatched parameters are omitted:**

In Express 4, unmatched wildcards were empty strings (`''`) and optional `:` parameters (using `?`) had a key with value `undefined`. In Express 5, unmatched parameters are completely omitted from `req.params`.

```
// v4: unmatched wildcard is empty string
app.get('/*', (req, res) => {
  // GET /
  console.dir(req.params);
  // => { '0': '' }
});


// v4: unmatched optional param is undefined
app.get('/:file.:ext?', (req, res) => {
  // GET /image
  console.dir(req.params);
  // => { file: 'image', ext: undefined }
});


// v5: unmatched optional param is omitted
app.get('/:file{.:ext}', (req, res) => {
  // GET /image
  console.dir(req.params);
  // => [Object: null prototype] { file: 'image' }
});
```

### [req.query](#reqquery)

The `req.query` property is no longer a writable property and is instead a getter. The default query parser has been changed from “extended” to “simple”.

```
app.get('/search', (req, res) => {
  // This is no longer possible in Express 5
  req.query.page = 1;
});
```

### [res.clearCookie](#resclearcookie)

The `res.clearCookie` method ignores the `maxAge` and `expires` options provided by the user.

```
app.get('/logout', (req, res) => {
  res.clearCookie('session', { maxAge: 0, expires: new Date(0) });
  res.clearCookie('session');
});
```

### [res.status](#resstatus)

The `res.status` method only accepts integers in the range of `100` to `999`, following the behavior defined by Node.js, and it returns an error when the status code is not an integer.

```
app.get('/user', (req, res) => {
  res.status(99); // Throws an error
  res.status(200); // OK
});
```

### [res.vary](#resvary)

The `res.vary` throws an error when the `field` argument is missing. In Express 4, if the argument was omitted, it gave a warning in the console.

```
app.get('/user', (req, res) => {
  res.vary(); // Throws an error
  res.vary('Accept'); // OK
});
```

## [Improvements](#improvements)

These changes don’t require any migration steps, but are worth knowing about when upgrading.

### [res.render()](#resrender)

This method now enforces asynchronous behavior for all view engines, avoiding bugs caused by view engines that had a synchronous implementation and that violated the recommended interface.

### [Brotli encoding support](#brotli-encoding-support)

Middleware like `express.json()`, `express.urlencoded()`, `express.text()`, and `express.raw()` now support Brotli (`Content-Encoding: br`) decompression for incoming request bodies, in addition to `gzip` and `deflate`.

----
url: https://expressjs.com/en/resources/glossary
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/glossary.mdx)

# [Glossary](#overview)

## [application](#application)

In general, one or more programs that are designed to carry out operations for a specific purpose. In the context of Express, a program that uses the Express API running on the Node.js platform. Might also refer to an [app object](/en/5x/api/express/).

## [API](#api)

Application programming interface. Spell out the abbreviation when it is first used.

## [Express](#express)

A fast, un-opinionated, minimalist web framework for Node.js applications. In general, “Express” is preferred to “Express.js,” though the latter is acceptable.

## [libuv](#libuv)

A multi-platform support library which focuses on asynchronous I/O, primarily developed for use by Node.js.

## [middleware](#middleware)

A function that is invoked by the Express routing layer before the final request handler, and thus sits in the middle between a raw request and the final intended route. A few fine points of terminology around middleware:

* `var foo = require('middleware')` is called *requiring* or *using* a Node.js module. Then the statement `var mw = foo()` typically returns the middleware.
* `app.use(mw)` is called *adding the middleware to the global processing stack*.
* `app.get('/foo', mw, (req, res) => { /* ... */ })` is called *adding the middleware to the “GET /foo” processing stack*.

## [Node.js](#nodejs)

A software platform that is used to build scalable network applications. Node.js uses JavaScript as its scripting language, and achieves high throughput via non-blocking I/O and a single-threaded event loop. See [nodejs.org](https://nodejs.org/en/). **Usage note**: Initially, “Node.js,” thereafter “Node”.

## [open-source, open source](#open-source-open-source)

When used as an adjective, hyphenate; for example: “This is open-source software.” See [Open-source software on Wikipedia](https://en.wikipedia.org/wiki/Open-source_software).

### Note

Although it is common not to hyphenate this term, we are using the standard English rules for hyphenating a compound adjective.

## [request](#request)

An HTTP request. A client submits an HTTP request message to a server, which returns a response. The request must use one of several [request methods](https://en.wikipedia.org/wiki/HTTP#Request_methods) such as GET, POST, and so on.

## [response](#response)

An HTTP response. A server returns an HTTP response message to the client. The response contains completion status information about the request and might also contain requested content in its message body.

## [route](#route)

Part of a URL that identifies a resource. For example, in `http://foo.com/products/id`, “/products/id” is the route.

## [router](#router)

See [router](/en/5x/api/router/) in the API reference.

----
url: https://expressjs.com/en/blog/2025-06-05-vulnerability-reporting-process-overhaul
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2025-06-05-vulnerability-reporting-process-overhaul)

security

# [How Express.js Rebuilt Its Vulnerability Reporting Process](#overview)

Ulises GascónJune 5, 2025

[](https://x.com/intent/tweet?text=How%20Express.js%20Rebuilt%20Its%20Vulnerability%20Reporting%20Process\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-06-05-vulnerability-reporting-process-overhaul%2F)[](https://bsky.app/intent/compose?text=How%20Express.js%20Rebuilt%20Its%20Vulnerability%20Reporting%20Process%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-06-05-vulnerability-reporting-process-overhaul%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-06-05-vulnerability-reporting-process-overhaul%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-06-05-vulnerability-reporting-process-overhaul%2F\&text=How%20Express.js%20Rebuilt%20Its%20Vulnerability%20Reporting%20Process)[](https://wa.me/?text=How%20Express.js%20Rebuilt%20Its%20Vulnerability%20Reporting%20Process%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-06-05-vulnerability-reporting-process-overhaul%2F)[](/feed.xml)

The Express.js project has completed a major milestone in its ongoing commitment to security: the implementation of a formal, centralized vulnerability reporting and response process.

Until recently, security reports were typically handled over email — an approach that worked in the early days but no longer scaled with the growing complexity and user base of Express. This informal system introduced potential delays, inconsistent handling, and increased the risk of issues being missed or misunderstood.

Thanks to support from the [Sovereign Tech Fund](https://sovereign.tech), the Express.js Security Working Group has now completed a ground-up overhaul of how we manage vulnerability reports.

## [🛠️ Key Improvements](#️-key-improvements)

### [Formalized Vulnerability Reporting Workflow](#formalized-vulnerability-reporting-workflow)

A comprehensive runbook and process flow have been created to guide maintainers through each step of triaging, confirming, and addressing reported security issues.

* [View the documentation](https://github.com/expressjs/security-wg/blob/main/docs/incident_response_plan.md)
* [Security Report Handling Flowchart](https://github.com/expressjs/security-wg/blob/main/docs/incident_response_plan.md#security-report-handling-flowchart)

### [Unified Security Policy Across Repositories](#unified-security-policy-across-repositories)

All Express.js repositories now share a single, unified `SECURITY.md` policy to ensure consistency and remove confusion for reporters and maintainers alike.

* [View the unified Security Policy](https://github.com/expressjs/.github/blob/master/SECURITY.md)

### [GitHub Security Advisories Enabled](#github-security-advisories-enabled)

Security Advisories are now enabled across all Express.js repositories, allowing for secure, private vulnerability reporting through GitHub’s built-in system.

* [How to report a security bug using GitHub Security Advisory](https://github.com/expressjs/.github/blob/master/SECURITY.md#reporting-security-bugs-via-github-security-advisory-preferred)

### [Clear Maintainer Responsibilities](#clear-maintainer-responsibilities)

Expectations around ownership and response timelines have been clarified and published to reduce ambiguity and improve responsiveness.

> A [Security triage team member](https://github.com/expressjs/security-wg#security-triage-team-expressjssecurity-triage) or [the repo captain](https://github.com/expressjs/discussions/blob/master/docs/contributing/captains_and_committers.md) will acknowledge your report as soon as possible.
>
> After the initial reply to your report, the security team will endeavor to keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
>
> *[Security Policy](https://github.com/expressjs/.github/blob/master/SECURITY.md)*

## [🛡️ Express is Now Covered Under the OpenJS Foundation CNA](#️-express-is-now-covered-under-the-openjs-foundation-cna)

As of June 2025, the [OpenJS Foundation](https://openjsf.org/) is officially a [CVE Numbering Authority (CNA)](https://openjsf.org/blog/openjs-foundation-cna), empowered to assign CVE identifiers for security vulnerabilities across its hosted projects—including Express.

What this means for the community:

* Security vulnerabilities in Express can now receive official CVE IDs through OpenJS, improving transparency and coordination.
* The foundation provides support and tooling to streamline the vulnerability disclosure process, particularly for maintainers and security researchers.
* For critical issues, the CNA helps ensure that disclosures follow best practices and are recorded in global vulnerability databases.

Please refer to [Express’s Security Policy](https://github.com/expressjs/express/security/policy) for the correct disclosure process. If needed, escalation routes through the OpenJS CNA are now available.

This advancement is part of a broader effort to strengthen the security of JavaScript’s open-source ecosystem—especially for widely used, community-driven projects like Express.

Learn more:

* [OpenJS Foundation is now a CNA – Official Blog Post](https://openjsf.org/blog/openjs-foundation-cna)
* [Socket.dev Coverage: OpenJS Foundation Becomes a CNA](https://socket.dev/blog/openjs-foundation-is-now-a-cna)

## [👀 Coming Soon: Bug Bounty Program in the Works](#-coming-soon-bug-bounty-program-in-the-works)

To further enhance the security of our ecosystem and encourage responsible vulnerability disclosure, the Express.js team has begun exploring participation in a community-focused bug bounty initiative—powered by the [Sovereign Tech Resilience program](https://www.sovereign.tech/programs/bug-resilience).

This collaboration aims to:

* Reward contributors for discovering and responsibly reporting security issues
* Improve our ability to address vulnerabilities quickly and transparently
* Strengthen long-term resilience for users and maintainers alike

Join the conversation and share your thoughts in [expressjs/discussions#345 – Bug Bounty Proposal](https://github.com/expressjs/discussions/issues/345)

## [Why This Matters](#why-this-matters)

Security is a shared responsibility — and one that must evolve as the project grows. With these updates, Express.js has laid the foundation for a more reliable, scalable, and transparent vulnerability response system.

We’re grateful to the [OpenJS Foundation](https://openjsf.org/) and the [Sovereign Tech Fund](https://www.sovereign.tech/) for their support and are excited to share this progress with the broader community.

----
url: https://expressjs.com/en/4x/guide/error-handling
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/guide/error-handling.mdx)

# [Error Handling](#overview)

*Error Handling* refers to how Express catches and processes errors that occur both synchronously and asynchronously. Express comes with a default error handler so you don’t need to write your own to get started.

## [Catching Errors](#catching-errors)

It’s important to ensure that Express catches all errors that occur while running route handlers and middleware.

Errors that occur in synchronous code inside route handlers and middleware require no extra work. If synchronous code throws an error, then Express will catch and process it. For example:

```
app.get('/', (req, res) => {
  throw new Error('BROKEN'); // Express will catch this on its own.
});
```

```
import { type Request, type Response } from 'express';


app.get('/', (req: Request, res: Response) => {
  throw new Error('BROKEN'); // Express will catch this on its own.
});
```

For errors returned from asynchronous functions invoked by route handlers and middleware, you must pass them to the `next()` function, where Express will catch and process them. For example:

```
app.get('/', (req, res, next) => {
  fs.readFile('/file-does-not-exist', (err, data) => {
    if (err) {
      next(err); // Pass errors to Express.
    } else {
      res.send(data);
    }
  });
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get('/', (req: Request, res: Response, next: NextFunction) => {
  fs.readFile('/file-does-not-exist', (err, data) => {
    if (err) {
      next(err); // Pass errors to Express.
    } else {
      res.send(data);
    }
  });
});
```

Errors from rejected promises are not passed to `next` automatically, and this includes `async` functions: if an `async` route handler throws or awaits a rejected promise, the rejection is unhandled, which crashes the process on current Node.js versions. You must catch the error yourself and pass it to Express:

```
app.get('/user/:id', async (req, res, next) => {
  try {
    const user = await getUserById(req.params.id);
    res.send(user);
  } catch (err) {
    next(err);
  }
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get('/user/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const user = await getUserById(req.params.id);
    res.send(user);
  } catch (err) {
    next(err);
  }
});
```

### Note

Consider [updating to Express 5](/en/guide/migrating-5/), where route handlers and middleware that return a Promise call `next(value)` automatically when they reject or throw an error, making the `try...catch` above unnecessary.

If you pass anything to the `next()` function (except the string `'route'`), Express regards the current request as being an error and will skip any remaining non-error handling routing and middleware functions.

If the callback in a sequence provides no data, only errors, you can simplify this code as follows:

```
app.get('/', [
  function (req, res, next) {
    fs.writeFile('/inaccessible-path', 'data', next);
  },
  function (req, res) {
    res.send('OK');
  },
]);
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get('/', [
  function (req: Request, res: Response, next: NextFunction) {
    fs.writeFile('/inaccessible-path', 'data', next);
  },
  function (req: Request, res: Response) {
    res.send('OK');
  },
]);
```

In the above example, `next` is provided as the callback for `fs.writeFile`, which is called with or without errors. If there is no error, the second handler is executed, otherwise Express catches and processes the error.

You must catch errors that occur in asynchronous code invoked by route handlers or middleware and pass them to Express for processing. For example:

```
app.get('/', (req, res, next) => {
  setTimeout(() => {
    try {
      throw new Error('BROKEN');
    } catch (err) {
      next(err);
    }
  }, 100);
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get('/', (req: Request, res: Response, next: NextFunction) => {
  setTimeout(() => {
    try {
      throw new Error('BROKEN');
    } catch (err) {
      next(err);
    }
  }, 100);
});
```

The above example uses a `try...catch` block to catch errors in the asynchronous code and pass them to Express. If the `try...catch` block were omitted, Express would not catch the error since it is not part of the synchronous handler code.

Use promises to avoid the overhead of the `try...catch` block or when using functions that return promises. For example:

```
app.get('/', (req, res, next) => {
  Promise.resolve()
    .then(() => {
      throw new Error('BROKEN');
    })
    .catch(next); // Errors will be passed to Express.
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get('/', (req: Request, res: Response, next: NextFunction) => {
  Promise.resolve()
    .then(() => {
      throw new Error('BROKEN');
    })
    .catch(next); // Errors will be passed to Express.
});
```

If a callback in the promise chain throws, the chain turns that exception into a rejection, which travels down to the final `.catch`. There, passing `next` as the handler is enough: `.catch` calls it with the error as its first argument, which is exactly the argument `next` expects, so the error reaches Express.

You could also use a chain of handlers to rely on synchronous error catching, by reducing the asynchronous code to something trivial. For example:

```
app.get('/', [
  function (req, res, next) {
    fs.readFile('/maybe-valid-file', 'utf-8', (err, data) => {
      res.locals.data = data;
      next(err);
    });
  },
  function (req, res) {
    res.locals.data = res.locals.data.split(',')[1];
    res.send(res.locals.data);
  },
]);
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get('/', [
  function (req: Request, res: Response, next: NextFunction) {
    fs.readFile('/maybe-valid-file', 'utf-8', (err, data) => {
      res.locals.data = data;
      next(err);
    });
  },
  function (req: Request, res: Response) {
    res.locals.data = res.locals.data.split(',')[1];
    res.send(res.locals.data);
  },
]);
```

The above example contains a couple of trivial statements following the `readFile` call. If `readFile` causes an error, then it passes the error to Express, otherwise you quickly return to the world of synchronous error handling in the next handler in the chain. Then, the example above tries to process the data. If this fails, then the synchronous error handler will catch it. If you had done this processing inside the `readFile` callback, then the application might exit and the Express error handlers would not run.

```
function errorHandler(err, req, res, next) {
  if (res.headersSent) {
    return next(err);
  }
  res.status(500);
  res.render('error', { error: err });
}
```

```
import { type Request, type Response, type NextFunction } from 'express';


function errorHandler(err: Error, req: Request, res: Response, next: NextFunction) {
  if (res.headersSent) {
    return next(err);
  }
  res.status(500);
  res.render('error', { error: err });
}
```

Note that the default error handler can get triggered if you call `next()` with an error in your code more than once, even if custom error handling middleware is in place.

Other error handling middleware can be found at [Express middleware](/en/resources/middleware/).

## [Writing error handlers](#writing-error-handlers)

Define error-handling middleware functions in the same way as other middleware functions, except error-handling functions have four arguments instead of three: `(err, req, res, next)`. For example:

```
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

You define error-handling middleware last, after other `app.use()` and routes calls; for example:

index.cjs

```
const bodyParser = require('body-parser');
const methodOverride = require('method-override');


app.use(
  bodyParser.urlencoded({
    extended: true,
  })
);
app.use(bodyParser.json());
app.use(methodOverride());
app.use((err, req, res, next) => {
  // logic
});
```

index.mjs

```
import bodyParser from 'body-parser';
import methodOverride from 'method-override';


app.use(
  bodyParser.urlencoded({
    extended: true,
  })
);
app.use(bodyParser.json());
app.use(methodOverride());
app.use((err, req, res, next) => {
  // logic
});
```

index.ts

```
import bodyParser from 'body-parser';
import methodOverride from 'method-override';
import { type Request, type Response, type NextFunction } from 'express';


app.use(
  bodyParser.urlencoded({
    extended: true,
  })
);
app.use(bodyParser.json());
app.use(methodOverride());
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  // logic
});
```

Responses from within a middleware function can be in any format, such as an HTML error page, a simple message, or a JSON string.

For organizational (and higher-level framework) purposes, you can define several error-handling middleware functions, much as you would with regular middleware functions. For example, to define an error-handler for requests made by using `XHR` and those without:

index.cjs

```
const bodyParser = require('body-parser');
const methodOverride = require('method-override');


app.use(
  bodyParser.urlencoded({
    extended: true,
  })
);
app.use(bodyParser.json());
app.use(methodOverride());
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHandler);
```

index.mjs

```
import bodyParser from 'body-parser';
import methodOverride from 'method-override';


app.use(
  bodyParser.urlencoded({
    extended: true,
  })
);
app.use(bodyParser.json());
app.use(methodOverride());
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHandler);
```

In this example, the generic `logErrors` might write request and error information to `stderr`, for example:

```
function logErrors(err, req, res, next) {
  console.error(err.stack);
  next(err);
}
```

```
import { type Request, type Response, type NextFunction } from 'express';


function logErrors(err: Error, req: Request, res: Response, next: NextFunction) {
  console.error(err.stack);
  next(err);
}
```

Also in this example, `clientErrorHandler` is defined as follows; in this case, the error is explicitly passed along to the next one.

Notice that when you do not call `next` in an error-handling function, you are responsible for writing (and ending) the response. Otherwise, those requests will “hang” and will not be eligible for garbage collection.

```
function clientErrorHandler(err, req, res, next) {
  if (req.xhr) {
    res.status(500).send({ error: 'Something failed!' });
  } else {
    next(err);
  }
}
```

```
import { type Request, type Response, type NextFunction } from 'express';


function clientErrorHandler(err: Error, req: Request, res: Response, next: NextFunction) {
  if (req.xhr) {
    res.status(500).send({ error: 'Something failed!' });
  } else {
    next(err);
  }
}
```

Implement the “catch-all” `errorHandler` function as follows (for example):

```
function errorHandler(err, req, res, next) {
  res.status(500);
  res.render('error', { error: err });
}
```

```
import { type Request, type Response, type NextFunction } from 'express';


function errorHandler(err: Error, req: Request, res: Response, next: NextFunction) {
  res.status(500);
  res.render('error', { error: err });
}
```

If you have a route handler with multiple callback functions, you can use the `route` parameter to skip to the next route handler. For example:

```
app.get(
  '/a_route_behind_paywall',
  (req, res, next) => {
    if (!req.user.hasPaid) {
      // continue handling this request
      next('route');
    } else {
      next();
    }
  },
  (req, res, next) => {
    PaidContent.find((err, doc) => {
      if (err) return next(err);
      res.json(doc);
    });
  }
);
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get(
  '/a_route_behind_paywall',
  (req: Request, res: Response, next: NextFunction) => {
    if (!req.user.hasPaid) {
      // continue handling this request
      next('route');
    } else {
      next();
    }
  },
  (req: Request, res: Response, next: NextFunction) => {
    PaidContent.find((err, doc) => {
      if (err) return next(err);
      res.json(doc);
    });
  }
);
```

In this example, the `getPaidContent` handler will be skipped but any remaining handlers in `app` for `/a_route_behind_paywall` would continue to be executed.

### Note

Calls to `next()` and `next(err)` indicate that the current handler is complete and in what state. `next(err)` will skip all remaining handlers in the chain except for those that are set up to handle errors as described above.

----
url: https://expressjs.com/en/4x/starter/static-files
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/starter/static-files.mdx)

# [Serving static files in Express](#overview)

To serve static files such as images, CSS files, and JavaScript files, use the `express.static` built-in middleware function in Express.

The function signature is:

```
express.static(root, [options]);
```

The `root` argument specifies the root directory from which to serve static assets. For more information on the `options` argument, see [express.static](/en/4x/api/express/#expressstatic).

For example, use the following code to serve images, CSS files, and JavaScript files in a directory named `public`:

```
app.use(express.static('public'));
```

Now, you can load the files that are in the `public` directory:

```
http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html
```

### Note

Express looks up the files relative to the static directory, so the name of the static directory is not part of the URL.

To use multiple static assets directories, call the `express.static` middleware function multiple times:

```
app.use(express.static('public'));
app.use(express.static('files'));
```

Express looks up the files in the order in which you set the static directories with the `express.static` middleware function.

### Note

For best results, [use a reverse proxy](/en/advanced/best-practice-performance/#use-a-reverse-proxy) cache to improve performance of serving static assets.

To create a virtual path prefix (where the path does not actually exist in the file system) for files that are served by the `express.static` function, [specify a mount path](/en/4x/api/application/#appuse) for the static directory, as shown below:

```
app.use('/static', express.static('public'));
```

Now, you can load the files that are in the `public` directory from the `/static` path prefix.

```
http://localhost:3000/static/images/kitten.jpg
http://localhost:3000/static/css/style.css
http://localhost:3000/static/js/app.js
http://localhost:3000/static/images/bg.png
http://localhost:3000/static/hello.html
```

However, the path that you provide to the `express.static` function is relative to the directory from where you launch your `node` process. If you run the express app from another directory, it’s safer to use the absolute path of the directory that you want to serve:

index.cjs

```
const path = require('path');
app.use('/static', express.static(path.join(__dirname, 'public')));
```

index.mjs

```
import path from 'path';


app.use('/static', express.static(path.join(__dirname, 'public')));
```

----
url: https://expressjs.com/en/blog/2025-03-31-v5-1-latest-release
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2025-03-31-v5-1-latest-release)

announcements

# [Express@5.1.0: Now the Default on npm with LTS Timeline](#overview)

Express Technical CommitteeMarch 31, 2025

[](https://x.com/intent/tweet?text=Express%405.1.0%3A%20Now%20the%20Default%20on%20npm%20with%20LTS%20Timeline\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-03-31-v5-1-latest-release%2F)[](https://bsky.app/intent/compose?text=Express%405.1.0%3A%20Now%20the%20Default%20on%20npm%20with%20LTS%20Timeline%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-03-31-v5-1-latest-release%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-03-31-v5-1-latest-release%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-03-31-v5-1-latest-release%2F\&text=Express%405.1.0%3A%20Now%20the%20Default%20on%20npm%20with%20LTS%20Timeline)[](https://wa.me/?text=Express%405.1.0%3A%20Now%20the%20Default%20on%20npm%20with%20LTS%20Timeline%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-03-31-v5-1-latest-release%2F)[](/feed.xml)

Express v5.0.0 was released on September 9th last year, but we didn’t make it the `latest` release on npm. Many asked us why and when it would be, and frankly we were not ready at the time to take that jump. If you have not followed the news from the project this past year, we have been [hard at work reviving the project](/en/blog/2025-01-09-rewind-2024-triumphs-and-2025-vision/) and when we pushed the initial v5 release there were many loose ends still hanging. So first lets quickly go over some of those loose ends.

### [Documentation updates](#documentation-updates)

We had not updated the docs, provided migration guides, or even fully reviewed some of the stagnated v4/5 docs in a long time. Since then we have had tons of great contributors help get things into better shape. As with any volunteer based Open Source project, we love contributions to help us improve so as you upgrade please continue to open PRs to fix anything we missed.

You can find our [v5 docs](/en/5x/api/) and our [migration guide](/en/guide/migrating-5/) on the website.

### [Migration Support](#migration-support)

We know that migrating between versions can be challenging, especially when it involves significant changes in a widely used framework like Express. That’s why we have worked on a solution to simplify part of the process and reduce the impact on developers.

Thanks to the incredible efforts of [Sebastian](https://github.com/bjohansebas) and [Filip](https://github.com/kjugi), we have developed a new [codemod package](https://www.npmjs.com/package/@expressjs/codemod) specifically designed to facilitate the transition from Express v4 to v5, as well as future major versions. This package automates many of the necessary code changes, minimizing manual effort and making the upgrade as smooth and efficient as possible.

However, we understand that not all changes can be automated. Some breaking changes, such as the [new Path Route Matching syntax](/en/guide/migrating-5/#path-route-matching-syntax), require manual modifications by developers. You can read more about all of the breaking changes which came with v5 in our [original release announcement](/en/blog/2024-10-15-v5-release/).

For more details on the migration process and how to use the codemod package, check the [repository’s README](https://github.com/expressjs/codemod#readme) and the [migration guide](/en/guide/migrating-5/).

### [Ecosystem compatibility](#ecosystem-compatibility)

The Express ecosystem is one of its strongest assets. It goes back to the early days of Node.js and is the backbone that keeps express popular. When it goes [10 years without a major release](/en/blog/2024-10-15-v5-release/) everything from middleware to documentation needed updates. We wanted to make sure folks had some time to get all of that updated before we had everyone moving over. Particularly we care about our very large beginner user base who may not know the blog post they are reading is not compatible with what they get from `npm i express`.

We recognize that some friction is inevitable during major upgrades, but thanks to work from ecosystem partners like [Kamil](https://github.com/kamilmysliwiec) from NestJS [working to update `express` before we went `latest`](https://github.com/expressjs/express/issues/5944#issuecomment-2523074127) we will hopefully be ahead of the curve. And as I said above, we always welcome help to make this transition easier for those who follow after you, PRs are the best support you can give.

### [Long Term Support](#long-term-support)

We had been discussing how to support v4 now that v5 was out, but we had not defined a clear guideline or expectation, and we had (still don’t have) end user docs on our plans here. While we still have progress to make here, we have a [proposed LTS strategy ](https://github.com/expressjs/discussions/pull/352)which will be the basis for our forthcoming docs. Input is very welcome on this so we can make sure it is clearly communicated and acceptable to the community.

Additionally since then [we have announced a partnership with HeroDevs](/en/blog/2024-10-01-herodevs-partnership-announcement/) to help companies who are less capable of updating. More information on how this will work when v4 EOL will come when we get closer to that time.

***

## [Support Phases and Going latest](#support-phases-and-going-latest)

What does it mean to “go latest”? If you are unfamiliar with how npm `dist-tags` work, the `latest` tag is what users will get when they run `npm install express`. This is important because it means it is the “default installed version” and will trigger the transition of nearly 17 million weekly downloads from our current latest v4.21.2 to v5. As we start this transition we want users, companies, and other organizations to know exactly what it means for support. To help with this we have developed an LTS strategy which defines our 3 support phases and set’s target dates for when v4 will enter EOL.

Express major versions will go through three supported phases:

* `CURRENT`: A new major version is designated as `CURRENT` upon release. It is available but not the `latest` version on npm for a minimum of 3 months.
* `ACTIVE`: After the minimum 3 month period and the TC agrees it is stable and secure, the `ACTIVE` version is tagged `latest` on npm for a minimum of 12 months.
* `MAINTENANCE`: When a new major version becomes `ACTIVE`, the previous major version enters `MAINTENANCE` for 12 months.

### [CURRENT](#current)

* New majors will go through a short period of hardening to ensure stability, security, and ecosystem libraries/resources compatibility.
* We will strive to ensure no breaking changes are included, but reserve the right to make security or high priority fixes of breaking nature within this period.
* `CURRENT` lines will receive all types of active work including: bug fixes, security patches, new features, and deprecation notices.
* Users are recommended to use `CURRENT` lines and to upgrade as quickly as their risk profile allows

### [ACTIVE](#active)

* `ACTIVE` lines will receive all types of active work including: bug fixes, security patches, new features, and deprecation notices.
* For users, `ACTIVE` lines are considered the most stable and well supported version at any given time.

### [MAINTENANCE](#maintenance)

* `MAINTENANCE` lines will only receive security patches or high priority bug fixes.
* Users are highly encouraged to upgrade to a `CURRENT` or `ACTIVE` release.

### [Proposed Schedule](#proposed-schedule)

For the existing release lines, we will set the following phase dates:

| Major | CURRENT                         | ACTIVE     | MAINTENANCE                   | EOL                           |
| ----- | ------------------------------- | ---------- | ----------------------------- | ----------------------------- |
| 4.x   |                                 |            | 2025-04-01                    | \*no sooner than 2026-10-01   |
| 5.x   | 2024-09-11                      | 2025-03-31 | \*\*no sooner than 2026-04-01 | \*\*no sooner than 2027-04-01 |
| 6.x   | \*\*\*no sooner than 2026-01-01 |            |                               |                               |

As you can see, this means that v5.1.0 being tagged `latest` indicates that we moved from `CURRENT` to `ACTIVE` which starts the clock on EOL for v4 by moving it to `MAINTENANCE`. We recognize that v4 is a special case having been the only major version for most of the history of Node.js itself. Because of this, we want to remain flexible and also provide a bit longer support. We want to do what is best for the ecosystem, so consider these goals not commitments.

\*: v4 is a special case, and we may extend MAINTENANCE support \*\*: v5 MAINTENANCE and EOL dates are determined by when v6 is released, these dates reflect the earliest dates if we were to ship v6 on 2025-10-01 \*\*\* : v6 work has not officially started yet, this is simply the earliest date we can ship based on our proposed policy

***

## [Finally, what changed in v5.1.0](#finally-what-changed-in-v510)

This release primarily focused on tech debt from supporting so many old Node.js versions and other things that stagnated but were not landed before v5.0.0 went out.

### [Express 5.1.0 Main Changes](#express-510-main-changes)

* Add support for `Uint8Array` in `res.send()`
* Transitioned all remaining dependencies to use `^` ranges instead of locked versions
* Add package.json funding field to highlight our OpenCollective
* Added support for ETag option in `res.sendFile()`
* Added support for adding multiple links with the same rel with `res.links()`
* Performance: Use loop for acceptParams
* See [Changelog v5.1.0](https://github.com/expressjs/express/releases/tag/v5.1.0)

### [Dependencies updated](#dependencies-updated)

We also invested time to prepare several releases in the packages that Express depend on. Most of this packages are used by other libraries and framework as individual libraries.

* [body-parser@2.2.0](https://github.com/expressjs/body-parser/releases/tag/v2.2.0)

  * Remove legacy node.js support checks for Brotli & `AsyncLocalStorage`
  * Remove `unpipe` & `destroy`

* [router@2.2.0](https://github.com/pillarjs/router/releases/tag/v2.2.0)

  * Restore `debug`. Now with the `router` scope instead of `express`.
  * Remove legacy node.js support checks for `setImmediate`
  * Deprecate non-native promise support
  * Remove `after`, `safe-buffer`, `array-flatten`, `setprototypeof`, `methods`, `utils-merge`

* [finalhandler@2.1.0](https://github.com/pillarjs/finalhandler/releases/tag/v2.1.0)

  * Remove legacy node.js support checks for `headersSent`, `setImmediate`, & http2 support
  * Remove `unpipe`

* [serve-static@2.2.0](https://github.com/expressjs/serve-static/releases/tag/v2.2.0)

***

## [Thanks and What’s Next](#thanks-and-whats-next)

Thanks so much to everyone involved in Express over the past year, the work all our contributors have put in is incredible, and we couldn’t do it without them. If you are not able to become a contributor yourself, please consider asking your companies to support the project financially on [OpenCollective](https://opencollective.com/express).

As we look ahead, we’re excited to keep building momentum. If you haven’t read it yet, our [Rewind 2024 + 2025 Vision blog post](/en/blog/2025-01-09-rewind-2024-triumphs-and-2025-vision/) lays out where we’ve been and where we’re headed. This includes performances scoped packages, better automation, security hardening, and more.

One major initiative is our new [Performance Working Group](https://github.com/expressjs/discussions/pull/306), focused on identifying and fixing long-standing bottlenecks in Express. We’re grateful to be kicking this off with support from the [Sovereign Tech Fund (STF)](https://www.sovereign.tech/), who are helping us invest in long-term sustainability and performance of core infrastructure. Additionally, we will be working to [improve our Typescript DX](https://github.com/expressjs/discussions/issues/192) and taking next steps to [improve the website](https://github.com/expressjs/expressjs.com/issues/1787).

And yes, v6 discussions are already starting to heat up. Keep an eye out for updates, and as always, see you in the issues!

Big thanks to [@wesleytodd](https://github.com/wesleytodd), [@blakeembrey](https://github.com/blakeembrey), [@bjohansebas](https://github.com/bjohansebas), [@UlisesGascon](https://github.com/UlisesGascon), [@Phillip9587](https://github.com/Phillip9587), [@carpasse](https://github.com/carpasse), [@jonchurch](https://github.com/jonchurch), [@ctcpip](https://github.com/ctcpip), [@inigomarquinez](https://github.com/inigomarquinez), [@carlosstenzel](https://github.com/carlosstenzel), [@crandmck](https://github.com/crandmck), [@chrisdel101](https://github.com/chrisdel101), [@dpopp07](https://github.com/dpopp07), [@Ayoub-Mabrouk](https://github.com/Ayoub-Mabrouk), [@jonkoops](https://github.com/jonkoops), [@IamLizu](https://github.com/IamLizu), [@marco-ippolito](https://github.com/marco-ippolito), [@ipreencekmr](https://github.com/ipreencekmr), [@ShubhamOulkar](https://github.com/ShubhamOulkar), [@raksbisht](https://github.com/raksbisht), [@jeffreybaird](https://github.com/jeffreybaird), [@dougwilson](https://github.com/dougwilson), [@mertcanaltin](https://github.com/mertcanaltin), [@GeorgeShvab](https://github.com/GeorgeShvab), [@RobinTail](https://github.com/RobinTail), [@EvanHahn](https://github.com/EvanHahn), [@rhodgkins](https://github.com/rhodgkins), [@cengizcmataraci](https://github.com/cengizcmataraci), [@Shantanugupta43](https://github.com/Shantanugupta43), [@italojs](https://github.com/italojs), [@ljharb](https://github.com/ljharb), [@MaoShizhong](https://github.com/MaoShizhong), [@aroyan](https://github.com/aroyan), [@Binilkks](https://github.com/Binilkks), [@danielgindi](https://github.com/danielgindi), [@papandreou](https://github.com/papandreou), [@jsoref](https://github.com/jsoref), [@bigbigDreamer](https://github.com/bigbigDreamer), [@broofa](https://github.com/broofa), [@CommanderRoot](https://github.com/CommanderRoot), [@andvea](https://github.com/andvea), [@juanarbol](https://github.com/juanarbol), [@agungjati](https://github.com/agungjati), [@alexandercerutti](https://github.com/alexandercerutti), [@pr4j3sh](https://github.com/pr4j3sh), [@hamirmahal](https://github.com/hamirmahal), [@slagiewka](https://github.com/slagiewka), [@Abdel-Monaam-Aouini](https://github.com/Abdel-Monaam-Aouini), [@sazk07](https://github.com/sazk07), [@bhavya3024](https://github.com/bhavya3024), [@joshbuker](https://github.com/joshbuker), [@almic](https://github.com/almic), [@FDrag0n](https://github.com/FDrag0n), [@Dmitry-Kondar](https://github.com/Dmitry-Kondar), [@attrid](https://github.com/attrid), [@kristof-low](https://github.com/kristof-low), [@gireeshpunathil](https://github.com/gireeshpunathil), [@UzairJ99](https://github.com/UzairJ99), [@choi2021](https://github.com/choi2021), [@hayden36](https://github.com/hayden36), [@joharkhan99](https://github.com/joharkhan99), [@peterh-capella](https://github.com/peterh-capella), [@johnburnett](https://github.com/johnburnett), [@nicolasgandrade](https://github.com/nicolasgandrade), [@axhuwastaken](https://github.com/axhuwastaken), [@abhijeetpandit7](https://github.com/abhijeetpandit7), [@peterdanwan](https://github.com/peterdanwan), [@rehmansheikh222](https://github.com/rehmansheikh222), [@corydalis10](https://github.com/corydalis10), [@mgsantos177](https://github.com/mgsantos177), [@wilyJ80](https://github.com/wilyJ80), [@LuiGeeDev](https://github.com/LuiGeeDev), [@juliogarciape](https://github.com/juliogarciape), [@aelmardhi](https://github.com/aelmardhi), [@Ahmed1monm](https://github.com/Ahmed1monm), [@erensarac](https://github.com/erensarac), [@tomasz13nocon](https://github.com/tomasz13nocon), [@tianbuyung](https://github.com/tianbuyung), [@GreyTearsDev](https://github.com/GreyTearsDev), [@aastha-cse](https://github.com/aastha-cse), [@krzysdz](https://github.com/krzysdz), [@Miguelrom](https://github.com/Miguelrom), [@bnoordhuis](https://github.com/bnoordhuis), [@MehfoozurRehman](https://github.com/MehfoozurRehman), [@EasonLin0716](https://github.com/EasonLin0716), [@grjan7](https://github.com/grjan7), [@mishrasur7](https://github.com/mishrasur7), [@gregfenton](https://github.com/gregfenton), [@zareefhasan](https://github.com/zareefhasan), [@Tejas150](https://github.com/Tejas150), [@jpricardo](https://github.com/jpricardo), [@nikeee](https://github.com/nikeee), [@dotnetCarpenter](https://github.com/dotnetCarpenter), [@engpetermwangi](https://github.com/engpetermwangi), [@msimerson](https://github.com/msimerson), [@fetsorn](https://github.com/fetsorn), [@manoharreddyporeddy](https://github.com/manoharreddyporeddy), [@lancatlin](https://github.com/lancatlin), [@mifi](https://github.com/mifi), [@meowingwhitey](https://github.com/meowingwhitey), [@sheplu](https://github.com/sheplu), [@krsriq](https://github.com/krsriq), [@ravibisht](https://github.com/ravibisht), [@wojtekmaj](https://github.com/wojtekmaj), [@aqeelat](https://github.com/aqeelat), [@melikhov-dev](https://github.com/melikhov-dev), [@alexstrat](https://github.com/alexstrat), [@isnifer](https://github.com/isnifer), [@TorstenDittmann](https://github.com/TorstenDittmann), [@Uzlopak](https://github.com/Uzlopak), [@gurgunday](https://github.com/gurgunday), [@kurtextrem](https://github.com/kurtextrem), [@hdtmccallie](https://github.com/hdtmccallie), [@proudparrot2](https://github.com/proudparrot2), [@bewinsnw](https://github.com/bewinsnw), [@jonboulle](https://github.com/jonboulle), [@alexander-akait](https://github.com/alexander-akait), [@alxndrsn](https://github.com/alxndrsn), [@DimitriPapadopoulos](https://github.com/DimitriPapadopoulos), [@greggman](https://github.com/greggman), [@jkbach](https://github.com/jkbach), [@julien-c](https://github.com/julien-c), [@risu729](https://github.com/risu729), [@JohnSimumatik](https://github.com/JohnSimumatik), [@dhouck](https://github.com/dhouck), [@pedro-php](https://github.com/pedro-php), [@aminerol](https://github.com/aminerol), [@robertsky](https://github.com/robertsky), [@ipetrouchtchak-fi](https://github.com/ipetrouchtchak-fi), [@tinhochu](https://github.com/tinhochu), [@Lord-Kamina](https://github.com/Lord-Kamina), [@joshkel](https://github.com/joshkel), [@raiandexter0607](https://github.com/raiandexter0607), [@NateEag](https://github.com/NateEag), [@rmhaiderali](https://github.com/rmhaiderali), [@ljeda](https://github.com/ljeda)

## More from Express

[announcements](/en/blog/2026-05-18-a-new-look-for-express)

## [A New Look for Express](/en/blog/2026-05-18-a-new-look-for-express)

[Sebastian BeltranMay 18, 2026](/en/blog/2026-05-18-a-new-look-for-express)

[announcements](/en/blog/2025-05-16-express-cleanup-legacy-packages)

## [Spring Cleaning in Express.js: Deprecations and the Path Ahead](/en/blog/2025-05-16-express-cleanup-legacy-packages)

[Express Technical CommitteeMay 16, 2025](/en/blog/2025-05-16-express-cleanup-legacy-packages)

[announcements](/en/blog/2025-01-09-rewind-2024-triumphs-and-2025-vision)

## [A New Chapter for Express.js: Triumphs of 2024 and an ambitious 2025](/en/blog/2025-01-09-rewind-2024-triumphs-and-2025-vision)

[Express Technical CommitteeJanuary 9, 2025](/en/blog/2025-01-09-rewind-2024-triumphs-and-2025-vision)

### Interested in writing a post? Check out our guidelines to get started.

[Read the guidelines](/en/blog/write-post)

----
url: https://expressjs.com/en/advanced/healthcheck-graceful-shutdown
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/advanced/healthcheck-graceful-shutdown.mdx)

# [Health Checks and Graceful Shutdown](#overview)

## [Graceful shutdown](#graceful-shutdown)

When you deploy a new version of your application, you must replace the previous version. The process manager you’re using will first send a SIGTERM signal to the application to notify it that it will be killed. Once the application gets this signal, it should stop accepting new requests, finish all the ongoing requests, clean up the resources it used, including database connections and file locks then exit.

### [Example](#example)

```
const server = app.listen(port);


process.on('SIGTERM', () => {
  debug('SIGTERM signal received: closing HTTP server');
  server.close(() => {
    debug('HTTP server closed');
  });
});
```

## [Health checks](#health-checks)

A load balancer uses health checks to determine if an application instance is healthy and can accept requests. For example, [Kubernetes has two health checks](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes//):

* `liveness`, that determines when to restart a container.
* `readiness`, that determines when a container is ready to start accepting traffic. When a pod is not ready, it is removed from the service load balancers.

----
url: https://expressjs.com/en/resources/community
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/community.mdx)

# [Community](#overview)

## [Technical committee](#technical-committee)

The Express technical committee meets online every two weeks (as needed) to discuss development and maintenance of Express, and other issues relevant to the Express project. Each meeting is typically announced in an [expressjs/discussions issue](https://github.com/expressjs/discussions/issues) with a link to join or view the meeting, which is open to all observers.

The meetings are recorded; for a list of the recordings, see the [Express.js YouTube channel](https://www.youtube.com/channel/UCYjxjAeH6TRik9Iwy5nXw7g).

Members of the Express technical committee are:

**Active:**

* [@blakeembrey](https://github.com/blakeembrey) - Blake Embrey
* [@crandmck](https://github.com/crandmck) - Rand McKinney
* [@LinusU](https://github.com/LinusU) - Linus Unnebäck
* [@ulisesgascon](https://github.com/ulisesGascon) - Ulises Gascón
* [@sheplu](https://github.com/sheplu) - Jean Burellier
* [@wesleytodd](https://github.com/wesleytodd) - Wes Todd
* [@jonchurch](https://github.com/jonchurch) - Jon Church
* [@ctcpip](https://github.com/ctcpip/) - Chris de Almeida

**Inactive:**

* [@dougwilson](https://github.com/dougwilson) - Douglas Wilson
* [@hacksparrow](https://github.com/hacksparrow) - Hage Yaapa
* [@jonathanong](https://github.com/jonathanong) - jongleberry
* [@niftylettuce](https://github.com/niftylettuce) - niftylettuce
* [@troygoode](https://github.com/troygoode) - Troy Goode

## [Express is made of many modules](#express-is-made-of-many-modules)

Our vibrant community has created a large variety of extensions, [middleware modules](/en/resources/middleware/) and higher-level frameworks.

Additionally, the Express community maintains modules in these two GitHub orgs:

* [jshttp](https://github.com/jshttp) modules providing useful utility functions; see [Utility modules](/en/resources/utils/).
* [pillarjs](https://github.com/pillarjs): low-level modules that Express uses internally.

To keep up with what is going on in the whole community, check out the [ExpressJS StatusBoard](https://expressjs.github.io/statusboard/).

## [Issues](#issues)

If you’ve come across what you think is a bug, or just want to make a feature request open a ticket in the [issue queue](https://github.com/expressjs/express/issues).

## [Examples](#examples)

View dozens of Express application [examples](https://github.com/expressjs/express/tree/master/examples) in the repository covering everything from API design and authentication to template engine integration.

## [GitHub Discussions](#github-discussions)

The [GitHub Discussions](https://github.com/expressjs/discussions) section is an excellent space to engage in conversations about the development and maintenance of Express, as well as to share ideas and discuss topics related to its usage.

## [Express.js Logo](#expressjs-logo)

Express is a project of the OpenJS Foundation. Please review the [trademark policy](https://trademark-policy.openjsf.org/) for information about permissible use of Express.js logos and marks.

### [Wordmark](#wordmark)

[Download](/images/logos/logo-express-black.svg)

[Download](/images/logos/logo-express-white.svg)

### [Glyph](#glyph)

[Download](/images/logos/logo-white.svg)

[Download](/images/logos/logo-dark.svg)

### [Kawaii](#kawaii)

This logo was created by [SAWARATSUKI](https://github.com/SAWARATSUKI).

[Download](/images/logos/express-kawaii.webp)

[Download](/images/logos/express-kawaii.webp)

----
url: https://expressjs.com/en/5x/guide/error-handling
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/guide/error-handling.mdx)

# [Error Handling](#overview)

*Error Handling* refers to how Express catches and processes errors that occur both synchronously and asynchronously. Express comes with a default error handler so you don’t need to write your own to get started.

## [Catching Errors](#catching-errors)

It’s important to ensure that Express catches all errors that occur while running route handlers and middleware.

### [Errors in synchronous code](#errors-in-synchronous-code)

Errors that occur in synchronous code inside route handlers and middleware require no extra work. If synchronous code throws an error, then Express will catch and process it. For example:

```
app.get('/', (req, res) => {
  throw new Error('BROKEN'); // Express will catch this on its own.
});
```

```
import { type Request, type Response } from 'express';


app.get('/', (req: Request, res: Response) => {
  throw new Error('BROKEN'); // Express will catch this on its own.
});
```

### [Errors in asynchronous code](#errors-in-asynchronous-code)

The recommended way to write asynchronous handlers is with `async` functions. Route handlers and middleware that return a Promise call `next(value)` automatically when they reject or throw an error, and `async` functions always return a Promise, so their errors reach Express with no extra work. For example:

```
app.get('/user/:id', async (req, res) => {
  const user = await getUserById(req.params.id);
  res.send(user);
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/:id', async (req: Request, res: Response) => {
  const user = await getUserById(req.params.id);
  res.send(user);
});
```

If `getUserById` throws an error or rejects, `next` will be called with either the thrown error or the rejected value. If no rejected value is provided, `next` will be called with a default Error object provided by the Express router.

If you pass anything to the `next()` function (except the string `'route'`), Express regards the current request as being an error and will skip any remaining non-error handling routing and middleware functions.

### [Working with promise chains](#working-with-promise-chains)

If you build a promise chain instead of using an `async` function, return the promise from the handler and Express will likewise call `next` automatically when it rejects:

```
app.get('/', (req, res) => {
  return Promise.resolve().then(() => {
    throw new Error('BROKEN'); // Express will catch this and call next.
  });
});
```

```
import { type Request, type Response } from 'express';


app.get('/', (req: Request, res: Response) => {
  return Promise.resolve().then(() => {
    throw new Error('BROKEN'); // Express will catch this and call next.
  });
});
```

If the promise is not returned, Express does not know it exists, and you must route the error yourself by providing `next` as the final catch handler. Without it, the rejection would be unhandled and crash the process:

```
app.get('/', (req, res, next) => {
  Promise.resolve()
    .then(() => {
      throw new Error('BROKEN');
    })
    .catch(next); // Errors will be passed to Express.
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get('/', (req: Request, res: Response, next: NextFunction) => {
  Promise.resolve()
    .then(() => {
      throw new Error('BROKEN');
    })
    .catch(next); // Errors will be passed to Express.
});
```

This works because if a callback in the promise chain throws, the chain turns that exception into a rejection, which travels down to the final `.catch`. There, `.catch` calls its handler with the error as the first argument, which is exactly the argument `next` expects, so the error reaches Express.

### [Working with callback APIs](#working-with-callback-apis)

Errors produced by callback-based APIs, such as those in `node:fs`, are not thrown and are not part of any promise. The callback receives them as its first argument, and you must pass them to the `next()` function yourself, where Express will catch and process them. For example:

```
app.get('/', (req, res, next) => {
  fs.readFile('/file-does-not-exist', (err, data) => {
    if (err) {
      next(err); // Pass errors to Express.
    } else {
      res.send(data);
    }
  });
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get('/', (req: Request, res: Response, next: NextFunction) => {
  fs.readFile('/file-does-not-exist', (err, data) => {
    if (err) {
      next(err); // Pass errors to Express.
    } else {
      res.send(data);
    }
  });
});
```

If the callback in a sequence provides no data, only errors, you can simplify this code as follows:

```
app.get('/', [
  function (req, res, next) {
    fs.writeFile('/inaccessible-path', 'data', next);
  },
  function (req, res) {
    res.send('OK');
  },
]);
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get('/', [
  function (req: Request, res: Response, next: NextFunction) {
    fs.writeFile('/inaccessible-path', 'data', next);
  },
  function (req: Request, res: Response) {
    res.send('OK');
  },
]);
```

In the above example, `next` is provided as the callback for `fs.writeFile`, which is called with or without errors. If there is no error, the second handler is executed, otherwise Express catches and processes the error.

You could also use a chain of handlers to rely on synchronous error catching, by reducing the asynchronous code to something trivial. For example:

```
app.get('/', [
  function (req, res, next) {
    fs.readFile('/maybe-valid-file', 'utf-8', (err, data) => {
      res.locals.data = data;
      next(err);
    });
  },
  function (req, res) {
    res.locals.data = res.locals.data.split(',')[1];
    res.send(res.locals.data);
  },
]);
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get('/', [
  function (req: Request, res: Response, next: NextFunction) {
    fs.readFile('/maybe-valid-file', 'utf-8', (err, data) => {
      res.locals.data = data;
      next(err);
    });
  },
  function (req: Request, res: Response) {
    res.locals.data = res.locals.data.split(',')[1];
    res.send(res.locals.data);
  },
]);
```

The above example contains a couple of trivial statements following the `readFile` call. If `readFile` causes an error, then it passes the error to Express, otherwise you quickly return to the world of synchronous error handling in the next handler in the chain. Then, the example above tries to process the data. If this fails, then the synchronous error handler will catch it. If you had done this processing inside the `readFile` callback, then the application might exit and the Express error handlers would not run.

Finally, for asynchronous code that provides no error-first callback, such as a timer, catch errors inside the asynchronous code itself and pass them to Express:

```
app.get('/', (req, res, next) => {
  setTimeout(() => {
    try {
      throw new Error('BROKEN');
    } catch (err) {
      next(err);
    }
  }, 100);
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get('/', (req: Request, res: Response, next: NextFunction) => {
  setTimeout(() => {
    try {
      throw new Error('BROKEN');
    } catch (err) {
      next(err);
    }
  }, 100);
});
```

The above example uses a `try...catch` block to catch errors in the asynchronous code and pass them to Express. If the `try...catch` block were omitted, Express would not catch the error since it is not part of the synchronous handler code.

```
function errorHandler(err, req, res, next) {
  if (res.headersSent) {
    return next(err);
  }
  res.status(500);
  res.render('error', { error: err });
}
```

```
import { type Request, type Response, type NextFunction } from 'express';


function errorHandler(err: Error, req: Request, res: Response, next: NextFunction) {
  if (res.headersSent) {
    return next(err);
  }
  res.status(500);
  res.render('error', { error: err });
}
```

Note that the default error handler can get triggered if you call `next()` with an error in your code more than once, even if custom error handling middleware is in place.

Other error handling middleware can be found at [Express middleware](/en/resources/middleware/).

## [Writing error handlers](#writing-error-handlers)

Define error-handling middleware functions in the same way as other middleware functions, except error-handling functions have four arguments instead of three: `(err, req, res, next)`. For example:

```
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

You define error-handling middleware last, after other `app.use()` and routes calls; for example:

index.cjs

```
const bodyParser = require('body-parser');
const methodOverride = require('method-override');


app.use(
  bodyParser.urlencoded({
    extended: true,
  })
);
app.use(bodyParser.json());
app.use(methodOverride());
app.use((err, req, res, next) => {
  // logic
});
```

index.mjs

```
import bodyParser from 'body-parser';
import methodOverride from 'method-override';


app.use(
  bodyParser.urlencoded({
    extended: true,
  })
);
app.use(bodyParser.json());
app.use(methodOverride());
app.use((err, req, res, next) => {
  // logic
});
```

index.ts

```
import { type Request, type Response, type NextFunction } from 'express';
import bodyParser from 'body-parser';
import methodOverride from 'method-override';


app.use(
  bodyParser.urlencoded({
    extended: true,
  })
);
app.use(bodyParser.json());
app.use(methodOverride());
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  // logic
});
```

Responses from within a middleware function can be in any format, such as an HTML error page, a simple message, or a JSON string.

For organizational (and higher-level framework) purposes, you can define several error-handling middleware functions, much as you would with regular middleware functions. For example, to define an error-handler for requests made by using `XHR` and those without:

index.cjs

```
const bodyParser = require('body-parser');
const methodOverride = require('method-override');


app.use(
  bodyParser.urlencoded({
    extended: true,
  })
);
app.use(bodyParser.json());
app.use(methodOverride());
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHandler);
```

index.mjs

```
import bodyParser from 'body-parser';
import methodOverride from 'method-override';


app.use(
  bodyParser.urlencoded({
    extended: true,
  })
);
app.use(bodyParser.json());
app.use(methodOverride());
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHandler);
```

In this example, the generic `logErrors` might write request and error information to `stderr`, for example:

```
function logErrors(err, req, res, next) {
  console.error(err.stack);
  next(err);
}
```

```
import { type Request, type Response, type NextFunction } from 'express';


function logErrors(err: Error, req: Request, res: Response, next: NextFunction) {
  console.error(err.stack);
  next(err);
}
```

Also in this example, `clientErrorHandler` is defined as follows; in this case, the error is explicitly passed along to the next one.

Notice that when you do not call `next` in an error-handling function, you are responsible for writing (and ending) the response. Otherwise, those requests will “hang” and will not be eligible for garbage collection.

```
function clientErrorHandler(err, req, res, next) {
  if (req.xhr) {
    res.status(500).send({ error: 'Something failed!' });
  } else {
    next(err);
  }
}
```

```
import { type Request, type Response, type NextFunction } from 'express';


function clientErrorHandler(err: Error, req: Request, res: Response, next: NextFunction) {
  if (req.xhr) {
    res.status(500).send({ error: 'Something failed!' });
  } else {
    next(err);
  }
}
```

Implement the “catch-all” `errorHandler` function as follows (for example):

```
function errorHandler(err, req, res, next) {
  res.status(500);
  res.render('error', { error: err });
}
```

```
import { type Request, type Response, type NextFunction } from 'express';


function errorHandler(err: Error, req: Request, res: Response, next: NextFunction) {
  res.status(500);
  res.render('error', { error: err });
}
```

If you have a route handler with multiple callback functions, you can use the `route` parameter to skip to the next route handler. For example:

```
app.get(
  '/a_route_behind_paywall',
  (req, res, next) => {
    if (!req.user.hasPaid) {
      // continue handling this request
      next('route');
    } else {
      next();
    }
  },
  (req, res, next) => {
    PaidContent.find((err, doc) => {
      if (err) return next(err);
      res.json(doc);
    });
  }
);
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get(
  '/a_route_behind_paywall',
  (req: Request, res: Response, next: NextFunction) => {
    if (!req.user.hasPaid) {
      // continue handling this request
      next('route');
    } else {
      next();
    }
  },
  (req: Request, res: Response, next: NextFunction) => {
    PaidContent.find((err, doc) => {
      if (err) return next(err);
      res.json(doc);
    });
  }
);
```

In this example, the `getPaidContent` handler will be skipped but any remaining handlers in `app` for `/a_route_behind_paywall` would continue to be executed.

### Note

Calls to `next()` and `next(err)` indicate that the current handler is complete and in what state. `next(err)` will skip all remaining handlers in the chain except for those that are set up to handle errors as described above.

----
url: https://expressjs.com/en/blog/2026-03-30-security-releases
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2026-03-30-security-releases)

security

# [March 2026 Security Releases](#overview)

Ulises GasconMarch 30, 2026

[](https://x.com/intent/tweet?text=March%202026%20Security%20Releases\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-03-30-security-releases%2F)[](https://bsky.app/intent/compose?text=March%202026%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-03-30-security-releases%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-03-30-security-releases%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-03-30-security-releases%2F\&text=March%202026%20Security%20Releases)[](https://wa.me/?text=March%202026%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-03-30-security-releases%2F)[](/feed.xml)

The Express team has released new patch versions of [path-to-regexp](https://www.npmjs.com/package/path-to-regexp) addressing three regular expression denial of service vulnerabilities.

### Warning

We recommend upgrading to the latest version of path-to-regexp to secure your applications. If you have a `package-lock.json`, you can update the dependency by running:

Terminal window

```
npm update path-to-regexp
```

The following vulnerabilities have been addressed:

* [CVE-2026-4867 in path-to-regexp utility module (High)](#cve-2026-4867-in-path-to-regexp-utility-module-high)
* [CVE-2026-4926 in path-to-regexp utility module (High)](#cve-2026-4926-in-path-to-regexp-utility-module-high)
* [CVE-2026-4923 in path-to-regexp utility module (Medium)](#cve-2026-4923-in-path-to-regexp-utility-module-medium)

## [CVE-2026-4867 in path-to-regexp utility module (High)](#cve-2026-4867-in-path-to-regexp-utility-module-high)

**[path-to-regexp](https://www.npmjs.com/package/path-to-regexp) versions `<= 0.1.12` are vulnerable to regular expression denial of service via multiple route parameters**

A bad regular expression is generated any time you have three or more parameters within a single segment, separated by something that is not a period. For example, `/:a-:b-:c`. The backtrack protection added in v0.1.12 only prevents ambiguity for two parameters. With three or more, the generated lookahead does not block single separator characters, causing catastrophic backtracking.

**Affected versions**: `<= 0.1.12`\
**Patched version**: `>= 0.1.13`

For more details, see [GHSA-37ch-88jc-xwx2](https://github.com/pillarjs/path-to-regexp/security/advisories/GHSA-37ch-88jc-xwx2).

## [CVE-2026-4926 in path-to-regexp utility module (High)](#cve-2026-4926-in-path-to-regexp-utility-module-high)

**[path-to-regexp](https://www.npmjs.com/package/path-to-regexp) versions `>= 8.0.0` are vulnerable to denial of service via sequential optional groups**

A bad regular expression is generated any time you have multiple sequential optional groups, such as `{a}{b}{c}:z`. The generated regex grows exponentially with the number of groups, causing denial of service. Avoid passing user-controlled input as route patterns.

**Affected versions**: `>= 8.0.0`\
**Patched version**: `>= 8.4.0`

For more details, see [GHSA-j3q9-mxjg-w52f](https://github.com/pillarjs/path-to-regexp/security/advisories/GHSA-j3q9-mxjg-w52f).

## [CVE-2026-4923 in path-to-regexp utility module (Medium)](#cve-2026-4923-in-path-to-regexp-utility-module-medium)

**[path-to-regexp](https://www.npmjs.com/package/path-to-regexp) versions `>= 8.0.0, <= 8.3.0` are vulnerable to regular expression denial of service via multiple wildcards**

When using multiple wildcards combined with at least one parameter, a regular expression can be generated that is vulnerable to ReDoS. The second wildcard must be somewhere other than the end of the path. For example, `/*foo-*bar-:baz`.

**Affected versions**: `>= 8.0.0, <= 8.3.0`\
**Patched version**: `>= 8.4.0`

For more details, see [GHSA-27v5-c462-wpq7](https://github.com/pillarjs/path-to-regexp/security/advisories/GHSA-27v5-c462-wpq7).

***

We recommend upgrading to the latest version of path-to-regexp to secure your applications.

----
url: https://expressjs.com/en/5x/advanced/developing-template-engines
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/advanced/developing-template-engines.mdx)

# [Developing template engines for Express](#overview)

Use the `app.engine(ext, callback)` method to create your own template engine. `ext` refers to the file extension, and `callback` is the template engine function, which accepts the following items as parameters: the location of the file, the options object, and the callback function.

The following code is an example of implementing a very simple template engine for rendering `.ntl` files.

```
const fs = require('fs'); // this engine requires the fs module
app.engine('ntl', (filePath, options, callback) => {
  // define the template engine
  fs.readFile(filePath, (err, content) => {
    if (err) return callback(err);
    // this is an extremely simple template engine
    const rendered = content
      .toString()
      .replace('#title#', `<title>${options.title}</title>`)
      .replace('#message#', `<h1>${options.message}</h1>`);
    return callback(null, rendered);
  });
});
app.set('views', './views'); // specify the views directory
app.set('view engine', 'ntl'); // register the template engine
```

```
import fs from 'fs'; // this engine requires the fs module
app.engine(
  'ntl',
  (
    filePath: string,
    options: Record<string, any>,
    callback: (e: any, rendered?: string) => void
  ) => {
    // define the template engine
    fs.readFile(filePath, (err, content) => {
      if (err) return callback(err);
      // this is an extremely simple template engine
      const rendered = content
        .toString()
        .replace('#title#', `<title>${options.title}</title>`)
        .replace('#message#', `<h1>${options.message}</h1>`);
      return callback(null, rendered);
    });
  }
);
app.set('views', './views'); // specify the views directory
app.set('view engine', 'ntl'); // register the template engine
```

Your app will now be able to render `.ntl` files. Create a file named `index.ntl` in the `views` directory with the following content.

```
#title#
#message#
```

Then, create the following route in your app.

```
app.get('/', (req, res) => {
  res.render('index', { title: 'Hey', message: 'Hello there!' });
});
```

When you make a request to the home page, `index.ntl` will be rendered as HTML.

----
url: https://expressjs.com/en/4x/starter/faq
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/starter/faq.mdx)

# [FAQ](#overview)

## [How should I structure my application?](#how-should-i-structure-my-application)

There is no definitive answer to this question. The answer depends on the scale of your application and the team that is involved. To be as flexible as possible, Express makes no assumptions in terms of structure.

Routes and other application-specific logic can live in as many files as you wish, in any directory structure you prefer. View the following examples for inspiration:

* [Route listings](https://github.com/expressjs/express/blob/v4.22.2/examples/route-separation/index.js#L34-L49)
* [Route map](https://github.com/expressjs/express/blob/v4.22.2/examples/route-map/index.js#L55-L69)

```
app.use((req, res, next) => {
  res.status(404).send("Sorry can't find that!");
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use((req: Request, res: Response, next: NextFunction) => {
  res.status(404).send("Sorry can't find that!");
});
```

Add routes dynamically at runtime on an instance of `express.Router()` so the routes are not superseded by a middleware function.

## [How do I setup an error handler?](#how-do-i-setup-an-error-handler)

You define error-handling middleware in the same way as other middleware, except with four arguments instead of three; specifically with the signature `(err, req, res, next)`:

```
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

## [How do I render plain HTML?](#how-do-i-render-plain-html)

You don’t! There’s no need to “render” HTML with the `res.render()` function. If you have a specific file, use the `res.sendFile()` function. If you are serving many assets from a directory, use the `express.static()` middleware function.

## [What version of Node.js does Express require?](#what-version-of-nodejs-does-express-require)

* [Express 4.x](/en/4x/api/) requires Node.js 0.10 or higher.
* [Express 5.x](/en/5x/api/) requires Node.js 18 or higher.

----
url: https://expressjs.com/en/5x/guide/behind-proxies
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/guide/behind-proxies.mdx)

# [Express behind proxies](#overview)

When running an Express app behind a reverse proxy, some of the Express APIs may return different values than expected. In order to adjust for this, the `trust proxy` application setting may be used to expose information provided by the reverse proxy in the Express APIs. The most common issue is express APIs that expose the client’s IP address may instead show an internal IP address of the reverse proxy.

### Note

When configuring the `trust proxy` setting, it is important to understand the exact setup of the reverse proxy. Since this setting will trust values provided in the request, it is important that the combination of the setting in Express matches how the reverse proxy operates.

The application setting `trust proxy` may be set to one of the values listed in the following table.

| Type         | Value                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Boolean      | If `true`, the client’s IP address is understood as the left-most entry in the `X-Forwarded-For` header.If `false`, the app is understood as directly facing the client and the client’s IP address is derived from `req.socket.remoteAddress`. This is the default setting.### WarningWhen setting to `true`, it is important to ensure that the last reverse proxy trusted is removing/overwriting all of the following HTTP headers: `X-Forwarded-For`, `X-Forwarded-Host`, and `X-Forwarded-Proto`, otherwise it may be possible for the client to provide any value.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| IP addresses | An IP address, subnet, or an array of IP addresses and subnets to trust as being a reverse proxy. The following list shows the pre-configured subnet names:- loopback - `127.0.0.1/8`, `::1/128`
- linklocal - `169.254.0.0/16`, `fe80::/10`
- uniquelocal - `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `fc00::/7`You can set IP addresses in any of the following ways:```
app.set('trust proxy', 'loopback'); // specify a single subnet
app.set('trust proxy', 'loopback, 123.123.123.123'); // specify a subnet and an address
app.set('trust proxy', 'loopback, linklocal, uniquelocal'); // specify multiple subnets as CSV
app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']); // specify multiple subnets as an array
```When specified, the IP addresses or the subnets are excluded from the address determination process, and the untrusted IP address nearest to the application server is determined as the client’s IP address. This works by checking if `req.socket.remoteAddress` is trusted. If so, then each address in `X-Forwarded-For` is checked from right to left until the first non-trusted address. |
| Number       | Use the address that is at most `n` number of hops away from the Express application. `req.socket.remoteAddress` is the first hop, and the rest are looked for in the `X-Forwarded-For` header from right to left. A value of `0` means that the first untrusted address would be `req.socket.remoteAddress`, i.e. there is no reverse proxy.### WarningWhen using this setting, it is important to ensure there are not multiple, different-length paths to the Express application such that the client can be less than the configured number of hops away, otherwise it may be possible for the client to provide any value.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| Function     | Custom trust implementation.```
app.set('trust proxy', (ip) => {
  if (ip === '127.0.0.1' || ip === '123.123.123.123')
    return true; // trusted IPs
  else return false;
});
``````
app.set('trust proxy', (ip: string) => {
  if (ip === '127.0.0.1' || ip === '123.123.123.123')
    return true; // trusted IPs
  else return false;
});
```                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |

Enabling `trust proxy` will have the following impact:

* The value of [req.hostname](/en/5x/api/request/#reqhostname) is derived from the value set in the `X-Forwarded-Host` header, which can be set by the client or by the proxy.

* `X-Forwarded-Proto` can be set by the reverse proxy to tell the app whether it is `https` or `http` or even an invalid name. This value is reflected by [req.protocol](/en/5x/api/request/#reqprotocol).

* The [req.ip](/en/5x/api/request/#reqip) and [req.ips](/en/5x/api/request/#reqips) values are populated based on the socket address and `X-Forwarded-For` header, starting at the first untrusted address.

The `trust proxy` setting is implemented using the [proxy-addr](https://www.npmjs.com/package/proxy-addr) package. For more information, see its documentation.

----
url: https://expressjs.com/en/blog/2025-07-18-security-releases
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2025-07-18-security-releases)

security

# [June 2025 Security Releases](#overview)

Ulises GascónJuly 18, 2025

[](https://x.com/intent/tweet?text=June%202025%20Security%20Releases\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-07-18-security-releases%2F)[](https://bsky.app/intent/compose?text=June%202025%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-07-18-security-releases%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-07-18-security-releases%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-07-18-security-releases%2F\&text=June%202025%20Security%20Releases)[](https://wa.me/?text=June%202025%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-07-18-security-releases%2F)[](/feed.xml)

The Express team has released a new patch version of [Multer](https://www.npmjs.com/package/multer), addressing a high-severity vulnerability that could lead to a Denial of Service (DoS) attack.

### Warning

We strongly recommend that all users upgrade to Multer v2.0.1 or later immediately.

This release addresses the following vulnerability:

### [High severity vulnerability CVE-2025-48997 in Multer middleware](#high-severity-vulnerability-cve-2025-48997-in-multer-middleware)

**[Multer](https://www.npmjs.com/package/multer) versions `>=1.4.4-lts.1` and `<2.0.1` are vulnerable to a Denial of Service (DoS) attack.**

An attacker can trigger this vulnerability by sending an upload request with an empty string as the field name. This malformed request causes an unhandled exception, leading to a crash of the server process.

**Affected versions**: `>=1.4.4-lts.1` and `<2.0.1`\
**Patched version**: `2.0.1`

For more details, see [GHSA-g5hg-p3ph-g8qg](https://github.com/expressjs/multer/security/advisories/GHSA-g5hg-p3ph-g8qg).

----
url: https://expressjs.com/en/blog/2025-12-01-security-releases
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2025-12-01-security-releases)

security

# [November 2025 Security Releases](#overview)

Ulises GascónDecember 1, 2025

[](https://x.com/intent/tweet?text=November%202025%20Security%20Releases\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-12-01-security-releases%2F)[](https://bsky.app/intent/compose?text=November%202025%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-12-01-security-releases%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-12-01-security-releases%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-12-01-security-releases%2F\&text=November%202025%20Security%20Releases)[](https://wa.me/?text=November%202025%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-12-01-security-releases%2F)[](/feed.xml)

The Express team has released a new patch version of [body-parser](https://www.npmjs.com/package/body-parser) addressing a moderate-severity security vulnerability.

### Warning

We recommend upgrading to the latest version of body-parser to secure your applications.

The following vulnerabilities have been addressed:

* [CVE-2025-13466 in Body-parser middleware (Moderate)](#cve-2025-13466-in-body-parser-middleware-moderate)

## [CVE-2025-13466 in Body-parser middleware (Moderate)](#cve-2025-13466-in-body-parser-middleware-moderate)

**[body-parser](https://www.npmjs.com/package/body-parser) version `2.2.0` is vulnerable to denial of service when url encoding is used**

body-parser 2.2.0 is vulnerable to denial of service due to inefficient handling of URL-encoded bodies with very large numbers of parameters. An attacker can send payloads containing thousands of parameters within the default 100KB request size limit, causing elevated CPU and memory usage. This can lead to service slowdown or partial outages under sustained malicious traffic.

**Affected versions**: `2.2.0`\
**Patched version**: `>= 2.2.1`

For more details, see [GHSA-wqch-xfxh-vrr4](https://github.com/expressjs/body-parser/security/advisories/GHSA-wqch-xfxh-vrr4).

***

----
url: https://expressjs.com/en/blog/2024-09-29-security-releases
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2024-09-29-security-releases)

security

# [September 2024 Security Releases](#overview)

Ulises GascónSeptember 29, 2024

[](https://x.com/intent/tweet?text=September%202024%20Security%20Releases\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-09-29-security-releases%2F)[](https://bsky.app/intent/compose?text=September%202024%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-09-29-security-releases%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-09-29-security-releases%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-09-29-security-releases%2F\&text=September%202024%20Security%20Releases)[](https://wa.me/?text=September%202024%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-09-29-security-releases%2F)[](/feed.xml)

Recently, the Express team has been made aware of a number of security vulnerabilities in the Express project. We have released a number of patches to address these vulnerabilities.

### Warning

We strongly recommend that you upgrade these modules to the recommended (or latest) version as soon as possible.

The following vulnerabilities have been addressed:

* [High severity vulnerability CVE-2024-45590 in body-parser middleware](#high-severity-vulnerability-cve-2024-45590-in-body-parser-middleware)
* [High severity vulnerability CVE-2024-47178 in basic-auth-connect middleware](#high-severity-vulnerability-cve-2024-47178-in-basic-auth-connect-middleware)
* [Moderate severity vulnerability CVE-2024-43796 in Express core](#moderate-severity-vulnerability-cve-2024-43796-in-express-core)
* [Moderate severity vulnerability CVE-2024-43799 in send utility module](#moderate-severity-vulnerability-cve-2024-43799-in-send-utility-module)
* [Moderate severity vulnerability CVE-2024-43800 in serve-static middleware](#moderate-severity-vulnerability-cve-2024-43800-in-serve-static-middleware)
* [Moderate severity vulnerability CVE-2024-45296 in path-to-regexp utility module](#moderate-severity-vulnerability-cve-2024-45296-in-path-to-regexp-utility-module)

## [High severity vulnerability CVE-2024-45590 in body-parser middleware](#high-severity-vulnerability-cve-2024-45590-in-body-parser-middleware)

**[body-parser](https://www.npmjs.com/package/body-parser) version `<1.20.3` is vulnerable to denial of service when URL-encoding is enabled**

A malicious actor using a specially-crafted payload could flood the server with a large number of requests, resulting in denial of service.

**Affected versions**: `<1.20.3`

**Patched versions**: `>=1.20.3`

This vulnerability was discovered during the [OSTIF audit to Express](https://github.com/expressjs/security-wg/issues/6) and was mitigated by [the Express security triage team](https://github.com/expressjs/security-wg?tab=readme-ov-file#security-triage-team).

For more details, see [GHSA-qwcr-r2fm-qrc7](https://github.com/expressjs/body-parser/security/advisories/GHSA-qwcr-r2fm-qrc7).

## [High severity vulnerability CVE-2024-47178 in basic-auth-connect middleware](#high-severity-vulnerability-cve-2024-47178-in-basic-auth-connect-middleware)

**[basic-auth-connect](https://www.npmjs.com/package/basic-auth-connect) uses a timing-unsafe equality comparison**

basic-auth-connect `<1.1.0` uses a timing-unsafe equality comparison that can leak timing information

**Affected versions**

* `<1.1.0`

**Patched versions**

* `>=1.1.0`

This vulnerability was discovered during the [OSTIF audit to Express](https://github.com/expressjs/security-wg/issues/6) and was mitigated by [the Express Security triage team](https://github.com/expressjs/security-wg?tab=readme-ov-file#security-triage-team).

More details area available in [GHSA-7p89-p6hx-q4fw](https://github.com/expressjs/basic-auth-connect/security/advisories/GHSA-7p89-p6hx-q4fw)

## [Moderate severity vulnerability CVE-2024-43796 in Express core](#moderate-severity-vulnerability-cve-2024-43796-in-express-core)

The core **[express](https://www.npmjs.com/package/express) package is vulnerable to cross-site scripting (XSS) attack via `response.redirect()`**.

In Express version `<4.20.0`, passing untrusted user input—even after sanitizing it—to `response.redirect()` may execute untrusted code.

**Affected versions**:

* `<4.20.0`
* `>=5.0.0-alpha.1`, `<5.0.0`

**Patched versions**:

* `>=4.20.0`
* `>=5.0.0`

This vulnerability was discovered during the [OSTIF audit of Express](https://github.com/expressjs/security-wg/issues/6) and was mitigated by [the Express security triage team](https://github.com/expressjs/security-wg?tab=readme-ov-file#security-triage-team).

For more details, see [GHSA-qw6h-vgh9-j6wx](https://github.com/expressjs/express/security/advisories/GHSA-qw6h-vgh9-j6wx).

## [Moderate severity vulnerability CVE-2024-43799 in send utility module](#moderate-severity-vulnerability-cve-2024-43799-in-send-utility-module)

The **[send](https://www.npmjs.com/package/send) utility module is vulnerable to template injection that can lead to vulnerability to cross-site scripting (XSS) attack**.

Passing untrusted user input—even after sanitizing it—to `SendStream.redirect()` can execute untrusted code.

**Affected versions**: `< 0.19.0`

**Patched versions**: `>=0.19.0`

This vulnerability was discovered during the [OSTIF audit of Express](https://github.com/expressjs/security-wg/issues/6) and was mitigated by [the Express security triage team](https://github.com/expressjs/security-wg?tab=readme-ov-file#security-triage-team).

For more details, see [GHSA-m6fv-jmcg-4jfg](https://github.com/pillarjs/send/security/advisories/GHSA-m6fv-jmcg-4jfg).

## [Moderate severity vulnerability CVE-2024-43800 in serve-static middleware](#moderate-severity-vulnerability-cve-2024-43800-in-serve-static-middleware)

The **[serve-static](https://www.npmjs.com/package/serve-static) middleware module is vulnerable to template injection that can lead to vulnerability to cross-site scripting (XSS) attack**.

Passing untrusted user input—even after sanitizing it—to `redirect()` can execute untrusted code.

**Affected versions**:

* `< 1.16.0`
* `>=2.0.0`, `<2.1.0`

**Patched versions**:

* `>=1.16.0`
* `>=2.1.0`

This vulnerability was discovered during the [OSTIF audit of Express](https://github.com/expressjs/security-wg/issues/6) and was mitigated by [the Express security triage team](https://github.com/expressjs/security-wg?tab=readme-ov-file#security-triage-team).

For more details, see [GHSA-cm22-4g7w-348p](https://github.com/expressjs/serve-static/security/advisories/GHSA-cm22-4g7w-348p)

## [Moderate severity vulnerability CVE-2024-45296 in path-to-regexp utility module](#moderate-severity-vulnerability-cve-2024-45296-in-path-to-regexp-utility-module)

The **[path-to-regexp](https://www.npmjs.com/package/path-to-regexp) utility module is vulnerable to regular expression denial of service (ReDoS) attack**.

A bad regular expression is generated any time you have two parameters within a single segment, separated by something that is not a period (`.`). For example, `/:a-:b`.

Using `/:a-:b` will produce the regular expression `/^\/([^\/]+?)-([^\/]+?)\/?$/`. This can be exploited by a path such as `/a${'-a'.repeat(8_000)}/a`. [OWASP](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS) has a good example of why this occurs, but in essence, the `/a` at the end ensures this route would never match, but due to naive backtracking it will still attempt every combination of the `:a-:b` on the repeated 8,000 `-a`.

Because JavaScript is single-threaded and regex matching runs on the main thread, poor performance will block the event loop and can lead to a DoS. In local benchmarks, exploiting the unsafe regex will result in performance that is over 1000x worse than the safe regex. In a more realistic environment, using Express v4 and ten concurrent connections results in an average latency of \~600ms vs 1ms.

**Affected versions**:

* `>=4.0.0`, `<8.0.0`
* `>=0.2.0`, `<1.9.0`
* `<0.1.10`
* `>=2.0.0`, `<3.3.0`
* `>=4.0.0`, `<6.3.0`

**Patched versions**:

* `>=8.0.0`
* `>=1.9.0`
* `>=0.1.10`
* `>=3.3.0`
* `>=6.3.0`

Thanks to [Blake Embrey](https://github.com/blakeembrey) who reported and created the security patch.

For more details, see [GHSA-9wv6-86v2-598j](https://github.com/pillarjs/path-to-regexp/security/advisories/GHSA-9wv6-86v2-598j)

----
url: https://expressjs.com/en/resources/middleware/cookie-session
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/cookie-session.mdx)

# [cookie-session middleware](#overview)

v2.1.1[GitHub](https://github.com/expressjs/cookie-session)[Changelog](https://github.com/expressjs/cookie-session/releases)[npm](https://www.npmjs.com/package/cookie-session)

Simple cookie-based session middleware.

A user session can be stored in two main ways with cookies: on the server or on the client. This module stores the session data on the client within a cookie, while a module like [express-session](https://www.npmjs.com/package/express-session) stores only a session identifier on the client within a cookie and stores the session data on the server, typically in a database.

The following points can help you choose which to use:

* `cookie-session` does not require any database / resources on the server side, though the total session data cannot exceed the browser’s max cookie size.
* `cookie-session` can simplify certain load-balanced scenarios.
* `cookie-session` can be used to store a “light” session and include an identifier to look up a database-backed secondary store to reduce database lookups.

**NOTE** This module does not encrypt the session contents in the cookie, only provides signing to prevent tampering. The client will be able to read the session data by examining the cookie’s value. Secret data should not be set in `req.session` without encrypting it, or use a server-side session instead.

**NOTE** This module does not prevent session replay, as the expiration set is that of the cookie only; if that is a concern of your application, you can store an expiration date in `req.session` object and validate it on the server, and implement any other logic to extend the session as your application needs.

## [Install](#install)

This is a [Node.js](https://nodejs.org/en/) module available through the [npm registry](https://www.npmjs.com/). Installation is done using the [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):

Terminal window

```
npm install cookie-session
```

Terminal window

```
yarn add cookie-session
```

Terminal window

```
pnpm add cookie-session
```

Terminal window

```
bun add cookie-session
```

### Note

`cookie-session` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/cookie-session
```

Terminal window

```
yarn add --dev @types/cookie-session
```

Terminal window

```
pnpm add --save-dev @types/cookie-session
```

Terminal window

```
bun add --dev @types/cookie-session
```

## [API](#api)

```
var cookieSession = require('cookie-session');
var express = require('express');


var app = express();


app.use(
  cookieSession({
    name: 'session',
    keys: [
      /* secret keys */
    ],


    // Cookie Options
    maxAge: 24 * 60 * 60 * 1000, // 24 hours
  })
);
```

### [cookieSession(options)](#cookiesessionoptions)

Create a new cookie session middleware with the provided options. This middleware will attach the property `session` to `req`, which provides an object representing the loaded session. This session is either a new session if no valid session was provided in the request, or a loaded session from the request.

The middleware will automatically add a `Set-Cookie` header to the response if the contents of `req.session` were altered. *Note* that no `Set-Cookie` header will be in the response (and thus no session created for a specific user) unless there are contents in the session, so be sure to add something to `req.session` as soon as you have identifying information to store for the session.

#### [Options](#options)

Cookie session accepts these properties in the options object.

##### [name](#name)

The name of the cookie to set, defaults to `session`.

##### [keys](#keys)

The list of keys to use to sign & verify cookie values, or a configured [`Keygrip`](https://www.npmjs.com/package/keygrip) instance. Set cookies are always signed with `keys[0]`, while the other keys are valid for verification, allowing for key rotation. If a `Keygrip` instance is provided, it can be used to change signature parameters like the algorithm of the signature.

##### [secret](#secret)

A string which will be used as single key if `keys` is not provided.

##### [Cookie Options](#cookie-options)

Other options are passed to `cookies.get()` and `cookies.set()` allowing you to control security, domain, path, and signing among other settings.

The options can also contain any of the following (for the full list, see [cookies module documentation](https://www.npmjs.org/package/cookies#readme):

* `maxAge`: a number representing the milliseconds from `Date.now()` for expiry
* `expires`: a `Date` object indicating the cookie’s expiration date (expires at the end of session by default).
* `path`: a string indicating the path of the cookie (`/` by default).
* `domain`: a string indicating the domain of the cookie (no default).
* `partitioned`: a boolean indicating whether to partition the cookie in Chrome for the [CHIPS Update](https://developers.google.com/privacy-sandbox/3pcd/chips) (`false` by default). If this is true, Cookies from embedded sites will be partitioned and only readable from the same top level site from which it was created.
* `priority`: a string indicating the cookie priority. This can be set to `'low'`, `'medium'`, or `'high'`.
* `sameSite`: a boolean or string indicating whether the cookie is a “same site” cookie (`false` by default). This can be set to `'strict'`, `'lax'`, `'none'`, or `true` (which maps to `'strict'`).
* `secure`: a boolean indicating whether the cookie is only to be sent over HTTPS (`false` by default for HTTP, `true` by default for HTTPS). If this is set to `true` and Node.js is not directly over a TLS connection, be sure to read how to [setup Express behind proxies](/en/5x/guide/behind-proxies/) or the cookie may not ever set correctly.
* `httpOnly`: a boolean indicating whether the cookie is only to be sent over HTTP(S), and not made available to client JavaScript (`true` by default).
* `signed`: a boolean indicating whether the cookie is to be signed (`true` by default).
* `overwrite`: a boolean indicating whether to overwrite previously set cookies of the same name (`true` by default).

### [req.session](#reqsession)

Represents the session for the given request.

#### [.isChanged](#ischanged)

Is `true` if the session has been changed during the request.

#### [.isNew](#isnew)

Is `true` if the session is new.

#### [.isPopulated](#ispopulated)

Determine if the session has been populated with data or is empty.

### [req.sessionOptions](#reqsessionoptions)

Represents the session options for the current request. These options are a shallow clone of what was provided at middleware construction and can be altered to change cookie setting behavior on a per-request basis.

### [Destroying a session](#destroying-a-session)

To destroy a session simply set it to `null`:

```
req.session = null;
```

### [Saving a session](#saving-a-session)

Since the entire contents of the session is kept in a client-side cookie, the session is “saved” by writing a cookie out in a `Set-Cookie` response header. This is done automatically if there has been a change made to the session when the Node.js response headers are being written to the client and the session was not destroyed.

## [Examples](#examples)

### [Simple view counter example](#simple-view-counter-example)

```
var cookieSession = require('cookie-session');
var express = require('express');


var app = express();


app.set('trust proxy', 1); // trust first proxy


app.use(
  cookieSession({
    name: 'session',
    keys: ['key1', 'key2'],
  })
);


app.get('/', function (req, res, next) {
  // Update views
  req.session.views = (req.session.views || 0) + 1;


  // Write response
  res.end(req.session.views + ' views');
});


app.listen(3000);
```

### [Per-user sticky max age](#per-user-sticky-max-age)

```
var cookieSession = require('cookie-session');
var express = require('express');


var app = express();


app.set('trust proxy', 1); // trust first proxy


app.use(
  cookieSession({
    name: 'session',
    keys: ['key1', 'key2'],
  })
);


// This allows you to set req.session.maxAge to let certain sessions
// have a different value than the default.
app.use(function (req, res, next) {
  req.sessionOptions.maxAge = req.session.maxAge || req.sessionOptions.maxAge;
  next();
});


// ... your logic here ...
```

### [Extending the session expiration](#extending-the-session-expiration)

This module does not send a `Set-Cookie` header if the contents of the session have not changed. This means that to extend the expiration of a session in the user’s browser (in response to user activity, for example) some kind of modification to the session needs be made.

```
var cookieSession = require('cookie-session');
var express = require('express');


var app = express();


app.use(
  cookieSession({
    name: 'session',
    keys: ['key1', 'key2'],
  })
);


// Update a value in the cookie so that the set-cookie will be sent.
// Only changes every minute so that it's not sent with every request.
app.use(function (req, res, next) {
  req.session.nowInMinutes = Math.floor(Date.now() / 60e3);
  next();
});


// ... your logic here ...
```

### [Using a custom signature algorithm](#using-a-custom-signature-algorithm)

This example shows creating a custom `Keygrip` instance as the `keys` option to provide keys and additional signature configuration.

```
var cookieSession = require('cookie-session');
var express = require('express');
var Keygrip = require('keygrip');


var app = express();


app.use(
  cookieSession({
    name: 'session',
    keys: new Keygrip(['key1', 'key2'], 'SHA384', 'base64'),
  })
);


// ... your logic here ...
```

## [Usage Limitations](#usage-limitations)

### [Max Cookie Size](#max-cookie-size)

Because the entire session object is encoded and stored in a cookie, it is possible to exceed the maximum cookie size limits on different browsers. The [RFC6265 specification](https://tools.ietf.org/html/rfc6265#section-6.1) recommends that a browser **SHOULD** allow

> At least 4096 bytes per cookie (as measured by the sum of the length of the cookie’s name, value, and attributes)

In practice this limit differs slightly across browsers. See a list of [browser limits here](http://browsercookielimits.iain.guru). As a rule of thumb **don’t exceed 4093 bytes per domain**.

If your session object is large enough to exceed a browser limit when encoded, in most cases the browser will refuse to store the cookie. This will cause the following requests from the browser to either a) not have any session information or b) use old session information that was small enough to not exceed the cookie limit.

If you find your session object is hitting these limits, it is best to consider if data in your session should be loaded from a database on the server instead of transmitted to/from the browser with every request. Or move to an [alternative session strategy](https://github.com/expressjs/session#compatible-session-stores)

## [License](#license)

[MIT](https://github.com/expressjs/cookie-session/blob/HEAD/LICENSE)

----
url: https://expressjs.com/en/guide/migrating-4
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/guide/migrating-4.mdx)

# [Moving to Express 4](#overview)

Express 4 is a breaking change from Express 3. That means an existing Express 3 app will *not* work if you update the Express version in its dependencies.

This article covers:

* [Changes in Express 4](#changes-in-express-4).
* [An example](#example-app-migration) of migrating an Express 3 app to Express 4.
* [Upgrading to the Express 4 app generator](#upgrading-to-the-express-4-app-generator).

## [Changes in Express 4](#changes-in-express-4)

There are several significant changes in Express 4:

* [Changes to Express core and middleware system.](#changes-to-express-core-and-middleware-system) The dependencies on Connect and built-in middleware were removed, so you must add middleware yourself.
* [Changes to the routing system.](#the-routing-system)
* [Various other changes.](#other-changes)

See also:

* [New features in 4.x.](https://github.com/expressjs/express/wiki/New-features-in-4.x)
* [Migrating from 3.x to 4.x.](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x)

### [Changes to Express core and middleware system](#changes-to-express-core-and-middleware-system)

Express 4 no longer depends on Connect, and removes all built-in middleware from its core, except for the `express.static` function. This means that Express is now an independent routing and middleware web framework, and Express versioning and releases are not affected by middleware updates.

Without built-in middleware, you must explicitly add all the middleware that is required to run your app. Simply follow these steps:

1. Install the module: `npm install --save <module-name>`
2. In your app, require the module: `require('module-name')`
3. Use the module according to its documentation: `app.use( ... )`

The following table lists Express 3 middleware and their counterparts in Express 4.

| Express 3                | Express 4                                                                                               |
| ------------------------ | ------------------------------------------------------------------------------------------------------- |
| `express.bodyParser`     | [body-parser](https://github.com/expressjs/body-parser) + [multer](https://github.com/expressjs/multer) |
| `express.compress`       | [compression](https://github.com/expressjs/compression)                                                 |
| `express.cookieSession`  | [cookie-session](https://github.com/expressjs/cookie-session)                                           |
| `express.cookieParser`   | [cookie-parser](https://github.com/expressjs/cookie-parser)                                             |
| `express.logger`         | [morgan](https://github.com/expressjs/morgan)                                                           |
| `express.session`        | [express-session](https://github.com/expressjs/session)                                                 |
| `express.favicon`        | [serve-favicon](https://github.com/expressjs/serve-favicon)                                             |
| `express.responseTime`   | [response-time](https://github.com/expressjs/response-time)                                             |
| `express.errorHandler`   | [errorhandler](https://github.com/expressjs/errorhandler)                                               |
| `express.methodOverride` | [method-override](https://github.com/expressjs/method-override)                                         |
| `express.timeout`        | [connect-timeout](https://github.com/expressjs/timeout)                                                 |
| `express.vhost`          | [vhost](https://github.com/expressjs/vhost)                                                             |
| `express.csrf`           | [csurf](https://github.com/expressjs/csurf)                                                             |
| `express.directory`      | [serve-index](https://github.com/expressjs/serve-index)                                                 |
| `express.static`         | [serve-static](https://github.com/expressjs/serve-static)                                               |

Here is the [complete list](https://github.com/senchalabs/connect#middleware) of Express 4 middleware.

In most cases, you can simply replace the old version 3 middleware with its Express 4 counterpart. For details, see the module documentation in GitHub.

#### [`app.use` accepts parameters](#appuse-accepts-parameters)

In version 4 you can use a variable parameter to define the path where middleware functions are loaded, then read the value of the parameter from the route handler. For example:

```
app.use('/book/:id', (req, res, next) => {
  console.log('ID:', req.params.id);
  next();
});
```

### [The routing system](#the-routing-system)

Apps now implicitly load routing middleware, so you no longer have to worry about the order in which middleware is loaded with respect to the `router` middleware.

The way you define routes is unchanged, but the routing system has two new features to help organize your routes:

* A new method, `app.route()`, to create chainable route handlers for a route path.
* A new class, `express.Router`, to create modular mountable route handlers.

#### [`app.route()` method](#approute-method)

The new `app.route()` method enables you to create chainable route handlers for a route path. Because the path is specified in a single location, creating modular routes is helpful, as is reducing redundancy and typos. For more information about routes, see [`Router()` documentation](/en/4x/api/router/).

Here is an example of chained route handlers that are defined by using the `app.route()` function.

```
app
  .route('/book')
  .get((req, res) => {
    res.send('Get a random book');
  })
  .post((req, res) => {
    res.send('Add a book');
  })
  .put((req, res) => {
    res.send('Update the book');
  });
```

#### [`express.Router` class](#expressrouter-class)

The other feature that helps to organize routes is a new class, `express.Router`, that you can use to create modular mountable route handlers. A `Router` instance is a complete middleware and routing system; for this reason it is often referred to as a “mini-app”.

The following example creates a router as a module, loads middleware in it, defines some routes, and mounts it on a path on the main app.

For example, create a router file named `birds.js` in the app directory, with the following content:

birds.cjs

```
var express = require('express');
var router = express.Router();


// middleware specific to this router
router.use((req, res, next) => {
  console.log('Time: ', Date.now());
  next();
});
// define the home page route
router.get('/', (req, res) => {
  res.send('Birds home page');
});
// define the about route
router.get('/about', (req, res) => {
  res.send('About birds');
});


module.exports = router;
```

birds.mjs

```
import express from 'express';


const router = express.Router();


// middleware specific to this router
router.use((req, res, next) => {
  console.log('Time: ', Date.now());
  next();
});
// define the home page route
router.get('/', (req, res) => {
  res.send('Birds home page');
});
// define the about route
router.get('/about', (req, res) => {
  res.send('About birds');
});


export default router;
```

Then, load the router module in the app:

index.cjs

```
var birds = require('./birds');


// ...


app.use('/birds', birds);
```

index.mjs

```
import birds from './birds';


// ...


app.use('/birds', birds);
```

The app will now be able to handle requests to the `/birds` and `/birds/about` paths, and will call the `timeLog` middleware that is specific to the route.

### [Other changes](#other-changes)

The following table lists other small but important changes in Express 4:

| Object                             | Description                                                                                                                                                               |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Node.js                            | Express 4 requires Node.js 0.10.x or later and has dropped support for Node.js 0.8.x.                                                                                     |
| `http.createServer()`              | The `http` module is no longer needed, unless you need to directly work with it (socket.io/SPDY/HTTPS). The app can be started by using the `app.listen()` function.      |
| `app.configure()`                  | The `app.configure()` function has been removed. Use the `process.env.NODE_ENV` or `app.get('env')` function to detect the environment and configure the app accordingly. |
| `json spaces`                      | The `json spaces` application property is disabled by default in Express 4.                                                                                               |
| `req.accepted()`                   | Use `req.accepts()`, `req.acceptsEncodings()`, `req.acceptsCharsets()`, and `req.acceptsLanguages()`.                                                                     |
| `res.location()`                   | No longer resolves relative URLs.                                                                                                                                         |
| `req.params`                       | Was an array; now an object.                                                                                                                                              |
| `res.locals`                       | Was a function; now an object.                                                                                                                                            |
| `res.headerSent`                   | Changed to `res.headersSent`.                                                                                                                                             |
| `app.route`                        | Now available as `app.mountpath`.                                                                                                                                         |
| `res.on('header')`                 | Removed.                                                                                                                                                                  |
| `res.charset`                      | Removed.                                                                                                                                                                  |
| `res.setHeader('Set-Cookie', val)` | Functionality is now limited to setting the basic cookie value. Use `res.cookie()` for added functionality.                                                               |

## [Example app migration](#example-app-migration)

Here is an example of migrating an Express 3 application to Express 4. The files of interest are `app.js` and `package.json`.

### [Version 3 app](#version-3-app)

#### [`app.js`](#appjs)

Consider an Express v.3 application with the following `app.js` file:

index.cjs

```
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');


var app = express();


// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.methodOverride());
app.use(express.session({ secret: 'your secret here' }));
app.use(express.bodyParser());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));


// development only
if (app.get('env') === 'development') {
  app.use(express.errorHandler());
}


app.get('/', routes.index);
app.get('/users', user.list);


http.createServer(app).listen(app.get('port'), () => {
  console.log('Express server listening on port ' + app.get('port'));
});
```

index.mjs

```
import express from 'express';
import routes from './routes';
import user from './routes/user';
import http from 'http';
import path from 'path';


const app = express();


// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.methodOverride());
app.use(express.session({ secret: 'your secret here' }));
app.use(express.bodyParser());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));


// development only
if (app.get('env') === 'development') {
  app.use(express.errorHandler());
}


app.get('/', routes.index);
app.get('/users', user.list);


http.createServer(app).listen(app.get('port'), () => {
  console.log('Express server listening on port ' + app.get('port'));
});
```

#### [`package.json`](#packagejson)

The accompanying version 3 `package.json` file might look something like this:

```
{
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "3.12.0",
    "pug": "*"
  }
}
```

### [Process](#process)

Begin the migration process by installing the required middleware for the Express 4 app and updating Express and Pug to their respective latest version with the following command:

Terminal window

```
npm install serve-favicon morgan method-override express-session body-parser multer errorhandler express@latest pug@latest --save
```

Terminal window

```
yarn add serve-favicon morgan method-override express-session body-parser multer errorhandler express@latest pug@latest
```

Terminal window

```
pnpm add serve-favicon morgan method-override express-session body-parser multer errorhandler express@latest pug@latest
```

Terminal window

```
bun add serve-favicon morgan method-override express-session body-parser multer errorhandler express@latest pug@latest
```

Make the following changes to `app.js`:

1. The built-in Express middleware functions `express.favicon`, `express.logger`, `express.methodOverride`, `express.session`, `express.bodyParser` and `express.errorHandler` are no longer available on the `express` object. You must install their alternatives manually and load them in the app.

2. You no longer need to load the `app.router` function. It is not a valid Express 4 app object, so remove the `app.use(app.router);` code.

3. Make sure that the middleware functions are loaded in the correct order - load `errorHandler` after loading the app routes.

### [Version 4 app](#version-4-app)

#### [`package.json`](#packagejson-1)

Running the above `npm` command will update `package.json` as follows:

```
{
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "body-parser": "^1.5.2",
    "errorhandler": "^1.1.1",
    "express": "^4.8.0",
    "express-session": "^1.7.2",
    "pug": "^2.0.0",
    "method-override": "^2.1.2",
    "morgan": "^1.2.2",
    "multer": "^0.1.3",
    "serve-favicon": "^2.0.1"
  }
}
```

#### [`app.js`](#appjs-1)

Then, remove invalid code, load the required middleware, and make other changes as necessary. The `app.js` file will look like this:

index.cjs

```
var http = require('http');
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var path = require('path');


var favicon = require('serve-favicon');
var logger = require('morgan');
var methodOverride = require('method-override');
var session = require('express-session');
var bodyParser = require('body-parser');
var multer = require('multer');
var errorHandler = require('errorhandler');


var app = express();


// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(favicon(path.join(__dirname, '/public/favicon.ico')));
app.use(logger('dev'));
app.use(methodOverride());
app.use(
  session({
    resave: true,
    saveUninitialized: true,
    secret: 'uwotm8',
  })
);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(multer());
app.use(express.static(path.join(__dirname, 'public')));


app.get('/', routes.index);
app.get('/users', user.list);


// error handling middleware should be loaded after the loading the routes
if (app.get('env') === 'development') {
  app.use(errorHandler());
}


var server = http.createServer(app);
server.listen(app.get('port'), () => {
  console.log('Express server listening on port ' + app.get('port'));
});
```

index.mjs

```
import http from 'http';
import express from 'express';
import routes from './routes';
import user from './routes/user';
import path from 'path';
import favicon from 'serve-favicon';
import logger from 'morgan';
import methodOverride from 'method-override';
import session from 'express-session';
import bodyParser from 'body-parser';
import multer from 'multer';
import errorHandler from 'errorhandler';


const app = express();


// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(favicon(path.join(__dirname, '/public/favicon.ico')));
app.use(logger('dev'));
app.use(methodOverride());
app.use(
  session({
    resave: true,
    saveUninitialized: true,
    secret: 'uwotm8',
  })
);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(multer());
app.use(express.static(path.join(__dirname, 'public')));


app.get('/', routes.index);
app.get('/users', user.list);


// error handling middleware should be loaded after the loading the routes
if (app.get('env') === 'development') {
  app.use(errorHandler());
}


const server = http.createServer(app);
server.listen(app.get('port'), () => {
  console.log('Express server listening on port ' + app.get('port'));
});
```

### Note

Unless you need to work directly with the `http` module (socket.io/SPDY/HTTPS), loading it is not required, and the app can be simply started this way:

```
app.listen(app.get('port'), () => {
  console.log('Express server listening on port ' + app.get('port'));
});
```

### [Run the app](#run-the-app)

The migration process is complete, and the app is now an Express 4 app. To confirm, start the app by using the following command:

Terminal window

```
$ node .
```

Load <http://localhost:3000> and see the home page being rendered by Express 4.

## [Upgrading to the Express 4 app generator](#upgrading-to-the-express-4-app-generator)

The command-line tool to generate an Express app is still `express`, but to upgrade to the new version, you must uninstall the Express 3 app generator and then install the new `express-generator`.

### [Installing](#installing)

If you already have the Express 3 app generator installed on your system, you must uninstall it:

Terminal window

```
npm uninstall -g express
```

Terminal window

```
yarn global remove express
```

Terminal window

```
pnpm remove --global express
```

Terminal window

```
bun remove --global express
```

Depending on how your file and directory privileges are configured, you might need to run this command with `sudo`.

Now install the new generator:

Terminal window

```
npm install -g express-generator
```

Terminal window

```
yarn global add express-generator
```

Terminal window

```
pnpm add --global express-generator
```

Terminal window

```
bun add --global express-generator
```

Depending on how your file and directory privileges are configured, you might need to run this command with `sudo`.

Now the `express` command on your system is updated to the Express 4 generator.

### [Changes to the app generator](#changes-to-the-app-generator)

Command options and use largely remain the same, with the following exceptions:

* Removed the `--sessions` option.
* Removed the `--jshtml` option.
* Added the `--hogan` option to support [Hogan.js](https://twitter.github.io/hogan.js/).

### [Example](#example)

Execute the following command to create an Express 4 app:

Terminal window

```
$ express app4
```

If you look at the contents of the `app4/app.js` file, you will notice that all the middleware functions (except `express.static`) that are required for the app are loaded as independent modules, and the `router` middleware is no longer explicitly loaded in the app.

You will also notice that the `app.js` file is now a Node.js module, in contrast to the standalone app that was generated by the old generator.

After installing the dependencies, start the app by using the following command:

Terminal window

```
$ npm start
```

If you look at the `npm start` script in the `package.json` file, you will notice that the actual command that starts the app is `node ./bin/www`, which used to be `node app.js` in Express 3.

Because the `app.js` file that was generated by the Express 4 generator is now a Node.js module, it can no longer be started independently as an app (unless you modify the code). The module must be loaded in a Node.js file and started via the Node.js file. The Node.js file is `./bin/www` in this case.

Neither the `bin` directory nor the extensionless `www` file is mandatory for creating an Express app or starting the app. They are just suggestions made by the generator, so feel free to modify them to suit your needs.

To get rid of the `www` directory and keep things the “Express 3 way”, delete the line that says `module.exports = app;` at the end of the `app.js` file, then paste the following code in its place:

```
app.set('port', process.env.PORT || 3000);


var server = app.listen(app.get('port'), () => {
  debug('Express server listening on port ' + server.address().port);
});
```

Ensure that you load the `debug` module at the top of the `app.js` file by using the following code:

```
var debug = require('debug')('app4');
```

Next, change `"start": "node ./bin/www"` in the `package.json` file to `"start": "node app.js"`.

You have now moved the functionality of `./bin/www` back to `app.js`. This change is not recommended, but the exercise helps you to understand how the `./bin/www` file works, and why the `app.js` file no longer starts on its own.

----
url: https://expressjs.com/en/4x/starter/examples
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/starter/examples.mdx)

# [Express examples](#overview)

* [auth](https://github.com/expressjs/express/tree/4.x/examples/auth) - Authentication with login and password
* [content-negotiation](https://github.com/expressjs/express/tree/4.x/examples/content-negotiation) - HTTP content negotiation
* [cookie-sessions](https://github.com/expressjs/express/tree/4.x/examples/cookie-sessions) - Working with cookie-based sessions
* [cookies](https://github.com/expressjs/express/tree/4.x/examples/cookies) - Working with cookies
* [downloads](https://github.com/expressjs/express/tree/4.x/examples/downloads) - Transferring files to client
* [ejs](https://github.com/expressjs/express/tree/4.x/examples/ejs) - Working with Embedded JavaScript templating (ejs)
* [error-pages](https://github.com/expressjs/express/tree/4.x/examples/error-pages) - Creating error pages
* [error](https://github.com/expressjs/express/tree/4.x/examples/error) - Working with error middleware
* [hello-world](https://github.com/expressjs/express/tree/4.x/examples/hello-world) - Simple request handler
* [markdown](https://github.com/expressjs/express/tree/4.x/examples/markdown) - Markdown as template engine
* [multi-router](https://github.com/expressjs/express/tree/4.x/examples/multi-router) - Working with multiple Express routers
* [mvc](https://github.com/expressjs/express/tree/4.x/examples/mvc) - MVC-style controllers
* [online](https://github.com/expressjs/express/tree/4.x/examples/online) - Tracking online user activity with `online` and `redis` packages
* [params](https://github.com/expressjs/express/tree/4.x/examples/params) - Working with route parameters
* [resource](https://github.com/expressjs/express/tree/4.x/examples/resource) - Multiple HTTP operations on the same resource
* [route-map](https://github.com/expressjs/express/tree/4.x/examples/route-map) - Organizing routes using a map
* [route-middleware](https://github.com/expressjs/express/tree/4.x/examples/route-middleware) - Working with route middleware
* [route-separation](https://github.com/expressjs/express/tree/4.x/examples/route-separation) - Organizing routes per each resource
* [search](https://github.com/expressjs/express/tree/4.x/examples/search) - Search API
* [session](https://github.com/expressjs/express/tree/4.x/examples/session) - User sessions
* [static-files](https://github.com/expressjs/express/tree/4.x/examples/static-files) - Serving static files
* [vhost](https://github.com/expressjs/express/tree/4.x/examples/vhost) - Working with virtual hosts
* [view-constructor](https://github.com/expressjs/express/tree/4.x/examples/view-constructor) - Rendering views dynamically
* [view-locals](https://github.com/expressjs/express/tree/4.x/examples/view-locals) - Saving data in request object between middleware calls
* [web-service](https://github.com/expressjs/express/tree/4.x/examples/web-service) - Simple API service

## [Additional examples](#additional-examples)

These are some additional examples with more extensive integrations.

### Warning

This information refers to third-party sites, products, or modules that are not maintained by the Expressjs team. Listing here does not constitute an endorsement or recommendation from the Expressjs project team.

* [prisma-rest-api-ts](https://github.com/prisma/prisma-examples/tree/latest/orm/express) - REST API with Express in TypeScript using [Prisma](https://www.npmjs.com/package/prisma) as an ORM

----
url: https://expressjs.com/en/5x/api/response
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/5x/api/response/index.mdx)

# [Response](#overview)

The `res` object represents the HTTP response that an Express app sends when it gets an HTTP request.

In this documentation and by convention, the object is always referred to as `res` (and the HTTP request is `req`) but its actual name is determined by the parameters to the callback function in which you’re working.

For example:

```
app.get('/user/:id', (req, res) => {
  res.send(`user ${req.params.id}`);
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/:id', (req: Request, res: Response) => {
  res.send(`user ${req.params.id}`);
});
```

But you could just as well have:

```
app.get('/user/:id', (request, response) => {
  response.send(`user ${request.params.id}`);
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/:id', (request: Request, response: Response) => {
  response.send(`user ${request.params.id}`);
});
```

The `res` object is an enhanced version of Node’s own response object and supports all [built-in fields and methods](https://nodejs.org/api/http.html#class-httpserverresponse).

## [Properties](#properties)

### [res.app](#resapp)

Type:`Application`

This property holds a reference to the instance of the Express application that is using the middleware.

`res.app` is identical to the [req.app](/en/5x/api/request/#reqapp) property in the request object.

```
app.get('/', (req, res) => {
  console.dir(res.app.get('view engine'));
  console.dir(res.app === req.app);
  // => true
  res.send('OK');
});
```

```
import { type Request, type Response } from 'express';


app.get('/', (req: Request, res: Response) => {
  console.dir(res.app.get('view engine'));
  console.dir(res.app === req.app);
  // => true
  res.send('OK');
});
```

### [res.headersSent](#resheaderssent)

Type:`Boolean`

Boolean property that indicates if the app sent HTTP headers for the response.

```
app.get('/', (req, res) => {
  console.log(res.headersSent); // false
  res.send('OK');
  console.log(res.headersSent); // true
});
```

```
import { type Request, type Response } from 'express';


app.get('/', (req: Request, res: Response) => {
  console.log(res.headersSent); // false
  res.send('OK');
  console.log(res.headersSent); // true
});
```

### [res.locals](#reslocals)

Type:`Object`

Use this property to set variables accessible in templates rendered with [res.render](#resrender). The variables set on `res.locals` are available within a single request-response cycle, and will not be shared between requests.

### Warning

The `locals` object is used by view engines to render a response. The object keys may be particularly sensitive and should not contain user-controlled input, as it may affect the operation of the view engine or provide a path to cross-site scripting. Consult the documentation for the used view engine for additional considerations.

In order to keep local variables for use in template rendering between requests, use [app.locals](/en/5x/api/application/#applocals) instead.

This property is useful for exposing request-level information such as the request path name, authenticated user, user settings, and so on to templates rendered within the application.

```
app.use((req, res, next) => {
  // Make `user` and `authenticated` available in templates
  res.locals.user = req.user;
  res.locals.authenticated = !req.user.anonymous;
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use((req: Request, res: Response, next: NextFunction) => {
  // Make `user` and `authenticated` available in templates
  res.locals.user = req.user;
  res.locals.authenticated = !req.user.anonymous;
  next();
});
```

### [res.req](#resreq)

Type:`Request`

This property holds a reference to the [request object](/en/5x/api/request/) that relates to this response object.

```
app.get('/', (req, res) => {
  console.dir(res.req === req);
  // => true
  res.send('OK');
});
```

```
import { type Request, type Response } from 'express';


app.get('/', (req: Request, res: Response) => {
  console.dir(res.req === req);
  // => true
  res.send('OK');
});
```

Appends the specified `value` to the HTTP response header `field`. If the header is not already set, it creates the header with the specified value. The `value` parameter can be a string or an array.

### Note

calling `res.set()` after `res.append()` will reset the previously-set header value.

```
res.append('Link', ['<http://localhost/>', '<http://localhost:3000/>']);
res.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly');
res.append('Warning', '199 Miscellaneous warning');
```

### [res.attachment()](#resattachment)

#### Arguments

`filename`

Type:`String | undefined`

The file name used to set the `Content-Disposition` “filename=” parameter and the `Content-Type` (from its extension).

↵Returns:`Response`

Sets the HTTP response `Content-Disposition` header field to “attachment”. If a `filename` is given, then it sets the `Content-Type` based on the extension name via `res.type()`, and sets the `Content-Disposition` “filename=” parameter.

```
res.attachment();
// Content-Disposition: attachment


res.attachment('path/to/logo.png');
// Content-Disposition: attachment; filename="logo.png"
// Content-Type: image/png
```

The `expires` and `maxAge` options are being ignored completely.

### Caution

Web browsers and other compliant clients will only clear the cookie if the given `options` is identical to those given to [res.cookie()](#rescookie)

```
res.cookie('name', 'tobi', { path: '/admin' });
res.clearCookie('name', { path: '/admin' });
```

```
res.cookie('name', 'tobi', { domain: '.example.com', path: '/admin', secure: true });
res.cookie('remember_me', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
```

You can set multiple cookies in a single response by calling `res.cookie` multiple times, for example:

```
res
  .status(201)
  .cookie('access_token', `Bearer ${token}`, {
    expires: new Date(Date.now() + 8 * 3600000), // cookie will be removed after 8 hours
  })
  .cookie('test', 'test')
  .redirect(301, '/admin');
```

The `encode` option allows you to choose the function used for cookie value encoding. Does not support asynchronous functions.

Example use case: You need to set a domain-wide cookie for another site in your organization. This other site (not under your administrative control) does not use URI-encoded cookie values.

```
// Default encoding
res.cookie('some_cross_domain_cookie', 'http://mysubdomain.example.com', { domain: 'example.com' });
// Result: 'some_cross_domain_cookie=http%3A%2F%2Fmysubdomain.example.com; Domain=example.com; Path=/'


// Custom encoding
res.cookie('some_cross_domain_cookie', 'http://mysubdomain.example.com', {
  domain: 'example.com',
  encode: String,
});
// Result: 'some_cross_domain_cookie=http://mysubdomain.example.com; Domain=example.com; Path=/;'
```

The `maxAge` option is a convenience option for setting “expires” relative to the current time in milliseconds. The following is equivalent to the second example above.

```
res.cookie('remember_me', '1', { maxAge: 900000, httpOnly: true });
```

You can pass an object as the `value` parameter; it is then serialized as JSON and parsed by `bodyParser()` middleware.

```
res.cookie('cart', { items: [1, 2, 3] });
res.cookie('cart', { items: [1, 2, 3] }, { maxAge: 900000 });
```

When using [cookie-parser](https://www.npmjs.com/package/cookie-parser) middleware, this method also supports signed cookies. Simply include the `signed` option set to `true`. Then, `res.cookie()` will use the secret passed to `cookieParser(secret)` to sign the value.

```
res.cookie('name', 'tobi', { signed: true });
```

Later, you may access this value through the [req.signedCookies](/en/5x/api/request/#reqsignedcookies) object.

Type:`Object | undefined`

```
res.download('/report-12345.pdf');


res.download('/report-12345.pdf', 'report.pdf');


res.download('/report-12345.pdf', 'report.pdf', (err) => {
  if (err) {
    // Handle error, but keep in mind the response may be partially-sent
    // so check res.headersSent
  } else {
    // decrement a download credit, etc.
  }
});
```

```
res.end();
res.status(404).end();
```

### [res.format()](#resformat)

#### Arguments

`object`

Type:`Object`

An object whose keys are MIME types (or extension names) mapped to handler functions, optionally with a `default` handler.

↵Returns:`Response`

Performs content-negotiation on the `Accept` HTTP header on the request object, when present. It uses [req.accepts()](/en/5x/api/request/#reqaccepts) to select a handler for the request, based on the acceptable types ordered by their quality values. If the header is not specified, the first callback is invoked. When no match is found, the server responds with 406 “Not Acceptable”, or invokes the `default` callback.

The `Content-Type` response header is set when a callback is selected. However, you may alter this within the callback using methods such as `res.set()` or `res.type()`.

The following example would respond with `{ "message": "hey" }` when the `Accept` header field is set to “application/json” or ”\*/json” (however, if it is ”\*/\*”, then the response will be “hey”).

```
res.format({
  'text/plain'() {
    res.send('hey');
  },


  'text/html'() {
    res.send('<p>hey</p>');
  },


  'application/json'() {
    res.send({ message: 'hey' });
  },


  default() {
    // log the request and respond with 406
    res.status(406).send('Not Acceptable');
  },
});
```

In addition to canonicalized MIME types, you may also use extension names mapped to these types for a slightly less verbose implementation:

```
res.format({
  text() {
    res.send('hey');
  },


  html() {
    res.send('<p>hey</p>');
  },


  json() {
    res.send({ message: 'hey' });
  },
});
```

```
res.get('Content-Type');
// => "text/plain"
```

### [res.json()](#resjson)

#### Arguments

`body`

Type:`any | undefined`

The value to send as JSON. Can be any JSON type: object, array, string, Boolean, number, or null.

↵Returns:`Response`

Sends a JSON response. This method sends a response (with the correct content-type) that is the parameter converted to a JSON string using [JSON.stringify()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).

The parameter can be any JSON type, including object, array, string, Boolean, number, or null, and you can also use it to convert other values to JSON.

```
res.json(null);
res.json({ user: 'tobi' });
res.status(500).json({ error: 'message' });
```

### [res.jsonp()](#resjsonp)

#### Arguments

`body`

Type:`any | undefined`

The value to send as a JSONP response. Can be any JSON type.

↵Returns:`Response`

Sends a JSON response with JSONP support. This method is identical to `res.json()`, except that it opts-in to JSONP callback support.

```
res.jsonp(null);
// => callback(null)


res.jsonp({ user: 'tobi' });
// => callback({ "user": "tobi" })


res.status(500).jsonp({ error: 'message' });
// => callback({ "error": "message" })
```

By default, the JSONP callback name is simply `callback`. Override this with the

[jsonp callback name](/en/5x/api/application/#application-settings) setting.

The following are some examples of JSONP responses using the same code:

```
// ?callback=foo
res.jsonp({ user: 'tobi' });
// => foo({ "user": "tobi" })


app.set('jsonp callback name', 'cb');


// ?cb=foo
res.status(500).jsonp({ error: 'message' });
// => foo({ "error": "message" })
```

### [res.links()](#reslinks)

#### Arguments

`links`

Type:`Record<String, String | String[]>`

An object whose properties (such as `next` and `last`) populate the `Link` response header. Each value can be a single URL string, or an array of URL strings to emit multiple links for the same relation.

↵Returns:`Response`

Joins the `links` provided as properties of the parameter to populate the response’s `Link` HTTP header field.

For example, the following call:

```
res.links({
  next: 'http://api.example.com/users?page=2',
  last: 'http://api.example.com/users?page=5',
});
```

Yields the following results:

```
Link: <http://api.example.com/users?page=2>; rel="next",
      <http://api.example.com/users?page=5>; rel="last"
```

```
res.location('/foo/bar');
res.location('http://example.com');
```

Redirects to the URL derived from the specified `path`, with specified `status`, a positive integer that corresponds to an [HTTP status code](https://www.rfc-editor.org/rfc/rfc9110#name-status-codes). If not specified, `status` defaults to `302 "Found"`.

```
res.redirect('/foo/bar');
res.redirect('http://example.com');
res.redirect(301, 'http://example.com');
res.redirect('../login');
```

Redirects can be a fully-qualified URL for redirecting to a different site:

```
res.redirect('https://google.com');
```

Redirects can be relative to the root of the host name. For example, if the application is on `http://example.com/admin/post/new`, the following would redirect to the URL `http://example.com/admin`:

```
res.redirect('/admin');
```

Redirects can be relative to the current URL. For example, from `http://example.com/blog/admin/` (notice the trailing slash), the following would redirect to the URL `http://example.com/blog/admin/post/new`.

```
res.redirect('post/new');
```

Redirecting to `post/new` from `http://example.com/blog/admin` (no trailing slash), will redirect to `http://example.com/blog/post/new`.

If you found the above behavior confusing, think of path segments as directories (with trailing slashes) and files, it will start to make sense.

Path-relative redirects are also possible. If you were on `http://example.com/admin/post/new`, the following would redirect to `http://example.com/admin/post`:

```
res.redirect('..');
```

For more information, see [Using template engines with Express](/en/5x/guide/using-template-engines/).

### Warning

The `view` argument performs file system operations like reading a file from disk and evaluating Node.js modules, and as so for security reasons should not contain input from the end-user.

### Warning

The `locals` object is used by view engines to render a response. The object keys may be particularly sensitive and should not contain user-controlled input, as it may affect the operation of the view engine or provide a path to cross-site scripting. Consult the documentation for the used view engine for additional considerations.

### Caution

The local variable `cache` enables view caching. Set it to `true`, to cache the view during development; view caching is enabled in production by default.

```
// send the rendered view to the client
res.render('index');


// if a callback is specified, the rendered HTML string has to be sent explicitly
res.render('index', (err, html) => {
  res.send(html);
});


// pass a local variable to the view
res.render('user', { name: 'Tobi' }, (err, html) => {
  // ...
});
```

### [res.send()](#ressend)

#### Arguments

`body`

Type:`String | Buffer | Object | Array | Boolean | undefined`

The response body. Strings are sent as HTML; objects and arrays as JSON; Buffers as binary.

↵Returns:`Response`

Sends the HTTP response.

The `body` parameter can be a `Buffer` object, a `String`, an object, `Boolean`, or an `Array`. For example:

```
res.send(Buffer.from('whoop'));
res.send({ some: 'json' });
res.send('<p>some html</p>');
res.status(404).send('Sorry, we cannot find that!');
res.status(500).send({ error: 'something blew up' });
```

This method performs many useful tasks for simple non-streaming responses: For example, it automatically assigns the `Content-Length` HTTP response header field and provides automatic HEAD and HTTP cache freshness support.

When the parameter is a `Buffer` object, the method sets the `Content-Type` response header field to “application/octet-stream”, unless previously defined as shown below:

```
res.set('Content-Type', 'text/html');
res.send(Buffer.from('<p>some html</p>'));
```

When the parameter is a `String`, the method sets the `Content-Type` to “text/html”:

```
res.send('<p>some html</p>');
```

When the parameter is an `Array` or `Object`, Express responds with the JSON representation:

```
res.send({ user: 'tobi' });
res.send([1, 2, 3]);
```

Transfers the file at the given `path`. Sets the `Content-Type` response HTTP header field based on the filename’s extension. Unless the `root` option is set in the options object, `path` must be an absolute path to the file.

### Warning

This API provides access to data on the running file system. Ensure that either (a) the way in which the `path` argument was constructed into an absolute path is secure if it contains user input or (b) set the `root` option to the absolute path of a directory to contain access within.

When the `root` option is provided, the `path` argument is allowed to be a relative path, including containing `..`. Express will validate that the relative path provided as `path` will resolve within the given `root` option.

The method invokes the callback function `fn(err)` when the transfer is complete or when an error occurs. If the callback function is specified and an error occurs, the callback function must explicitly handle the response process either by ending the request-response cycle, or by passing control to the next route.

Here is an example of using `res.sendFile` with all its arguments.

```
app.get('/file/:name', (req, res, next) => {
  const options = {
    root: path.join(__dirname, 'public'),
    dotfiles: 'deny',
    headers: {
      'x-timestamp': Date.now(),
      'x-sent': true,
    },
  };


  const fileName = req.params.name;
  res.sendFile(fileName, options, (err) => {
    if (err) {
      next(err);
    } else {
      console.log('Sent:', fileName);
    }
  });
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get('/file/:name', (req: Request, res: Response, next: NextFunction) => {
  const options = {
    root: path.join(__dirname, 'public'),
    dotfiles: 'deny',
    headers: {
      'x-timestamp': Date.now(),
      'x-sent': true,
    },
  };


  const fileName = req.params.name;
  res.sendFile(fileName, options, (err) => {
    if (err) {
      next(err);
    } else {
      console.log('Sent:', fileName);
    }
  });
});
```

The following example illustrates using `res.sendFile` to provide fine-grained support for serving files:

```
app.get('/user/:uid/photos/:file', (req, res) => {
  const uid = req.params.uid;
  const file = req.params.file;


  req.user.mayViewFilesFrom(uid, (yes) => {
    if (yes) {
      res.sendFile(`/uploads/${uid}/${file}`);
    } else {
      res.status(403).send("Sorry! You can't see that.");
    }
  });
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/:uid/photos/:file', (req: Request, res: Response) => {
  const uid = req.params.uid;
  const file = req.params.file;


  req.user.mayViewFilesFrom(uid, (yes) => {
    if (yes) {
      res.sendFile(`/uploads/${uid}/${file}`);
    } else {
      res.status(403).send("Sorry! You can't see that.");
    }
  });
});
```

For more information, or if you have issues or concerns, see [send](https://github.com/pillarjs/send).

```
res.sendStatus(404);
```

```
res.set('Content-Type', 'text/plain');


res.set({
  'Content-Type': 'text/plain',
  'Content-Length': '123',
  ETag: '12345',
});
```

```
res.status(403).end();
res.status(400).send('Bad Request');
res.status(404).sendFile('/absolute/path/to/404.png');
```

### [res.type()](#restype)

#### Arguments

`type`

Type:`String`

The MIME type, or a file extension that is looked up to a MIME type. If it contains `/`, it is used as-is.

↵Returns:`Response`

Sets the `Content-Type` HTTP header to the MIME type as determined by the specified `type`. If `type` contains the ”/” character, then it sets the `Content-Type` to the exact value of `type`, otherwise it is assumed to be a file extension and the MIME type is looked up using the `contentType()` method of the `mime-types` package.

```
res.type('.html'); // => 'text/html'
res.type('html'); // => 'text/html'
res.type('json'); // => 'application/json'
res.type('application/json'); // => 'application/json'
res.type('png'); // => image/png:
```

```
res.vary('User-Agent').render('docs');
```

----
url: https://expressjs.com/en/resources/middleware/serve-favicon
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/serve-favicon.mdx)

# [serve-favicon middleware](#overview)

v2.5.1[GitHub](https://github.com/expressjs/serve-favicon)[Changelog](https://github.com/expressjs/serve-favicon/releases)[npm](https://www.npmjs.com/package/serve-favicon)

Node.js middleware for serving a favicon.

A favicon is a visual cue that client software, like browsers, use to identify a site. For an example and more information, please visit [the Wikipedia article on favicons](https://en.wikipedia.org/wiki/Favicon).

Why use this module?

* User agents request `favicon.ico` frequently and indiscriminately, so you may wish to exclude these requests from your logs by using this middleware before your logger middleware.
* This module caches the icon in memory to improve performance by skipping disk access.
* This module provides an `ETag` based on the contents of the icon, rather than file system properties.
* This module will serve with the most compatible `Content-Type`.

**Note** This module is exclusively for serving the “default, implicit favicon”, which is `GET /favicon.ico`. For additional vendor-specific icons that require HTML markup, additional middleware is required to serve the relevant files, for example [serve-static](https://npmjs.org/package/serve-static).

## [Install](#install)

This is a [Node.js](https://nodejs.org/en/) module available through the [npm registry](https://www.npmjs.com/). Installation is done using the [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):

Terminal window

```
npm install serve-favicon
```

Terminal window

```
yarn add serve-favicon
```

Terminal window

```
pnpm add serve-favicon
```

Terminal window

```
bun add serve-favicon
```

### Note

`serve-favicon` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/serve-favicon
```

Terminal window

```
yarn add --dev @types/serve-favicon
```

Terminal window

```
pnpm add --save-dev @types/serve-favicon
```

Terminal window

```
bun add --dev @types/serve-favicon
```

## [API](#api)

### [favicon(path, options)](#faviconpath-options)

Create new middleware to serve a favicon from the given `path` to a favicon file. `path` may also be a `Buffer` of the icon to serve.

#### [Options](#options)

Serve favicon accepts these properties in the options object.

##### [maxAge](#maxage)

The `cache-control` `max-age` directive in `ms`, defaulting to 1 year. This can also be a string accepted by the [ms](https://www.npmjs.org/package/ms#readme) module.

## [Examples](#examples)

Typically this middleware will come very early in your stack (maybe even first) to avoid processing any other middleware if we already know the request is for `/favicon.ico`.

### [express](#express)

```
var express = require('express');
var favicon = require('serve-favicon');
var path = require('path');


var app = express();
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));


// Add your routes here, etc.


app.listen(3000);
```

### [connect](#connect)

```
var connect = require('connect');
var favicon = require('serve-favicon');
var path = require('path');


var app = connect();
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));


// Add your middleware here, etc.


app.listen(3000);
```

### [vanilla http server](#vanilla-http-server)

This middleware can be used anywhere, even outside express/connect. It takes `req`, `res`, and `callback`.

```
var http = require('http');
var favicon = require('serve-favicon');
var finalhandler = require('finalhandler');
var path = require('path');


var _favicon = favicon(path.join(__dirname, 'public', 'favicon.ico'));


var server = http.createServer(function onRequest(req, res) {
  var done = finalhandler(req, res);


  _favicon(req, res, function onNext(err) {
    if (err) return done(err);


    // continue to process the request here, etc.


    res.statusCode = 404;
    res.end('oops');
  });
});


server.listen(3000);
```

## [License](#license)

[MIT](https://github.com/expressjs/serve-favicon/blob/HEAD/LICENSE)

----
url: https://expressjs.com/en/3x/api/
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/3x/api.mdx)

# [3.x API Reference](#overview)

### Express 3.x IS END-OF-LIFE AND NO LONGER MAINTAINED

Known and unknown security and performance issues in 3.x have not been addressed since the last update (1 August, 2015). It is highly recommended to use the latest version of Express.

If you are unable to upgrade past 3.x, please consider [Commercial Support Options](/en/support/#commercial-support-options).

### Note

Express 3.x requires **Node.js 0.8.0 or higher**.

# [3.x API](#3x-api)

This section provides an overview of the modules and APIs available in Express 3.x for building web applications and HTTP services.

## [`express()`](#express)

The `express()` function, exported by the `express` module, creates and returns a new application instance that serves as the foundation for defining routes, configuring middleware, and handling HTTP requests.

index.js

```
var express = require('express');
var app = express();


app.get('/', function (req, res) {
  res.send('hello world');
});


app.listen(3000);
```

After creating an application instance, you can define routes, configure middleware, and start handling HTTP requests

### [Application Object](/en/3x/api/application/)

[Learn about the properties and methods of the Express 3.x application object.](/en/3x/api/application/)

### [Request Object](/en/3x/api/request/)

[Learn about the properties and methods of the Express 3.x request object.](/en/3x/api/request/)

### [Response Object](/en/3x/api/response/)

[Learn about the properties and methods of the Express 3.x response object.](/en/3x/api/response/)

### [Middleware](/en/3x/api/middleware/)

[Learn about middleware in Express 3.x, including built-in and third-party options.](/en/3x/api/middleware/)

----
url: https://expressjs.com/en/5x/starter/static-files
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/starter/static-files.mdx)

# [Serving static files in Express](#overview)

To serve static files such as images, CSS files, and JavaScript files, use the `express.static` built-in middleware function in Express.

The function signature is:

```
express.static(root, [options]);
```

The `root` argument specifies the root directory from which to serve static assets. For more information on the `options` argument, see [express.static](/en/5x/api/express/#expressstatic).

For example, use the following code to serve images, CSS files, and JavaScript files in a directory named `public`:

```
app.use(express.static('public'));
```

Now, you can load the files that are in the `public` directory:

```
http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html
```

### Note

Express looks up the files relative to the static directory, so the name of the static directory is not part of the URL.

To use multiple static assets directories, call the `express.static` middleware function multiple times:

```
app.use(express.static('public'));
app.use(express.static('files'));
```

Express looks up the files in the order in which you set the static directories with the `express.static` middleware function.

### Note

For best results, [use a reverse proxy](/en/advanced/best-practice-performance/#use-a-reverse-proxy) cache to improve performance of serving static assets.

To create a virtual path prefix (where the path does not actually exist in the file system) for files that are served by the `express.static` function, [specify a mount path](/en/5x/api/application/#appuse) for the static directory, as shown below:

```
app.use('/static', express.static('public'));
```

Now, you can load the files that are in the `public` directory from the `/static` path prefix.

```
http://localhost:3000/static/images/kitten.jpg
http://localhost:3000/static/css/style.css
http://localhost:3000/static/js/app.js
http://localhost:3000/static/images/bg.png
http://localhost:3000/static/hello.html
```

However, the path that you provide to the `express.static` function is relative to the directory from where you launch your `node` process. If you run the express app from another directory, it’s safer to use the absolute path of the directory that you want to serve:

index.cjs

```
const path = require('path');
app.use('/static', express.static(path.join(__dirname, 'public')));
```

index.mjs

```
import path from 'path';


app.use('/static', express.static(path.join(__dirname, 'public')));
```

----
url: https://expressjs.com/en/resources/middleware/compression
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/compression.mdx)

# [compression middleware](#overview)

v1.8.2[GitHub](https://github.com/expressjs/compression)[Changelog](https://github.com/expressjs/compression/releases)[npm](https://www.npmjs.com/package/compression)

Node.js compression middleware.

The following compression codings are supported:

* deflate
* gzip
* br (brotli)

**Note** Brotli is available in all currently supported Node.js LTS versions (v18+).

## [Install](#install)

This is a [Node.js](https://nodejs.org/en/) module available through the [npm registry](https://www.npmjs.com/). Installation is done using the [`npm install` command](https://docs.npmjs.com/downloading-and-installing-packages-locally):

Terminal window

```
npm install compression
```

Terminal window

```
yarn add compression
```

Terminal window

```
pnpm add compression
```

Terminal window

```
bun add compression
```

### Note

`compression` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/compression
```

Terminal window

```
yarn add --dev @types/compression
```

Terminal window

```
pnpm add --save-dev @types/compression
```

Terminal window

```
bun add --dev @types/compression
```

## [API](#api)

```
var compression = require('compression');
```

### [compression(\[options\])](#compressionoptions)

Returns the compression middleware using the given `options`. The middleware will attempt to compress response bodies for all requests that traverse through the middleware, based on the given `options`.

This middleware will never compress responses that include a `Cache-Control` header with the [`no-transform` directive](https://tools.ietf.org/html/rfc7234#section-5.2.2.4), as compressing will transform the body.

#### [Options](#options)

`compression()` accepts these properties in the options object. In addition to those listed below, [zlib](https://nodejs.org/api/zlib.html) options may be passed in to the options object or [brotli](https://nodejs.org/api/zlib.html#zlib_class_brotlioptions) options.

##### [chunkSize](#chunksize)

Type: `Number`\
Default: `zlib.constants.Z_DEFAULT_CHUNK`, or `16384`.

See [Node.js documentation](https://nodejs.org/api/zlib.html#zlib_memory_usage_tuning) regarding the usage.

##### [filter](#filter)

Type: `Function`

A function to decide if the response should be considered for compression. This function is called as `filter(req, res)` and is expected to return `true` to consider the response for compression, or `false` to not compress the response.

The default filter function uses the [compressible](https://www.npmjs.com/package/compressible) module to determine if `res.getHeader('Content-Type')` is compressible.

##### [level](#level)

Type: `Number`\
Default: `zlib.constants.Z_DEFAULT_COMPRESSION`, or `-1`

The level of zlib compression to apply to responses. A higher level will result in better compression, but will take longer to complete. A lower level will result in less compression, but will be much faster.

This is an integer in the range of `0` (no compression) to `9` (maximum compression). The special value `-1` can be used to mean the “default compression level”, which is a default compromise between speed and compression (currently equivalent to level 6).

* `-1` Default compression level (also `zlib.constants.Z_DEFAULT_COMPRESSION`).
* `0` No compression (also `zlib.constants.Z_NO_COMPRESSION`).
* `1` Fastest compression (also `zlib.constants.Z_BEST_SPEED`).
* `2`
* `3`
* `4`
* `5`
* `6` (currently what `zlib.constants.Z_DEFAULT_COMPRESSION` points to).
* `7`
* `8`
* `9` Best compression (also `zlib.constants.Z_BEST_COMPRESSION`).

**Note** in the list above, `zlib` is from `zlib = require('zlib')`.

##### [memLevel](#memlevel)

Type: `Number`\
Default: `zlib.constants.Z_DEFAULT_MEMLEVEL`, or `8`

This specifies how much memory should be allocated for the internal compression state and is an integer in the range of `1` (minimum level) and `9` (maximum level).

See [Node.js documentation](https://nodejs.org/api/zlib.html#zlib_memory_usage_tuning) regarding the usage.

##### [brotli](#brotli)

Type: `Object`

This specifies the options for configuring Brotli. See [Node.js documentation](https://nodejs.org/api/zlib.html#class-brotlioptions) for a complete list of available options.

##### [strategy](#strategy)

Type: `Number`\
Default: `zlib.constants.Z_DEFAULT_STRATEGY`

This is used to tune the compression algorithm. This value only affects the compression ratio, not the correctness of the compressed output, even if it is not set appropriately.

* `zlib.constants.Z_DEFAULT_STRATEGY` Use for normal data.
* `zlib.constants.Z_FILTERED` Use for data produced by a filter (or predictor). Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better. The effect is to force more Huffman coding and less string matching; it is somewhat intermediate between `zlib.constants.Z_DEFAULT_STRATEGY` and `zlib.constants.Z_HUFFMAN_ONLY`.
* `zlib.constants.Z_FIXED` Use to prevent the use of dynamic Huffman codes, allowing for a simpler decoder for special applications.
* `zlib.constants.Z_HUFFMAN_ONLY` Use to force Huffman encoding only (no string match).
* `zlib.constants.Z_RLE` Use to limit match distances to one (run-length encoding). This is designed to be almost as fast as `zlib.constants.Z_HUFFMAN_ONLY`, but give better compression for PNG image data.

**Note** in the list above, `zlib` is from `zlib = require('zlib')`.

##### [threshold](#threshold)

Type: `Number` or `String`\
Default: `1kb`

The byte threshold for the response body size before compression is considered for the response. This is a number of bytes or any string accepted by the [bytes](https://www.npmjs.com/package/bytes) module.

**Note** this is only an advisory setting; if the response size cannot be determined at the time the response headers are written, then it is assumed the response is *over* the threshold. To guarantee the response size can be determined, be sure set a `Content-Length` response header.

##### [windowBits](#windowbits)

Type: `Number`\
Default: `zlib.constants.Z_DEFAULT_WINDOWBITS`, or `15`

See [Node.js documentation](https://nodejs.org/api/zlib.html#zlib_memory_usage_tuning) regarding the usage.

##### [enforceEncoding](#enforceencoding)

Type: `String`\
Default: `identity`

This is the default encoding to use when the client does not specify an encoding in the request’s [Accept-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding) header.

#### [.filter](#filter-1)

The default `filter` function. This is used to construct a custom filter function that is an extension of the default function.

```
var compression = require('compression');
var express = require('express');


var app = express();


app.use(compression({ filter: shouldCompress }));


function shouldCompress(req, res) {
  if (req.headers['x-no-compression']) {
    // don't compress responses with this request header
    return false;
  }


  // fallback to standard filter function
  return compression.filter(req, res);
}
```

### [res.flush](#resflush)

This module adds a `res.flush()` method to force the partially-compressed response to be flushed to the client.

## [Examples](#examples)

### [express](#express)

When using this module with express, simply `app.use` the module as high as you like. Requests that pass through the middleware will be compressed.

```
var compression = require('compression');
var express = require('express');


var app = express();


// compress all responses
app.use(compression());


// add all routes
```

### [Node.js HTTP server](#nodejs-http-server)

```
var compression = require('compression')({ threshold: 0 });
var http = require('http');


function createServer(fn) {
  return http.createServer(function (req, res) {
    compression(req, res, function (err) {
      if (err) {
        res.statusCode = err.status || 500;
        res.end(err.message);
        return;
      }


      fn(req, res);
    });
  });
}


var server = createServer(function (req, res) {
  res.setHeader('Content-Type', 'text/plain');
  res.end('hello world!');
});


server.listen(3000, () => {
  console.log('> Listening at http://localhost:3000');
});
```

### [Server-Sent Events](#server-sent-events)

Because of the nature of compression this module does not work out of the box with server-sent events. To compress content, a window of the output needs to be buffered up in order to get good compression. Typically when using server-sent events, there are certain block of data that need to reach the client.

You can achieve this by calling `res.flush()` when you need the data written to actually make it to the client.

```
var compression = require('compression');
var express = require('express');


var app = express();


// compress responses
app.use(compression());


// server-sent event stream
app.get('/events', function (req, res) {
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');


  // send a ping approx every 2 seconds
  var timer = setInterval(function () {
    res.write('data: ping\n\n');


    // !!! this is the important part
    res.flush();
  }, 2000);


  res.on('close', function () {
    clearInterval(timer);
  });
});
```

## [Contributing](#contributing)

The Express.js project welcomes all constructive contributions. Contributions take many forms, from code for bug fixes and enhancements, to additions and fixes to documentation, additional tests, triaging incoming pull requests and issues, and more!

See the [Contributing Guide](https://github.com/expressjs/.github/blob/HEAD/CONTRIBUTING.md) for more technical details on contributing.

## [License](#license)

[MIT](https://github.com/expressjs/compression/blob/HEAD/LICENSE)

----
url: https://expressjs.com/en/blog/2026-07-31-security-releases
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2026-07-31-security-releases)

security

# [July 2026 Security Releases](#overview)

Ulises GasconJuly 31, 2026

[](https://x.com/intent/tweet?text=July%202026%20Security%20Releases\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-07-31-security-releases%2F)[](https://bsky.app/intent/compose?text=July%202026%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-07-31-security-releases%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-07-31-security-releases%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-07-31-security-releases%2F\&text=July%202026%20Security%20Releases)[](https://wa.me/?text=July%202026%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-07-31-security-releases%2F)[](/feed.xml)

The Express team has released [body-parser](https://www.npmjs.com/package/body-parser) 1.20.6 and 2.3.0, addressing a denial of service vulnerability triggered by invalid `limit` values.

### Warning

We recommend upgrading to the latest version of body-parser to secure your applications. If you have a `package-lock.json`, you can update the dependency by running:

Terminal window

```
npm update body-parser
```

The following vulnerability has been addressed:

* [CVE-2026-12590 in body-parser middleware (Low)](#cve-2026-12590-in-body-parser-middleware-low)

## [CVE-2026-12590 in body-parser middleware (Low)](#cve-2026-12590-in-body-parser-middleware-low)

**[body-parser](https://www.npmjs.com/package/body-parser) versions `< 1.20.6` and `>= 2.0.0, < 2.3.0` are vulnerable to denial of service when an invalid `limit` value silently disables size enforcement**

When body-parser was configured with an invalid `limit` option value, such as an unparsable string or `NaN`, the internal call to `bytes.parse()` returned `null` and the request body size check was silently skipped. Applications that relied on `limit` as their primary safeguard against oversized request bodies would accept arbitrarily large payloads, leading to excessive memory and CPU usage and denial of service. This affected applications that pass a programmatically computed or user-configurable value to the `limit` option without validating it first. After the fix, invalid `limit` values throw a clear error at parser construction time instead of silently disabling enforcement.

**Affected versions**: `< 1.20.6` and `>= 2.0.0, < 2.3.0`\
**Patched versions**: `>= 1.20.6` and `>= 2.3.0`

For more details, see [GHSA-v422-hmwv-36x6](https://github.com/expressjs/body-parser/security/advisories/GHSA-v422-hmwv-36x6).

***

----
url: https://expressjs.com/en/4x/starter/hello-world
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/starter/hello-world.mdx)

# [Hello world example](#overview)

### Note

Embedded below is essentially the simplest Express app you can create. It is a single file app — *not* what you’d get if you use the [Express generator](/en/4x/starter/generator/), which creates the scaffolding for a full app with numerous JavaScript files, Jade templates, and sub-directories for various purposes.

index.cjs

```
const express = require('express');
const app = express();
const port = 3000;


app.get('/', (req, res) => {
  res.send('Hello World!');
});


app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});
```

index.mjs

```
import express from 'express';


const app = express();
const port = 3000;


app.get('/', (req, res) => {
  res.send('Hello World!');
});


app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();
const port = 3000;


app.get('/', (req: Request, res: Response) => {
  res.send('Hello World!');
});


app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});
```

This app starts a server and listens on port 3000 for connections. The app responds with “Hello World!” for requests to the root URL (`/`) or *route*. For every other path, it will respond with a **404 Not Found**.

## [Running Locally](#running-locally)

First create a directory named `myapp`, change to it and run `npm init`. Then, install `express` as a dependency, as per the [installation guide](/en/4x/starter/installing/).

In the `myapp` directory, create a file named `app.js` and copy the code from the example above.

### Caution

The `req` (request) and `res` (response) are the exact same objects that Node provides, so you can invoke `req.pipe()`, `req.on('data', callback)`, and anything else you would do without Express involved.

Run the app with the following command:

Terminal window

```
$ node app.js
```

Then, load `http://localhost:3000/` in a browser to see the output.

----
url: https://expressjs.com/en/5x/guide/using-template-engines
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/guide/using-template-engines.mdx)

# [Using template engines with Express](#overview)

A *template engine* enables you to use static template files in your application. At runtime, the template engine replaces variables in a template file with actual values, and transforms the template into an HTML file sent to the client. This approach makes it easier to design an HTML page.

The [Express application generator](/en/5x/starter/generator/) uses [Pug](https://pugjs.org/api/getting-started.html) as its default, but it can generate apps configured for Handlebars-compatible engines such as [hbs](https://www.npmjs.com/package/hbs), [EJS](https://www.npmjs.com/package/ejs), among others.

For apps created by the generator, these settings are added to the generated `app.js`. For apps you create without the generator, set the following [application setting properties](/en/5x/api/application/#appset) yourself:

* `views`, the directory where the template files are located. Eg: `app.set('views', './views')`. This defaults to the `views` directory in the application root directory.
* `view engine`, the template engine to use. For example, to use the Pug template engine: `app.set('view engine', 'pug')`.

Then install the corresponding Express-compatible template engine npm package; for example to install Pug:

Terminal window

```
npm install pug --save
```

Terminal window

```
yarn add pug
```

Terminal window

```
pnpm add pug
```

Terminal window

```
bun add pug
```

### Caution

Express-compliant template engines such as Pug export a function named `__express(filePath, options, callback)`, which `res.render()` calls to render the template code.

Some template engines do not follow this convention. The [@ladjs/consolidate](https://www.npmjs.com/package/@ladjs/consolidate) library follows this convention by mapping all of the popular Node.js template engines, and therefore works seamlessly within Express. For example, install [hbs](https://www.npmjs.com/package/hbs) or any other Express-compatible Handlebars view engine instead of the raw `handlebars` package by itself.

After the view engine is set, you don’t have to specify the engine or load the template engine module in your app; Express loads the module internally, for example:

```
app.set('view engine', 'pug');
```

Then, create a Pug template file named `index.pug` in the `views` directory, with the following content:

```
html
  head
    title= title
  body
    h1= message
```

Create a route to render the `index.pug` file. If the `view engine` property is not set, you must specify the extension of the `view` file. Otherwise, you can omit it.

```
app.get('/', (req, res) => {
  res.render('index', { title: 'Hey', message: 'Hello there!' });
});
```

```
import { type Request, type Response } from 'express';


app.get('/', (req: Request, res: Response) => {
  res.render('index', { title: 'Hey', message: 'Hello there!' });
});
```

When you make a request to the home page, the `index.pug` file will be rendered as HTML.

The view engine cache does not cache the contents of the template’s output, only the underlying template itself. The view is still re-rendered with every request even when the cache is on.

----
url: https://expressjs.com/en/5x/starter/examples
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/starter/examples.mdx)

# [Express examples](#overview)

This page contains list of examples using Express.

* [auth](https://github.com/expressjs/express/tree/master/examples/auth) - Authentication with login and password
* [content-negotiation](https://github.com/expressjs/express/tree/master/examples/content-negotiation) - HTTP content negotiation
* [cookie-sessions](https://github.com/expressjs/express/tree/master/examples/cookie-sessions) - Working with cookie-based sessions
* [cookies](https://github.com/expressjs/express/tree/master/examples/cookies) - Working with cookies
* [downloads](https://github.com/expressjs/express/tree/master/examples/downloads) - Transferring files to client
* [ejs](https://github.com/expressjs/express/tree/master/examples/ejs) - Working with Embedded JavaScript templating (ejs)
* [error-pages](https://github.com/expressjs/express/tree/master/examples/error-pages) - Creating error pages
* [error](https://github.com/expressjs/express/tree/master/examples/error) - Working with error middleware
* [hello-world](https://github.com/expressjs/express/tree/master/examples/hello-world) - Simple request handler
* [markdown](https://github.com/expressjs/express/tree/master/examples/markdown) - Markdown as template engine
* [multi-router](https://github.com/expressjs/express/tree/master/examples/multi-router) - Working with multiple Express routers
* [mvc](https://github.com/expressjs/express/tree/master/examples/mvc) - MVC-style controllers
* [online](https://github.com/expressjs/express/tree/master/examples/online) - Tracking online user activity with `online` and `redis` packages
* [params](https://github.com/expressjs/express/tree/master/examples/params) - Working with route parameters
* [resource](https://github.com/expressjs/express/tree/master/examples/resource) - Multiple HTTP operations on the same resource
* [route-map](https://github.com/expressjs/express/tree/master/examples/route-map) - Organizing routes using a map
* [route-middleware](https://github.com/expressjs/express/tree/master/examples/route-middleware) - Working with route middleware
* [route-separation](https://github.com/expressjs/express/tree/master/examples/route-separation) - Organizing routes per each resource
* [search](https://github.com/expressjs/express/tree/master/examples/search) - Search API
* [session](https://github.com/expressjs/express/tree/master/examples/session) - User sessions
* [static-files](https://github.com/expressjs/express/tree/master/examples/static-files) - Serving static files
* [vhost](https://github.com/expressjs/express/tree/master/examples/vhost) - Working with virtual hosts
* [view-constructor](https://github.com/expressjs/express/tree/master/examples/view-constructor) - Rendering views dynamically
* [view-locals](https://github.com/expressjs/express/tree/master/examples/view-locals) - Saving data in request object between middleware calls
* [web-service](https://github.com/expressjs/express/tree/master/examples/web-service) - Simple API service

## [Additional examples](#additional-examples)

These are some additional examples with more extensive integrations.

### Warning

This information refers to third-party sites, products, or modules that are not maintained by the Expressjs team. Listing here does not constitute an endorsement or recommendation from the Expressjs project team.

* [prisma-rest-api-ts](https://github.com/prisma/prisma-examples/tree/latest/orm/express) - REST API with Express in TypeScript using [Prisma](https://www.npmjs.com/package/prisma) as an ORM

----
url: https://expressjs.com/en/resources/utils
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/utils.mdx)

# [Express utilities](#overview)

## [Express utility functions](#express-utility-functions)

The [pillarjs](https://github.com/pillarjs) GitHub organization contains a number of modules for utility functions that may be generally useful.

| Utility modules                                                | Description                                                                                                                                             |
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [cookies](https://www.npmjs.com/package/cookies)               | Get and set HTTP(S) cookies that can be signed to prevent tampering, using Keygrip. Can be used with the Node.js HTTP library or as Express middleware. |
| [csrf](https://www.npmjs.com/package/csrf)                     | Contains the logic behind CSRF token creation and verification. Use this module to create custom CSRF middleware.                                       |
| [finalhandler](https://www.npmjs.com/package/finalhandler)     | Function to invoke as the final step to respond to HTTP request.                                                                                        |
| [parseurl](https://www.npmjs.com/package/parseurl)             | Parse a URL with caching.                                                                                                                               |
| [path-to-regexp](https://www.npmjs.com/package/path-to-regexp) | Turn an Express-style path string such as “/user/:name\` into a regular expression.                                                                     |
| [resolve-path](https://www.npmjs.com/package/resolve-path)     | Resolves a relative path against a root path with validation.                                                                                           |
| [router](https://www.npmjs.com/package/router)                 | Simple middleware-style router.                                                                                                                         |
| [send](https://www.npmjs.com/package/send)                     | Library for streaming files as a HTTP response, with support for partial responses (ranges), conditional-GET negotiation, and granular events.          |

For additional low-level HTTP-related modules, see [jshttp](https://github.com/jshttp).

----
url: https://expressjs.com/en/4x/api/express/
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/4x/api/express/index.mdx)

# [Express Object](#overview)

Creates an Express application. The `express()` function is a top-level function exported by the `express` module.

index.cjs

```
var express = require('express');
var app = express();
```

index.mjs

```
import express from 'express';
const app = express();
```

index.ts

```
import express, { type Express } from 'express';
const app: Express = express();
```

## [Methods](#methods)

### [express.json()](#expressjson)

#### Arguments

`options`

Type:`Object | undefined`

Configures how the JSON body is parsed; it accepts the properties below.

Added in:`v4.16.0`

This is a built-in middleware function in Express. It parses incoming requests with JSON payloads and is based on [body-parser](/en/resources/middleware/body-parser/).

Returns middleware that only parses JSON and only looks at requests where the `Content-Type` header matches the `type` option. This parser accepts any Unicode encoding of the body and supports automatic inflation of `gzip` and `deflate` encodings.

A new `body` object containing the parsed data is populated on the `request` object after the middleware (i.e. `req.body`), or an empty object (`{}`) if there was no body to parse, the `Content-Type` was not matched, or an error occurred.

### Warning

As `req.body`’s shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, `req.body.foo.toString()` may fail in multiple ways, for example `foo` may not be there or may not be a string, and `toString` may not be a function and instead a string or other user-input.

index.cjs

```
var express = require('express');
var app = express();


// parse requests with a Content-Type of application/json
app.use(express.json());


app.post('/profile', function (req, res) {
  console.dir(req.body);
  res.json(req.body);
});
```

index.mjs

```
import express from 'express';


const app = express();


// parse requests with a Content-Type of application/json
app.use(express.json());


app.post('/profile', (req, res) => {
  console.dir(req.body);
  res.json(req.body);
});
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


// parse requests with a Content-Type of application/json
app.use(express.json());


app.post('/profile', (req: Request, res: Response) => {
  console.dir(req.body);
  res.json(req.body);
});
```

Added in:`v4.17.0`

This is a built-in middleware function in Express. It parses incoming request payloads into a `Buffer` and is based on [body-parser](/en/resources/middleware/body-parser/).

Returns middleware that parses all bodies as a `Buffer` and only looks at requests where the `Content-Type` header matches the `type` option. This parser accepts any Unicode encoding of the body and supports automatic inflation of `gzip` and `deflate` encodings.

A new `body` `Buffer` containing the parsed data is populated on the `request` object after the middleware (i.e. `req.body`), or an empty object (`{}`) if there was no body to parse, the `Content-Type` was not matched, or an error occurred.

### Warning

As `req.body`’s shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, `req.body.toString()` may fail in multiple ways, for example stacking multiple parsers `req.body` may be from a different parser. Testing that `req.body` is a `Buffer` before calling buffer methods is recommended.

index.cjs

```
var express = require('express');
var app = express();


// parse requests with a Content-Type of application/octet-stream into a Buffer
app.use(express.raw());


app.post('/upload', function (req, res) {
  console.dir(Buffer.isBuffer(req.body)); // => true
  res.send('received ' + req.body.length + ' bytes');
});
```

index.mjs

```
import express from 'express';


const app = express();


// parse requests with a Content-Type of application/octet-stream into a Buffer
app.use(express.raw());


app.post('/upload', (req, res) => {
  console.dir(Buffer.isBuffer(req.body)); // => true
  res.send(`received ${req.body.length} bytes`);
});
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


// parse requests with a Content-Type of application/octet-stream into a Buffer
app.use(express.raw());


app.post('/upload', (req: Request, res: Response) => {
  console.dir(Buffer.isBuffer(req.body)); // => true
  res.send(`received ${req.body.length} bytes`);
});
```

### [express.Router()](#expressrouter)

#### Arguments

`caseSensitive`

Type:`Boolean`Default:`false`

Enable case sensitivity. Disabled by default, treating `/Foo` and `/foo` as the same.

`mergeParams`

Type:`Boolean`Default:`false`Added in:`v4.5.0+`

Preserve the `req.params` values from the parent router. If the parent and the child have conflicting param names, the child’s value take precedence.

`strict`

Type:`Boolean`Default:`false`

Enable strict routing. Disabled by default, `/foo` and `/foo/` are treated the same by the router.

↵Returns:`Router`

Creates a new [router](/en/4x/api/router/) object.

```
var router = express.Router([options]);
```

You can add middleware and HTTP method routes (such as `get`, `put`, `post`, and so on) to `router` just like an application.

For more information, see [Router](/en/4x/api/router/).

Type:`String`Default:`undefined`

The `root` argument specifies the root directory from which to serve static assets. The function determines the file to serve by combining `req.url` with the provided `root` directory. When a file is not found, instead of sending a 404 response, it calls `next()` to move on to the next middleware, allowing for stacking and fall-backs.

For more information, see [Serving static files in Express](/en/4x/starter/static-files/). and [Using middleware - Built-in middleware](/en/4x/guide/using-middleware/#built-in-middleware).

#### [dotfiles](#dotfiles)

Possible values for this option are:

* “allow” - No special treatment for dotfiles.
* “deny” - Deny a request for a dotfile, respond with `403`, then call `next()`.
* “ignore” - Act as if the dotfile does not exist, respond with `404`, then call `next()`.
* `undefined` - Act as ignore, except that files in a directory that begins with a dot are **NOT** ignored.

```
fn(res, path, stat);
```

Arguments:

* `res`, the [response object](/en/4x/api/response/).
* `path`, the file path that is being sent.
* `stat`, the `stat` object of the file that is being sent.

#### [Example of express.static](#example-of-expressstatic)

Here is an example of using the `express.static` middleware function with an elaborate options object:

index.cjs

```
var express = require('express');
var app = express();


var options = {
  dotfiles: 'ignore',
  etag: false,
  extensions: ['htm', 'html'],
  index: false,
  maxAge: '1d',
  redirect: false,
  setHeaders: function (res, path, stat) {
    res.set('x-timestamp', Date.now());
  },
};


app.use(express.static('public', options));
```

index.mjs

```
import express from 'express';


const app = express();


const options = {
  dotfiles: 'ignore',
  etag: false,
  extensions: ['htm', 'html'],
  index: false,
  maxAge: '1d',
  redirect: false,
  setHeaders: (res, path, stat) => {
    res.set('x-timestamp', Date.now());
  },
};


app.use(express.static('public', options));
```

index.ts

```
import express, { type Express } from 'express';


const app: Express = express();


const options = {
  dotfiles: 'ignore',
  etag: false,
  extensions: ['htm', 'html'],
  index: false,
  maxAge: '1d',
  redirect: false,
  setHeaders: (res, path, stat) => {
    res.set('x-timestamp', Date.now());
  },
};


app.use(express.static('public', options));
```

Added in:`v4.17.0`

This is a built-in middleware function in Express. It parses incoming request payloads into a string and is based on [body-parser](/en/resources/middleware/body-parser/).

Returns middleware that parses all bodies as a string and only looks at requests where the `Content-Type` header matches the `type` option. This parser accepts any Unicode encoding of the body and supports automatic inflation of `gzip` and `deflate` encodings.

A new `body` string containing the parsed data is populated on the `request` object after the middleware (i.e. `req.body`), or an empty object (`{}`) if there was no body to parse, the `Content-Type` was not matched, or an error occurred.

### Warning

As `req.body`’s shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, `req.body.trim()` may fail in multiple ways, for example stacking multiple parsers `req.body` may be from a different parser. Testing that `req.body` is a string before calling string methods is recommended.

index.cjs

```
var express = require('express');
var app = express();


// parse requests with a Content-Type of text/plain into a string
app.use(express.text());


app.post('/', function (req, res) {
  console.dir(typeof req.body); // => 'string'
  res.send(req.body);
});
```

index.mjs

```
import express from 'express';


const app = express();


// parse requests with a Content-Type of text/plain into a string
app.use(express.text());


app.post('/', (req, res) => {
  console.dir(typeof req.body); // => 'string'
  res.send(req.body);
});
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


// parse requests with a Content-Type of text/plain into a string
app.use(express.text());


app.post('/', (req: Request, res: Response) => {
  console.dir(typeof req.body); // => 'string'
  res.send(req.body);
});
```

### [express.urlencoded()](#expressurlencoded)

#### Arguments

`options`

Type:`Object | undefined`

Configures how the URL-encoded body is parsed; it accepts the properties below.

`extended`

Type:`Boolean`Default:`true`

`depth`

Type:`Number`Default:`32`Added in:`v4.20.0`

Configure the maximum depth of the `qs` library when `extended` is `true`. This allows you to limit the amount of keys that are parsed and can be useful to prevent certain types of abuse. It is recommended to keep this value as low as possible.

↵Returns:`Function`

Added in:`v4.16.0`

This is a built-in middleware function in Express. It parses incoming requests with urlencoded payloads and is based on [body-parser](/en/resources/middleware/body-parser/).

Returns middleware that only parses urlencoded bodies and only looks at requests where the `Content-Type` header matches the `type` option. This parser accepts only UTF-8 encoding of the body and supports automatic inflation of `gzip` and `deflate` encodings.

A new `body` object containing the parsed data is populated on the `request` object after the middleware (i.e. `req.body`), or an empty object (`{}`) if there was no body to parse, the `Content-Type` was not matched, or an error occurred. This object will contain key-value pairs, where the value can be a string or array (when `extended` is `false`), or any type (when `extended` is `true`).

### Warning

As `req.body`’s shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, `req.body.foo.toString()` may fail in multiple ways, for example `foo` may not be there or may not be a string, and `toString` may not be a function and instead a string or other user-input.

index.cjs

```
var express = require('express');
var app = express();


// parse requests with a Content-Type of application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));


app.post('/profile', function (req, res) {
  console.dir(req.body);
  res.json(req.body);
});
```

index.mjs

```
import express from 'express';


const app = express();


// parse requests with a Content-Type of application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));


app.post('/profile', (req, res) => {
  console.dir(req.body);
  res.json(req.body);
});
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


// parse requests with a Content-Type of application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));


app.post('/profile', (req: Request, res: Response) => {
  console.dir(req.body);
  res.json(req.body);
});
```

----
url: https://expressjs.com/en/4x/starter/basic-routing
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/starter/basic-routing.mdx)

# [Basic routing](#overview)

*Routing* refers to determining how an application responds to a client request to a particular endpoint, which is a URI (or path) and a specific HTTP request method (GET, POST, and so on).

Each route can have one or more handler functions, which are executed when the route is matched.

Route definition takes the following structure:

```
app.METHOD(PATH, HANDLER);
```

Where:

* `app` is an instance of `express`.
* `METHOD` is an [HTTP request method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods), in lowercase.
* `PATH` is a path on the server.
* `HANDLER` is the function executed when the route is matched.

### Caution

This tutorial assumes that an instance of `express` named `app` is created and the server is running. If you are not familiar with creating an app and starting it, see the [Hello world example](/en/4x/starter/hello-world/).

The following examples illustrate defining simple routes.

Respond with `Hello World!` on the homepage:

```
app.get('/', (req, res) => {
  res.send('Hello World!');
});
```

```
import { type Request, type Response } from 'express';


app.get('/', (req: Request, res: Response) => {
  res.send('Hello World!');
});
```

Respond to a POST request on the root route (`/`), the application’s home page:

```
app.post('/', (req, res) => {
  res.send('Got a POST request');
});
```

```
import { type Request, type Response } from 'express';


app.post('/', (req: Request, res: Response) => {
  res.send('Got a POST request');
});
```

Respond to a PUT request to the `/user` route:

```
app.put('/user', (req, res) => {
  res.send('Got a PUT request at /user');
});
```

```
import { type Request, type Response } from 'express';


app.put('/user', (req: Request, res: Response) => {
  res.send('Got a PUT request at /user');
});
```

Respond to a DELETE request to the `/user` route:

```
app.delete('/user', (req, res) => {
  res.send('Got a DELETE request at /user');
});
```

```
import { type Request, type Response } from 'express';


app.delete('/user', (req: Request, res: Response) => {
  res.send('Got a DELETE request at /user');
});
```

----
url: https://expressjs.com/en/5x/api/application
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/5x/api/application/index.mdx)

# [Application Object](#overview)

The `app` object conventionally denotes the Express application. Create it by calling the top-level `express()` function exported by the Express module:

index.cjs

```
var express = require('express');
var app = express();


app.get('/', function (req, res) {
  res.send('hello world');
});


app.listen(3000);
```

index.mjs

```
import express from 'express';


const app = express();


app.get('/', function (req, res) {
  res.send('hello world');
});


app.listen(3000);
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


app.get('/', function (req: Request, res: Response) {
  res.send('hello world');
});


app.listen(3000);
```

The `app` object has methods for

* Routing HTTP requests; see for example, [app.METHOD](#appmethod) and [app.param](#appparam).
* Configuring middleware; see [app.route](#approute).
* Rendering HTML views; see [app.render](#apprender).
* Registering a template engine; see [app.engine](#appengine).

It also has settings (properties) that affect how the application behaves; for more information, see [Application settings](#application-settings).

### Note

The Express application object can be referred from the [request object](/en/5x/api/request/) and the [response object](/en/5x/api/response/) as `req.app`, and `res.app`, respectively.

## [Properties](#properties)

### [app.locals](#applocals)

Type:`Object`

The `app.locals` object has properties that are local variables within the application, and will be available in templates rendered with [res.render](/en/5x/api/response/#resrender).

### Warning

The `locals` object is used by view engines to render a response. The object keys may be particularly sensitive and should not contain user-controlled input, as it may affect the operation of the view engine or provide a path to cross-site scripting. Consult the documentation for the used view engine for additional considerations.

```
console.dir(app.locals.title);
// => 'My App'


console.dir(app.locals.email);
// => '[email protected]'
```

Once set, the value of `app.locals` properties persist throughout the life of the application, in contrast with [res.locals](/en/5x/api/response/#reslocals) properties that are valid only for the lifetime of the request.

You can access local variables in templates rendered within the application. This is useful for providing helper functions to templates, as well as application-level data. Local variables are available in middleware via `req.app.locals` (see [req.app](/en/5x/api/request/#reqapp))

```
app.locals.title = 'My App';
app.locals.strftime = require('strftime');
app.locals.email = '[email protected]';
```

### [app.mountpath](#appmountpath)

Type:`String | String[]`

The `app.mountpath` property contains one or more path patterns on which a sub-app was mounted.

### Note

A sub-app is an instance of `express` that may be used for handling the request to a route.

index.cjs

```
const express = require('express');


const app = express(); // the main app
const admin = express(); // the sub app


admin.get('/', (req, res) => {
  console.log(admin.mountpath); // /admin
  res.send('Admin Homepage');
});


app.use('/admin', admin); // mount the sub app
```

index.mjs

```
import express from 'express';


const app = express(); // the main app
const admin = express(); // the sub app


admin.get('/', (req, res) => {
  console.log(admin.mountpath); // /admin
  res.send('Admin Homepage');
});


app.use('/admin', admin); // mount the sub app
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express(); // the main app
const admin: Express = express(); // the sub app


admin.get('/', (req: Request, res: Response) => {
  console.log(admin.mountpath); // /admin
  res.send('Admin Homepage');
});


app.use('/admin', admin); // mount the sub app
```

It is similar to the [baseUrl](/en/5x/api/request/#reqbaseurl) property of the `req` object, except `req.baseUrl` returns the matched URL path, instead of the matched patterns.

If a sub-app is mounted on multiple path patterns, `app.mountpath` returns the list of patterns it is mounted on, as shown in the following example.

```
const admin = express();


admin.get('/', (req, res) => {
  console.log(admin.mountpath); // [ '/adm{*splat}n', '/manager' ]
  res.send('Admin Homepage');
});


const secret = express();
secret.get('/', (req, res) => {
  console.log(secret.mountpath); // /secr{*splat}t
  res.send('Admin Secret');
});


admin.use('/secr{*splat}t', secret); // load the 'secret' router on '/secr{*splat}t', on the 'admin' sub app
app.use(['/adm{*splat}n', '/manager'], admin); // load the 'admin' router on '/adm{*splat}n' and '/manager', on the parent app
```

```
import express, { type Express, type Request, type Response } from 'express';


const admin: Express = express();


admin.get('/', (req: Request, res: Response) => {
  console.log(admin.mountpath); // [ '/adm{*splat}n', '/manager' ]
  res.send('Admin Homepage');
});


const secret: Express = express();
secret.get('/', (req: Request, res: Response) => {
  console.log(secret.mountpath); // /secr{*splat}t
  res.send('Admin Secret');
});


admin.use('/secr{*splat}t', secret); // load the 'secret' router on '/secr{*splat}t', on the 'admin' sub app
app.use(['/adm{*splat}n', '/manager'], admin); // load the 'admin' router on '/adm{*splat}n' and '/manager', on the parent app
```

### [app.router](#approuter)

Type:`Router`

The application’s in-built instance of router. This is created lazily, on first access.

index.cjs

```
const express = require('express');
const app = express();
const router = app.router;


router.get('/', (req, res) => {
  res.send('hello world');
});


app.listen(3000);
```

index.mjs

```
import express from 'express';


const app = express();
const router = app.router;


router.get('/', (req, res) => {
  res.send('hello world');
});


app.listen(3000);
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();
const router = app.router;


router.get('/', (req: Request, res: Response) => {
  res.send('hello world');
});


app.listen(3000);
```

You can add middleware and HTTP method routes to the `router` just like an application.

For more information, see [Router](/en/5x/api/router/).

```
const admin = express();


admin.on('mount', (parent) => {
  console.log('Admin Mounted');
  console.log(parent); // refers to the parent app
});


admin.get('/', (req, res) => {
  res.send('Admin Homepage');
});


app.use('/admin', admin);
```

```
import express, { type Express, type Application, type Request, type Response } from 'express';


const admin: Express = express();


admin.on('mount', (parent: Application) => {
  console.log('Admin Mounted');
  console.log(parent); // refers to the parent app
});


admin.get('/', (req: Request, res: Response) => {
  res.send('Admin Homepage');
});


app.use('/admin', admin);
```

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/5x/api/router/) and [app](/en/5x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

This method is like the standard [app.METHOD()](#appmethod) methods, except it matches all HTTP verbs.

#### [Examples](#examples)

The following callback is executed for requests to `/secret` whether using GET, POST, PUT, DELETE, or any other HTTP request method:

```
app.all('/secret', (req, res, next) => {
  console.log('Accessing the secret section ...');
  next(); // pass control to the next handler
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.all('/secret', (req: Request, res: Response, next: NextFunction) => {
  console.log('Accessing the secret section ...');
  next(); // pass control to the next handler
});
```

The `app.all()` method is useful for mapping “global” logic for specific path prefixes or arbitrary matches. For example, if you put the following at the top of all other route definitions, it requires that all routes from that point on require authentication, and automatically load a user. Keep in mind that these callbacks do not have to act as end-points: `loadUser` can perform a task, then call `next()` to continue matching subsequent routes.

```
app.all('{*splat}', requireAuthentication, loadUser);
```

Or the equivalent:

```
app.all('{*splat}', requireAuthentication);
app.all('{*splat}', loadUser);
```

Another example is white-listed “global” functionality. The example is similar to the ones above, but it only restricts paths that start with “/api”:

```
app.all('/api/{*splat}', requireAuthentication);
```

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/5x/api/router/) and [app](/en/5x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

Routes HTTP DELETE requests to the specified path with the specified callback functions. For more information, see the [routing guide](/en/5x/guide/routing/).

#### [Example](#example)

```
app.delete('/', (req, res) => {
  res.send('DELETE request to homepage');
});
```

```
import { type Request, type Response } from 'express';


app.delete('/', (req: Request, res: Response) => {
  res.send('DELETE request to homepage');
});
```

```
app.disable('trust proxy');
app.get('trust proxy');
// => false
```

```
app.disabled('trust proxy');
// => true


app.enable('trust proxy');
app.disabled('trust proxy');
// => false
```

```
app.enable('trust proxy');
app.get('trust proxy');
// => true
```

```
app.enabled('trust proxy');
// => false


app.enable('trust proxy');
app.enabled('trust proxy');
// => true
```

```
app.engine('pug', require('pug').__express);
```

Use this method for engines that do not provide `.__express` out of the box, or if you wish to “map” a different extension to the template engine.

For example, to map the EJS template engine to “.html” files:

```
app.engine('html', require('ejs').renderFile);
```

In this case, EJS provides a `.renderFile()` method with the same signature that Express expects: `(path, options, callback)`, though note that it aliases this method as `ejs.__express` internally so if you’re using “.ejs” extensions you don’t need to do anything.

Some template engines do not follow this convention. The [consolidate.js](https://github.com/tj/consolidate.js) library maps Node template engines to follow this convention, so they work seamlessly with Express.

index.cjs

```
const engines = require('consolidate');
app.engine('haml', engines.haml);
app.engine('html', engines.hogan);
```

index.mjs

```
import engines from 'consolidate';


app.engine('haml', engines.haml);
app.engine('html', engines.hogan);
```

```
app.get('title');
// => undefined


app.set('title', 'My Site');
app.get('title');
// => "My Site"
```

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/5x/api/router/) and [app](/en/5x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

Routes HTTP GET requests to the specified path with the specified callback functions.

For more information, see the [routing guide](/en/5x/guide/routing/).

#### [Example](#example-1)

```
app.get('/', (req, res) => {
  res.send('GET request to homepage');
});
```

```
import { type Request, type Response } from 'express';


app.get('/', (req: Request, res: Response) => {
  res.send('GET request to homepage');
});
```

A function called once the server is listening. If the server emits an `error` event (for example `EADDRINUSE`), the error is passed to this callback as its argument.

↵Returns:`http.Server`

Binds and listens for connections on the specified host and port, or starts a UNIX socket and listens for connections on the given path. This method is identical to Node’s [http.Server.listen()](https://nodejs.org/api/http.html#serverlisten).

If port is omitted or is 0, the operating system will assign an arbitrary unused port, which is useful for cases like automated tasks (tests, etc.).

index.cjs

```
const express = require('express');
const app = express();


app.listen(3000); // bind and listen on a TCP port
app.listen('/tmp/sock'); // or listen on a UNIX socket
```

index.mjs

```
import express from 'express';


const app = express();


app.listen(3000); // bind and listen on a TCP port
app.listen('/tmp/sock'); // or listen on a UNIX socket
```

index.ts

```
import express, { type Express } from 'express';


const app: Express = express();


app.listen(3000); // bind and listen on a TCP port
app.listen('/tmp/sock'); // or listen on a UNIX socket
```

### Note

When the server emits an `error` event (such as `EADDRINUSE`), the error is passed to the provided `callback`. Handle it inside the callback:

```
const server = app.listen(8080, '0.0.0.0', (error) => {
  if (error) {
    throw error; // e.g. EADDRINUSE
  }
  console.log(`Listening on ${JSON.stringify(server.address())}`);
});
```

The `app` returned by `express()` is in fact a JavaScript `Function`, designed to be passed to Node’s HTTP servers as a callback to handle requests. This makes it easy to provide both HTTP and HTTPS versions of your app with the same code base, as the app does not inherit from these (it is simply a callback):

index.cjs

```
const express = require('express');
const https = require('https');
const http = require('http');
const app = express();


http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
```

index.mjs

```
import express from 'express';
import https from 'https';
import http from 'http';


const app = express();


http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
```

index.ts

```
import express, { type Express } from 'express';
import https from 'https';
import http from 'http';


const app: Express = express();


http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
```

The `app.listen()` method returns an [http.Server](https://nodejs.org/api/http.html#class-httpserver) object and (for HTTP) is a convenience method for the following:

```
app.listen = function () {
  const server = http.createServer(this);
  return server.listen.apply(server, arguments);
};
```

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/5x/api/router/) and [app](/en/5x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

```
app.get('/', (req, res) => {
  res.send('GET request to homepage');
});


app.post('/', (req, res) => {
  res.send('POST request to homepage');
});


// methods that are invalid JavaScript variable names use bracket notation
app['m-search']('/', (req, res) => {
  res.send('M-SEARCH request to homepage');
});
```

```
import { type Request, type Response } from 'express';


app.get('/', (req: Request, res: Response) => {
  res.send('GET request to homepage');
});


app.post('/', (req: Request, res: Response) => {
  res.send('POST request to homepage');
});


// methods that are invalid JavaScript variable names use bracket notation
app['m-search']('/', (req: Request, res: Response) => {
  res.send('M-SEARCH request to homepage');
});
```

### Note

The `app.get()` function is automatically called for the HTTP `HEAD` method in addition to the `GET` method if `app.head()` was not called for the path before `app.get()`.

The method, `app.all()`, is not derived from any HTTP method and loads middleware at the specified path for *all* HTTP request methods. For more information, see [app.all](#appall).

For more information on routing, see the [routing guide](/en/5x/guide/routing/).

### [app.param()](#appparam)

#### Arguments

`name`

Type:`String | String[]`

The name of the route parameter, or an array of names.

`callback`

Type:`Function`

The trigger called as `callback(req, res, next, value, name)`: the request object, the response object, the next middleware, the value of the parameter, and the name of the parameter, in that order.

Add callback triggers to [route parameters](/en/5x/guide/routing/#route-parameters), where `name` is the name of the parameter or an array of them, and `callback` is the callback function. The parameters of the callback function are the request object, the response object, the next middleware, the value of the parameter and the name of the parameter, in that order.

If `name` is an array, the `callback` trigger is registered for each parameter declared in it, in the order in which they are declared. Furthermore, for each declared parameter except the last one, a call to `next` inside the callback will call the callback for the next declared parameter. For the last parameter, a call to `next` will call the next middleware in place for the route currently being processed, just like it would if `name` were just a string.

For example, when `:user` is present in a route path, you may map user loading logic to automatically provide `req.user` to the route, or perform validations on the parameter input.

```
app.param('user', (req, res, next, id) => {
  // try to get the user details from the User model and attach it to the request object
  User.find(id, (err, user) => {
    if (err) {
      next(err);
    } else if (user) {
      req.user = user;
      next();
    } else {
      next(new Error('failed to load user'));
    }
  });
});
```

Param callback functions are local to the router on which they are defined. They are not inherited by mounted apps or routers, nor are they triggered for route parameters inherited from parent routers. Hence, param callbacks defined on `app` will be triggered only by route parameters defined on `app` routes.

All param callbacks will be called before any handler of any route in which the param occurs, and they will each be called only once in a request-response cycle, even if the parameter is matched in multiple routes, as shown in the following examples.

```
app.param('id', (req, res, next, id) => {
  console.log('CALLED ONLY ONCE');
  next();
});


app.get('/user/:id', (req, res, next) => {
  console.log('although this matches');
  next();
});


app.get('/user/:id', (req, res) => {
  console.log('and this matches too');
  res.end();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.param('id', (req: Request, res: Response, next: NextFunction, id: string) => {
  console.log('CALLED ONLY ONCE');
  next();
});


app.get('/user/:id', (req: Request, res: Response, next: NextFunction) => {
  console.log('although this matches');
  next();
});


app.get('/user/:id', (req: Request, res: Response) => {
  console.log('and this matches too');
  res.end();
});
```

On `GET /user/42`, the following is printed:

```
CALLED ONLY ONCE
although this matches
and this matches too
```

```
app.param(['id', 'page'], (req, res, next, value) => {
  console.log('CALLED ONLY ONCE with', value);
  next();
});


app.get('/user/:id/:page', (req, res, next) => {
  console.log('although this matches');
  next();
});


app.get('/user/:id/:page', (req, res) => {
  console.log('and this matches too');
  res.end();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.param(['id', 'page'], (req: Request, res: Response, next: NextFunction, value: string) => {
  console.log('CALLED ONLY ONCE with', value);
  next();
});


app.get('/user/:id/:page', (req: Request, res: Response, next: NextFunction) => {
  console.log('although this matches');
  next();
});


app.get('/user/:id/:page', (req: Request, res: Response) => {
  console.log('and this matches too');
  res.end();
});
```

On `GET /user/42/3`, the following is printed:

```
CALLED ONLY ONCE with 42
CALLED ONLY ONCE with 3
although this matches
and this matches too
```

### [app.path()](#apppath)

↵Returns:`String`

Returns the canonical path of the app, a string.

index.js

```
const app = express();
const blog = express();
const blogAdmin = express();


app.use('/blog', blog);
blog.use('/admin', blogAdmin);


console.log(app.path()); // ''
console.log(blog.path()); // '/blog'
console.log(blogAdmin.path()); // '/blog/admin'
```

index.ts

```
import express, { type Express } from 'express';


const app: Express = express();
const blog: Express = express();
const blogAdmin: Express = express();


app.use('/blog', blog);
blog.use('/admin', blogAdmin);


console.log(app.path()); // ''
console.log(blog.path()); // '/blog'
console.log(blogAdmin.path()); // '/blog/admin'
```

The behavior of this method can become very complicated in complex cases of mounted apps: it is usually better to use [req.baseUrl](/en/5x/api/request/#reqbaseurl) to get the canonical path of the app.

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/5x/api/router/) and [app](/en/5x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

Routes HTTP POST requests to the specified path with the specified callback functions. For more information, see the [routing guide](/en/5x/guide/routing/).

#### [Example](#example-2)

```
app.post('/', (req, res) => {
  res.send('POST request to homepage');
});
```

```
import { type Request, type Response } from 'express';


app.post('/', (req: Request, res: Response) => {
  res.send('POST request to homepage');
});
```

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/5x/api/router/) and [app](/en/5x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

Routes HTTP PUT requests to the specified path with the specified callback functions.

#### [Example](#example-3)

```
app.put('/', (req, res) => {
  res.send('PUT request to homepage');
});
```

```
import { type Request, type Response } from 'express';


app.put('/', (req: Request, res: Response) => {
  res.send('PUT request to homepage');
});
```

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/5x/api/router/) and [app](/en/5x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

Requires runtime:`Node.js >=20.19.3 <21 || >=22.2.0`

Routes HTTP QUERY requests to the specified path with the specified callback functions. For more information, see the [routing guide](/en/5x/guide/routing/).

### Caution

The HTTP QUERY method was standardized on June 15, 2026 as [RFC 10008](https://www.rfc-editor.org/rfc/rfc10008.html). Client and intermediary support is still limited. Verify that your target environments support the QUERY verb before relying on it in production.

The HTTP QUERY method ([RFC 10008](https://www.rfc-editor.org/rfc/rfc10008.html)) is designed for queries whose input is too large or too sensitive to encode in the URL. Unlike `GET`, a QUERY request carries a body containing the query input. Unlike `POST`, it is explicitly **safe and idempotent**, intermediaries and caches can retry it automatically, and the response is cacheable (with the request body included in the cache key).

Use `app.query()` when query parameters would exceed URL length limits, contain sensitive data that should not appear in server logs or browser history, or are too complex to express cleanly as a URL query string, such as deeply nested filters or structured criteria.

Because the query input travels in the request body, `req.body` is `undefined` until you mount a body-parsing middleware such as [`express.json()`](/en/5x/api/express/#expressjson) or [`express.urlencoded()`](/en/5x/api/express/#expressurlencoded) that matches the request’s `Content-Type`.

#### [Example](#example-4)

index.js

```
app.use(express.json()); // populate req.body for application/json payloads


app.query('/search', (req, res) => {
  // complex filter criteria arrive in req.body, not the URL
  const results = db.search(req.body);
  res.json(results);
});
```

index.ts

```
import express, { type Request, type Response } from 'express';


app.use(express.json()); // populate req.body for application/json payloads


app.query('/search', (req: Request, res: Response) => {
  // complex filter criteria arrive in req.body, not the URL
  const results = db.search(req.body);
  res.json(results);
});
```

Returns the rendered HTML of a view via the `callback` function. It accepts an optional parameter that is an object containing local variables for the view. It is like [res.render()](/en/5x/api/response/#resrender), except it cannot send the rendered view to the client on its own.

```
app.render('email', (err, html) => {
  // ...
});


app.render('email', { name: 'Tobi' }, (err, html) => {
  // ...
});
```

```
const app = express();


app
  .route('/events')
  .all((req, res, next) => {
    // runs for all HTTP verbs first
    // think of it as route specific middleware!
  })
  .get((req, res, next) => {
    res.json({});
  })
  .post((req, res, next) => {
    // maybe add a new event...
  });
```

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();


app
  .route('/events')
  .all((req: Request, res: Response, next: NextFunction) => {
    // runs for all HTTP verbs first
    // think of it as route specific middleware!
  })
  .get((req: Request, res: Response, next: NextFunction) => {
    res.json({});
  })
  .post((req: Request, res: Response, next: NextFunction) => {
    // maybe add a new event...
  });
```

```
app.set('title', 'My Site');
app.get('title'); // "My Site"
```

Type:`Boolean | String | Function`Default:`"simple"`

Read [Express behind proxies](/en/5x/guide/behind-proxies/) for more information.

```
app.set('trust proxy', 'loopback');
```

Specify a subnet and an address:

```
app.set('trust proxy', 'loopback, 123.123.123.123');
```

Specify multiple subnets as CSV:

```
app.set('trust proxy', 'loopback, linklocal, uniquelocal');
```

Specify multiple subnets as an array:

```
app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']);
```

When specified, the IP addresses or the subnets are excluded from the address determination process, and the untrusted IP address nearest to the application server is determined as the client’s IP address.

**Number**: Trust the *n*th hop from the front-facing proxy server as the client.

**Function**: Custom trust implementation. Use this only if you know what you are doing.

```
app.set('trust proxy', (ip) => {
  if (ip === '127.0.0.1' || ip === '123.123.123.123')
    return true; // trusted IPs
  else return false;
});
```

```
app.set('etag', (body, encoding) => {
  return generateHash(body, encoding); // consider the function is defined
});
```

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/5x/api/router/) and [app](/en/5x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

Mounts the specified [middleware](/en/5x/guide/using-middleware/) function or functions at the specified path: the middleware function is executed when the base of the requested path matches `path`.

#### [Description](#description)

A route will match any path that follows its path immediately with a “`/`”. For example: `app.use('/apple', ...)` will match “/apple”, “/apple/images”, “/apple/images/news”, and so on.

Since `path` defaults to ”/”, middleware mounted without a path will be executed for every request to the app. For example, this middleware function will be executed for *every* request to the app:

```
app.use((req, res, next) => {
  console.log('Time: %d', Date.now());
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use((req: Request, res: Response, next: NextFunction) => {
  console.log('Time: %d', Date.now());
  next();
});
```

### Note

Sub-apps will:

* Not inherit the value of settings that have a default value. You must set the value in the sub-app.
* Inherit the value of settings with no default value.

For details, see [Application settings](#application-settings).

Middleware functions are executed sequentially, therefore the order of middleware inclusion is important.

```
// this middleware will not allow the request to go beyond it
app.use((req, res, next) => {
  res.send('Hello World');
});


// requests will never reach this route
app.get('/', (req, res) => {
  res.send('Welcome');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


// this middleware will not allow the request to go beyond it
app.use((req: Request, res: Response, next: NextFunction) => {
  res.send('Hello World');
});


// requests will never reach this route
app.get('/', (req: Request, res: Response) => {
  res.send('Welcome');
});
```

**Error-handling middleware**

Error-handling middleware always takes *four* arguments. You must provide four arguments to identify it as an error-handling middleware function. Even if you don’t need to use the `next` object, you must specify it to maintain the signature. Otherwise, the `next` object will be interpreted as regular middleware and will fail to handle errors. For details about error-handling middleware, see: [Error handling](/en/5x/guide/error-handling/).

Define error-handling middleware functions in the same way as other middleware functions, except with four arguments instead of three, specifically with the signature `(err, req, res, next)`):

```
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

#### [Path examples](#path-examples)

The following table provides some simple examples of valid `path` values for mounting middleware.

**Path**: Matches the exact path `/abcd` and any sub-paths starting with `/abcd/` (for example, `/abcd/foo`):

```
app.use('/abcd', (req, res, next) => {
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use('/abcd', (req: Request, res: Response, next: NextFunction) => {
  next();
});
```

**Path Pattern**: This will match paths starting with `/abcd` and `/abd`:

```
app.use('/ab{c}d', (req, res, next) => {
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use('/ab{c}d', (req: Request, res: Response, next: NextFunction) => {
  next();
});
```

**Regular Expression**: This will match paths starting with `/abc` and `/xyz`:

```
app.use(/\/abc|\/xyz/, (req, res, next) => {
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use(/\/abc|\/xyz/, (req: Request, res: Response, next: NextFunction) => {
  next();
});
```

**Array**: This will match paths starting with `/abcd`, `/xyza`, `/lmn`, and `/pqr`:

```
app.use(['/abcd', '/xyza', /\/lmn|\/pqr/], (req, res, next) => {
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use(['/abcd', '/xyza', /\/lmn|\/pqr/], (req: Request, res: Response, next: NextFunction) => {
  next();
});
```

#### [Middleware callback function examples](#middleware-callback-function-examples)

The following table provides some simple examples of middleware functions that can be used as the `callback` argument to `app.use()`, `app.METHOD()`, and `app.all()`.

**Single Middleware**: You can define and mount a middleware function locally.

```
app.use((req, res, next) => {
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use((req: Request, res: Response, next: NextFunction) => {
  next();
});
```

A router is valid middleware.

```
const router = express.Router();
router.get('/', (req, res, next) => {
  next();
});
app.use(router);
```

```
import express, { type Request, type Response, type NextFunction } from 'express';


const router = express.Router();
router.get('/', (req: Request, res: Response, next: NextFunction) => {
  next();
});
app.use(router);
```

An Express app is valid middleware.

```
const subApp = express();
subApp.get('/', (req, res, next) => {
  next();
});
app.use(subApp);
```

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const subApp: Express = express();
subApp.get('/', (req: Request, res: Response, next: NextFunction) => {
  next();
});
app.use(subApp);
```

**Series of Middleware**: You can specify more than one middleware function at the same mount path.

```
const r1 = express.Router();
r1.get('/', (req, res, next) => {
  next();
});


const r2 = express.Router();
r2.get('/', (req, res, next) => {
  next();
});


app.use(r1, r2);
```

```
import express, { type Request, type Response, type NextFunction } from 'express';


const r1 = express.Router();
r1.get('/', (req: Request, res: Response, next: NextFunction) => {
  next();
});


const r2 = express.Router();
r2.get('/', (req: Request, res: Response, next: NextFunction) => {
  next();
});


app.use(r1, r2);
```

**Array**: Use an array to group middleware logically.

```
const r1 = express.Router();
r1.get('/', (req, res, next) => {
  next();
});


const r2 = express.Router();
r2.get('/', (req, res, next) => {
  next();
});


app.use([r1, r2]);
```

```
import express, { type Request, type Response, type NextFunction } from 'express';


const r1 = express.Router();
r1.get('/', (req: Request, res: Response, next: NextFunction) => {
  next();
});


const r2 = express.Router();
r2.get('/', (req: Request, res: Response, next: NextFunction) => {
  next();
});


app.use([r1, r2]);
```

**Combination**: You can combine all the above ways of mounting middleware.

```
function mw1(req, res, next) {
  next();
}
function mw2(req, res, next) {
  next();
}


const r1 = express.Router();
r1.get('/', (req, res, next) => {
  next();
});


const r2 = express.Router();
r2.get('/', (req, res, next) => {
  next();
});


const subApp = express();
subApp.get('/', (req, res, next) => {
  next();
});


app.use(mw1, [mw2, r1, r2], subApp);
```

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


function mw1(req: Request, res: Response, next: NextFunction) {
  next();
}
function mw2(req: Request, res: Response, next: NextFunction) {
  next();
}


const r1 = express.Router();
r1.get('/', (req: Request, res: Response, next: NextFunction) => {
  next();
});


const r2 = express.Router();
r2.get('/', (req: Request, res: Response, next: NextFunction) => {
  next();
});


const subApp: Express = express();
subApp.get('/', (req: Request, res: Response, next: NextFunction) => {
  next();
});


app.use(mw1, [mw2, r1, r2], subApp);
```

Following are some examples of using the [express.static](/en/5x/guide/using-middleware/#built-in-middleware) middleware in an Express app.

Serve static content for the app from the “public” directory in the application directory:

```
// GET /style.css etc
app.use(express.static(path.join(__dirname, 'public')));
```

Mount the middleware at “/static” to serve static content only when their request path is prefixed with “/static”:

```
// GET /static/style.css etc.
app.use('/static', express.static(path.join(__dirname, 'public')));
```

Disable logging for static content requests by loading the logger middleware after the static middleware:

```
app.use(express.static(path.join(__dirname, 'public')));
app.use(logger());
```

Serve static files from multiple directories, but give precedence to ”./public” over the others:

```
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'files')));
app.use(express.static(path.join(__dirname, 'uploads')));
```

----
url: https://expressjs.com/en/4x/guide/using-middleware
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/guide/using-middleware.mdx)

# [Using middleware](#overview)

Express is a routing and middleware web framework with minimal functionality of its own: an Express application is essentially a series of middleware function calls executed during the request-response cycle.

*Middleware* functions are functions that have access to:

* The [request object](/en/4x/api/request/) (`req`)
* The [response object](/en/4x/api/response/) (`res`)

Bind application-level middleware to an instance of the [app object](/en/4x/api/application/) by using the `app.use()` and `app.METHOD()` functions, where `METHOD` is the lowercase HTTP method of the request that the middleware function handles, such as `get`, `post`, `put`, or `delete`.

### [Middleware without a mount path](#middleware-without-a-mount-path)

The following middleware function runs every time the app receives a request:

index.cjs

```
const express = require('express');
const app = express();


app.use((req, res, next) => {
  console.log('Time:', Date.now());
  next();
});
```

index.mjs

```
import express from 'express';


const app = express();


app.use((req, res, next) => {
  console.log('Time:', Date.now());
  next();
});
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();


app.use((req: Request, res: Response, next: NextFunction) => {
  console.log('Time:', Date.now());
  next();
});
```

### [Middleware mounted on a path](#middleware-mounted-on-a-path)

The following middleware function runs for any type of HTTP request on the `/user/:id` path:

```
app.use('/user/:id', (req, res, next) => {
  console.log('Request Type:', req.method);
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use('/user/:id', (req: Request, res: Response, next: NextFunction) => {
  console.log('Request Type:', req.method);
  next();
});
```

### [Route handlers](#route-handlers)

This example shows a route and its handler function (middleware system). The function handles GET requests to the `/user/:id` path:

```
app.get('/user/:id', (req, res) => {
  res.send('USER');
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/:id', (req: Request, res: Response) => {
  res.send('USER');
});
```

### [Middleware sub-stacks](#middleware-sub-stacks)

Multiple middleware functions can be loaded together at a mount point to form a middleware sub-stack. This example prints request info for any type of HTTP request to the `/user/:id` path:

```
app.use(
  '/user/:id',
  (req, res, next) => {
    console.log('Request URL:', req.originalUrl);
    next();
  },
  (req, res, next) => {
    console.log('Request Type:', req.method);
    next();
  }
);
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use(
  '/user/:id',
  (req: Request, res: Response, next: NextFunction) => {
    console.log('Request URL:', req.originalUrl);
    next();
  },
  (req: Request, res: Response, next: NextFunction) => {
    console.log('Request Type:', req.method);
    next();
  }
);
```

### [Multiple route handlers](#multiple-route-handlers)

Route handlers enable you to define multiple routes for a path. The example below defines two routes for GET requests to the `/user/:id` path. The second route will not cause any problems, but it will never get called because the first route ends the request-response cycle.

```
app.get(
  '/user/:id',
  (req, res, next) => {
    console.log('ID:', req.params.id);
    next();
  },
  (req, res) => {
    res.send('User Info');
  }
);


// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', (req, res) => {
  res.send(req.params.id);
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get(
  '/user/:id',
  (req: Request, res: Response, next: NextFunction) => {
    console.log('ID:', req.params.id);
    next();
  },
  (req: Request, res: Response) => {
    res.send('User Info');
  }
);


// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', (req: Request, res: Response) => {
  res.send(req.params.id);
});
```

### [Skipping to the next route](#skipping-to-the-next-route)

Call `next('route')` to skip the remaining middleware functions in a router middleware stack and pass control to the next route.

### Note

`next('route')` will work only in middleware functions that were loaded by using the `app.METHOD()` or `router.METHOD()` functions.

In the following example, if the user ID is `0`, the first handler skips to the next route, which sends a special response:

```
app.get(
  '/user/:id',
  (req, res, next) => {
    // if the user ID is 0, skip to the next route
    if (req.params.id === '0') next('route');
    // otherwise pass the control to the next middleware function in this stack
    else next();
  },
  (req, res) => {
    // send a regular response
    res.send('regular');
  }
);


// handler for the /user/:id path, which sends a special response
app.get('/user/:id', (req, res) => {
  res.send('special');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get(
  '/user/:id',
  (req: Request, res: Response, next: NextFunction) => {
    // if the user ID is 0, skip to the next route
    if (req.params.id === '0') next('route');
    // otherwise pass the control to the next middleware function in this stack
    else next();
  },
  (req: Request, res: Response) => {
    // send a regular response
    res.send('regular');
  }
);


// handler for the /user/:id path, which sends a special response
app.get('/user/:id', (req: Request, res: Response) => {
  res.send('special');
});
```

### [Reusable middleware arrays](#reusable-middleware-arrays)

Middleware functions can also be grouped into arrays for better reusability. This example shows an array with a middleware sub-stack that handles GET requests to the `/user/:id` path:

```
function logOriginalUrl(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
}


function logMethod(req, res, next) {
  console.log('Request Type:', req.method);
  next();
}


const logStuff = [logOriginalUrl, logMethod];
app.get('/user/:id', logStuff, (req, res) => {
  res.send('User Info');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


function logOriginalUrl(req: Request, res: Response, next: NextFunction) {
  console.log('Request URL:', req.originalUrl);
  next();
}


function logMethod(req: Request, res: Response, next: NextFunction) {
  console.log('Request Type:', req.method);
  next();
}


const logStuff = [logOriginalUrl, logMethod];
app.get('/user/:id', logStuff, (req: Request, res: Response) => {
  res.send('User Info');
});
```

## [Router-level middleware](#router-level-middleware)

Router-level middleware works the same way as application-level middleware, except it is bound to an instance of `express.Router()`.

```
const router = express.Router();
```

```
import express from 'express';


const router = express.Router();
```

Load router-level middleware by using the `router.use()` and `router.METHOD()` functions.

The following example code replicates the middleware system that is shown above for application-level middleware, by using router-level middleware:

index.cjs

```
const express = require('express');
const app = express();
const router = express.Router();


// a middleware function with no mount path. This code is executed for every request to the router
router.use((req, res, next) => {
  console.log('Time:', Date.now());
  next();
});


// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use(
  '/user/:id',
  (req, res, next) => {
    console.log('Request URL:', req.originalUrl);
    next();
  },
  (req, res, next) => {
    console.log('Request Type:', req.method);
    next();
  }
);


// a middleware sub-stack that handles GET requests to the /user/:id path
router.get(
  '/user/:id',
  (req, res, next) => {
    // if the user ID is 0, skip to the next route
    if (req.params.id === '0') next('route');
    // otherwise pass control to the next middleware function in this stack
    else next();
  },
  (req, res) => {
    // render a regular page
    res.render('regular');
  }
);


// handler for the /user/:id path, which renders a special page
router.get('/user/:id', (req, res) => {
  console.log(req.params.id);
  res.render('special');
});


// mount the router on the app
app.use('/', router);
```

index.mjs

```
import express from 'express';


const app = express();
const router = express.Router();


// a middleware function with no mount path. This code is executed for every request to the router
router.use((req, res, next) => {
  console.log('Time:', Date.now());
  next();
});


// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use(
  '/user/:id',
  (req, res, next) => {
    console.log('Request URL:', req.originalUrl);
    next();
  },
  (req, res, next) => {
    console.log('Request Type:', req.method);
    next();
  }
);


// a middleware sub-stack that handles GET requests to the /user/:id path
router.get(
  '/user/:id',
  (req, res, next) => {
    // if the user ID is 0, skip to the next route
    if (req.params.id === '0') next('route');
    // otherwise pass control to the next middleware function in this stack
    else next();
  },
  (req, res) => {
    // render a regular page
    res.render('regular');
  }
);


// handler for the /user/:id path, which renders a special page
router.get('/user/:id', (req, res) => {
  console.log(req.params.id);
  res.render('special');
});


// mount the router on the app
app.use('/', router);
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();
const router = express.Router();


// a middleware function with no mount path. This code is executed for every request to the router
router.use((req: Request, res: Response, next: NextFunction) => {
  console.log('Time:', Date.now());
  next();
});


// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use(
  '/user/:id',
  (req: Request, res: Response, next: NextFunction) => {
    console.log('Request URL:', req.originalUrl);
    next();
  },
  (req: Request, res: Response, next: NextFunction) => {
    console.log('Request Type:', req.method);
    next();
  }
);


// a middleware sub-stack that handles GET requests to the /user/:id path
router.get(
  '/user/:id',
  (req: Request, res: Response, next: NextFunction) => {
    // if the user ID is 0, skip to the next route
    if (req.params.id === '0') next('route');
    // otherwise pass control to the next middleware function in this stack
    else next();
  },
  (req: Request, res: Response) => {
    // render a regular page
    res.render('regular');
  }
);


// handler for the /user/:id path, which renders a special page
router.get('/user/:id', (req: Request, res: Response) => {
  console.log(req.params.id);
  res.render('special');
});


// mount the router on the app
app.use('/', router);
```

### [Skipping out of a router](#skipping-out-of-a-router)

Use `next('router')` to skip the rest of the router’s middleware functions and pass control back out of the router instance.

In the following example, the router only responds when the request includes an `x-auth` header. Otherwise, `next('router')` exits the router and the app responds with a 401 status:

index.cjs

```
const express = require('express');
const app = express();
const router = express.Router();


// predicate the router with a check and bail out when needed
router.use((req, res, next) => {
  if (!req.headers['x-auth']) return next('router');
  next();
});


router.get('/user/:id', (req, res) => {
  res.send('hello, user!');
});


// use the router and 401 anything falling through
app.use('/admin', router, (req, res) => {
  res.sendStatus(401);
});
```

index.mjs

```
import express from 'express';


const app = express();
const router = express.Router();


// predicate the router with a check and bail out when needed
router.use((req, res, next) => {
  if (!req.headers['x-auth']) return next('router');
  next();
});


router.get('/user/:id', (req, res) => {
  res.send('hello, user!');
});


// use the router and 401 anything falling through
app.use('/admin', router, (req, res) => {
  res.sendStatus(401);
});
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();
const router = express.Router();


// predicate the router with a check and bail out when needed
router.use((req: Request, res: Response, next: NextFunction) => {
  if (!req.headers['x-auth']) return next('router');
  next();
});


router.get('/user/:id', (req: Request, res: Response) => {
  res.send('hello, user!');
});


// use the router and 401 anything falling through
app.use('/admin', router, (req: Request, res: Response) => {
  res.sendStatus(401);
});
```

## [Error-handling middleware](#error-handling-middleware)

Define error-handling middleware functions in the same way as other middleware functions, except with four arguments instead of three, specifically with the signature `(err, req, res, next)`:

```
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

### Caution

Error-handling middleware always takes *four* arguments. You must provide four arguments to identify it as an error-handling middleware function. Even if you don’t need to use the `next` object, you must specify it to maintain the signature. Otherwise, the `next` object will be interpreted as regular middleware and will fail to handle errors.

## [Built-in middleware](#built-in-middleware)

Starting with version 4.x, Express no longer depends on [Connect](https://github.com/senchalabs/connect). The middleware functions that were previously included with Express are now in separate modules; see [the list of middleware functions](https://github.com/senchalabs/connect#middleware).

Express has the following built-in middleware functions:

* [express.static](/en/4x/api/express/#expressstatic) serves static assets such as HTML files, images, and so on.
* [express.json](/en/4x/api/express/#expressjson) parses incoming requests with JSON payloads. **NOTE: Available with Express 4.16.0+**
* [express.raw](/en/4x/api/express/#expressraw) parses incoming requests with Buffer payloads. **NOTE: Available with Express 4.17.0+**
* [express.text](/en/4x/api/express/#expresstext) parses incoming requests with text payloads. **NOTE: Available with Express 4.17.0+**
* [express.urlencoded](/en/4x/api/express/#expressurlencoded) parses incoming requests with URL-encoded payloads. **NOTE: Available with Express 4.16.0+**

## [Third-party middleware](#third-party-middleware)

Use third-party middleware to add functionality to Express apps.

Install the Node.js module for the required functionality, then load it in your app at the application level or at the router level.

The following example illustrates installing and loading the cookie-parsing middleware function `cookie-parser`:

Terminal window

```
npm install cookie-parser
```

Terminal window

```
yarn add cookie-parser
```

Terminal window

```
pnpm add cookie-parser
```

Terminal window

```
bun add cookie-parser
```

index.cjs

```
const express = require('express');
const app = express();
const cookieParser = require('cookie-parser');


// load the cookie-parsing middleware
app.use(cookieParser());
```

index.mjs

```
import express from 'express';
import cookieParser from 'cookie-parser';


const app = express();


// load the cookie-parsing middleware
app.use(cookieParser());
```

index.ts

```
import express, { type Express } from 'express';
import cookieParser from 'cookie-parser';


const app: Express = express();


// load the cookie-parsing middleware
app.use(cookieParser());
```

----
url: https://expressjs.com/en/blog/2026-05-18-a-new-look-for-express
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2026-05-18-a-new-look-for-express)

announcements

# [A New Look for Express](#overview)

Sebastian BeltranMay 18, 2026

[](https://x.com/intent/tweet?text=A%20New%20Look%20for%20Express\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-05-18-a-new-look-for-express%2F)[](https://bsky.app/intent/compose?text=A%20New%20Look%20for%20Express%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-05-18-a-new-look-for-express%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-05-18-a-new-look-for-express%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-05-18-a-new-look-for-express%2F\&text=A%20New%20Look%20for%20Express)[](https://wa.me/?text=A%20New%20Look%20for%20Express%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-05-18-a-new-look-for-express%2F)[](/feed.xml)

Express has been one of the most important frameworks in the Node.js ecosystem for over a decade. Millions of developers have built their first API, their first web app, or even their first startup with Express. Yet, while the framework kept evolving, the website remained largely the same for years.

In 2024, the Express project went through a [major reboot](/en/blog/2025-01-09-rewind-2024-triumphs-and-2025-vision/). A new team, a fresh vision for the framework, and a clear path forward. That momentum inspired me to start contributing to Express with a simple goal: improve the documentation experience. Good documentation helps everyone, from beginners building their first server to experienced developers looking for the right API detail, or even those building frameworks on top of Express. In early 2025, that goal started to become a reality when the [redesign of the Express documentation](https://github.com/expressjs/expressjs.com/issues/1787) officially kicked off. What began as a documentation effort eventually grew into something much bigger, a complete redesign of the website and a brand-new logo for Express.

In short: we rebuilt the Express website, improved the documentation experience, and introduced a new logo and visual identity to match where the project is headed.

## [A New Website](#a-new-website)

Rebuilding the Express website was not only a visual refresh. It was also an opportunity to rethink the foundations of how the documentation is organized, generated, and maintained.

Under the hood, we moved from Jekyll to [Astro](https://astro.build), chosen after a long [community discussion](https://github.com/expressjs/expressjs.com/discussions/2019) weighing tradeoffs and long-term maintenance. It gave us the flexibility we needed for content-heavy pages, strong performance, solid i18n support, and a component model that doesn’t lock us into a single UI framework.

### [What’s New in the Documentation](#whats-new-in-the-documentation)

The redesign was also a chance to bring long-requested improvements to how the documentation works.

* **Improved versioning.** Documentation pages now support multiple versions of Express side by side. You can read the docs for the version you’re actually running, and the content stays stable as new versions are released. The previous site didn’t make this easy to achieve, which often led to confusion between versions. This is especially helpful now that Express 5 is the latest stable release and many projects are still on Express 4.
* **AI-powered search.** The new search is built on top of [Orama](https://orama.com) and goes beyond keyword matching. You can ask questions in natural language and get contextual answers drawn directly from the documentation, which makes finding the right API or concept much faster.
* **`llms.txt` support.** Every section of the documentation is now available through an `llms.txt` endpoint, following the [llms.txt](https://llmstxt.org) convention. This makes it much easier for language models, AI assistants, and other tools to access accurate, up-to-date Express documentation.

### [What’s Next for the Documentation](#whats-next-for-the-documentation)

Launching the new site is just the start. The next phase of this effort is focused on the documentation itself, closing the gaps that have built up over the years and bringing every Express API up to the standard the framework deserves.

A few of the things ahead:

* **Closing content gaps.** Many guides and API references still need fresh examples, clearer explanations, or rewrites that reflect how Express is used today, especially with Express 5.
* **Better translations.** The site has solid i18n foundations, but most translations are incomplete or out of date. The goal is to make translating Express docs a simple contribution for any native speaker.
* **Keeping docs aligned with releases.** New Express versions should ship with documentation that’s already ready, not catch up months later.

The new site is designed to make contributing easier than ever. If you spot something that could be better, an unclear explanation, a missing example, or a translation that needs love, please [open an issue or a pull request](https://github.com/expressjs/expressjs.com).

## [A New Logo](#a-new-logo)

One of the most visible changes is the brand-new Express logo. This wasn’t something we designed in isolation. It came out of a collaborative workshop with the [Orama](https://orama.com) team, where community members and the Express Technical Committee came together to define who Express is today and where it’s heading. The entire process was handled publicly, so anyone in the community could participate and share their voice.

Before jumping into the visual identity, we worked together on the foundations that would guide every design decision.

### [Vision and Mission](#vision-and-mission)

We started by asking ourselves two simple questions: what is Express today, and where do we want it to go? The answers became the vision and mission that now guide every decision, from the framework itself to the documentation and the new visual identity.

### [Brand Values](#brand-values)

With the vision and mission in place, we distilled them into three values that describe how Express shows up for its users. They anchor the new identity and set the tone for everything the project communicates.

### [The Logo](#the-logo)

With that foundation in place, the design work was led by [Angela Angelini](https://www.linkedin.com/in/angeliningl/) and [Davide Spaziani](https://www.linkedin.com/in/davidespazianitesta/) from the Orama team. Over several months, multiple logo proposals were shared with the community for feedback. You can still explore all of them in the [original discussion](https://github.com/expressjs/express/discussions/6670).

After gathering feedback from the community, both on the OpenJS Foundation [Slack](https://slack-invite.openjsf.org) and across social media, we landed on the logo and favicon you see today:

It represents a fresh chapter for Express while staying true to the minimalism and clarity that have always defined the framework.

## [Built by the Community](#built-by-the-community)

The redesign was not a solo effort. Dozens of people from across the Express community contributed code, design, reviews, and feedback over more than a year.

The effort was led by [Sebastian Beltran](https://github.com/bjohansebas), with [Francesca Giannino](https://github.com/g-francesca) driving much of the design and UI work across the new site, and [Angela Angelini](https://www.linkedin.com/in/angeliningl/) and [Davide Spaziani](https://www.linkedin.com/in/davidespazianitesta/) leading the brand workshop that shaped the new visual identity.

A huge thank you goes to the [Orama](https://orama.com) team for sponsoring [Francesca Giannino](https://github.com/g-francesca), [Angela Angelini](https://www.linkedin.com/in/angeliningl/), [Michele Riva](https://github.com/micheleriva), and [Davide Spaziani](https://www.linkedin.com/in/davidespazianitesta/), and for the design, feedback, and support they brought to every stage of the project.

From the Express side, the redesign was shaped by many hands: [Ulises Gascón](https://github.com/ulisesgascon), [Rand McKinney](https://github.com/crandmck), [Jon Church](https://github.com/jonchurch), [Shubham Oulkar](https://github.com/ShubhamOulkar), the rest of the [Express Technical Committee](https://github.com/expressjs/express#tc-technical-committee), and everyone who contributed reviews, issues, or comments along the way. The full history, including every PR that made it into the redesign, lives in [the main pull request](https://github.com/expressjs/expressjs.com/pull/2169).

More than a year of work went into this launch. In open source, progress is rarely fast: decisions take discussion, design takes iteration, and reviews take time. But step by step, a community can build something it’s proud of, and this is one of those steps.

Thank you to everyone who has written code with Express over the years, to the people who helped build this new site, and to the broader community that keeps the project alive. We can’t wait to see what you build next.

## More from Express

[announcements](/en/blog/2025-05-16-express-cleanup-legacy-packages)

## [Spring Cleaning in Express.js: Deprecations and the Path Ahead](/en/blog/2025-05-16-express-cleanup-legacy-packages)

[Express Technical CommitteeMay 16, 2025](/en/blog/2025-05-16-express-cleanup-legacy-packages)

----
url: https://expressjs.com/en/resources/middleware/response-time
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/response-time.mdx)

# [response-time middleware](#overview)

v2.3.4[GitHub](https://github.com/expressjs/response-time)[Changelog](https://github.com/expressjs/response-time/releases)[npm](https://www.npmjs.com/package/response-time)

Response time for Node.js servers.

This module creates a middleware that records the response time for requests in HTTP servers. The “response time” is defined here as the elapsed time from when a request enters this middleware to when the headers are written out to the client.

## [Installation](#installation)

This is a [Node.js](https://nodejs.org/en/) module available through the [npm registry](https://www.npmjs.com/). Installation is done using the [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):

Terminal window

```
npm install response-time
```

Terminal window

```
yarn add response-time
```

Terminal window

```
pnpm add response-time
```

Terminal window

```
bun add response-time
```

### Note

`response-time` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/response-time
```

Terminal window

```
yarn add --dev @types/response-time
```

Terminal window

```
pnpm add --save-dev @types/response-time
```

Terminal window

```
bun add --dev @types/response-time
```

## [API](#api)

```
var responseTime = require('response-time');
```

### [responseTime(\[options\])](#responsetimeoptions)

Create a middleware that adds a `X-Response-Time` header to responses. If you don’t want to use this module to automatically set a header, please see the section about [`responseTime(fn)`](#responsetimefn).

#### [Options](#options)

The `responseTime` function accepts an optional `options` object that may contain any of the following keys:

##### [digits](#digits)

The fixed number of digits to include in the output, which is always in milliseconds, defaults to `3` (ex: `2.300ms`).

##### [header](#header)

The name of the header to set, defaults to `X-Response-Time`.

##### [suffix](#suffix)

Boolean to indicate if units of measurement suffix should be added to the output, defaults to `true` (ex: `2.300ms` vs `2.300`).

### [responseTime(fn)](#responsetimefn)

Create a new middleware that records the response time of a request and makes this available to your own function `fn`. The `fn` argument will be invoked as `fn(req, res, time)`, where `time` is a number in milliseconds.

## [Examples](#examples)

### [express/connect](#expressconnect)

```
var express = require('express');
var responseTime = require('response-time');


var app = express();


app.use(responseTime());


app.get('/', function (req, res) {
  res.send('hello, world!');
});
```

### [vanilla http server](#vanilla-http-server)

```
var finalhandler = require('finalhandler');
var http = require('http');
var responseTime = require('response-time');


// create "middleware"
var _responseTime = responseTime();


http.createServer(function (req, res) {
  var done = finalhandler(req, res);
  _responseTime(req, res, function (err) {
    if (err) return done(err);


    // respond to request
    res.setHeader('content-type', 'text/plain');
    res.end('hello, world!');
  });
});
```

### [response time metrics](#response-time-metrics)

```
var express = require('express');
var responseTime = require('response-time');
var StatsD = require('node-statsd');


var app = express();
var stats = new StatsD();


stats.socket.on('error', function (error) {
  console.error(error.stack);
});


app.use(
  responseTime(function (req, res, time) {
    var stat = (req.method + req.url).toLowerCase().replace(/[:.]/g, '').replace(/\//g, '_');
    stats.timing(stat, time);
  })
);


app.get('/', function (req, res) {
  res.send('hello, world!');
});
```

## [License](#license)

[MIT](https://github.com/expressjs/response-time/blob/HEAD/LICENSE)

----
url: https://expressjs.com/en/resources/middleware/serve-index
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/serve-index.mdx)

# [serve-index middleware](#overview)

v1.9.2[GitHub](https://github.com/expressjs/serve-index)[Changelog](https://github.com/expressjs/serve-index/releases)[npm](https://www.npmjs.com/package/serve-index)

Serves pages that contain directory listings for a given path.

## [Install](#install)

This is a [Node.js](https://nodejs.org/en/) module available through the [npm registry](https://www.npmjs.com/). Installation is done using the [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):

Terminal window

```
npm install serve-index
```

Terminal window

```
yarn add serve-index
```

Terminal window

```
pnpm add serve-index
```

Terminal window

```
bun add serve-index
```

### Note

`serve-index` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/serve-index
```

Terminal window

```
yarn add --dev @types/serve-index
```

Terminal window

```
pnpm add --save-dev @types/serve-index
```

Terminal window

```
bun add --dev @types/serve-index
```

## [API](#api)

```
var serveIndex = require('serve-index');
```

### [serveIndex(path, options)](#serveindexpath-options)

Returns middleware that serves an index of the directory in the given `path`.

The `path` is based off the `req.url` value, so a `req.url` of `'/some/dir` with a `path` of `'public'` will look at `'public/some/dir'`. If you are using something like `express`, you can change the URL “base” with `app.use` (see the express example).

#### [Options](#options)

Serve index accepts these properties in the options object.

##### [filter](#filter)

Apply this filter function to files. Defaults to `false`. The `filter` function is called for each file, with the signature `filter(filename, index, files, dir)` where `filename` is the name of the file, `index` is the array index, `files` is the array of files and `dir` is the absolute path the file is located (and thus, the directory the listing is for).

##### [hidden](#hidden)

Display hidden (dot) files. Defaults to `false`.

##### [icons](#icons)

Display icons. Defaults to `false`.

##### [stylesheet](#stylesheet)

Optional path to a CSS stylesheet. Defaults to a built-in stylesheet.

##### [template](#template)

Optional path to an HTML template or a function that will render a HTML string. Defaults to a built-in template.

When given a string, the string is used as a file path to load and then the following tokens are replaced in templates:

* `{directory}` with the name of the directory.
* `{files}` with the HTML of an unordered list of file links.
* `{linked-path}` with the HTML of a link to the directory.
* `{style}` with the specified stylesheet and embedded images.

When given as a function, the function is called as `template(locals, callback)` and it needs to invoke `callback(error, htmlString)`. The following are the provided locals:

* `directory` is the directory being displayed (where `/` is the root).

* `displayIcons` is a Boolean for if icons should be rendered or not.

* `fileList` is a sorted array of files in the directory. The array contains objects with the following properties:

  * `name` is the relative name for the file.
  * `stat` is a `fs.Stats` object for the file.

* `path` is the full filesystem path to `directory`.

* `style` is the default stylesheet or the contents of the `stylesheet` option.

* `viewName` is the view name provided by the `view` option.

##### [view](#view)

Display mode. `tiles` and `details` are available. Defaults to `tiles`.

## [Examples](#examples)

### [Serve directory indexes with vanilla node.js http server](#serve-directory-indexes-with-vanilla-nodejs-http-server)

```
var finalhandler = require('finalhandler');
var http = require('http');
var serveIndex = require('serve-index');
var serveStatic = require('serve-static');


// Serve directory indexes for public/ftp folder (with icons)
var index = serveIndex('public/ftp', { icons: true });


// Serve up public/ftp folder files
var serve = serveStatic('public/ftp');


// Create server
var server = http.createServer(function onRequest(req, res) {
  var done = finalhandler(req, res);
  serve(req, res, function onNext(err) {
    if (err) return done(err);
    index(req, res, done);
  });
});


// Listen
server.listen(3000);
```

### [Serve directory indexes with express](#serve-directory-indexes-with-express)

```
var express = require('express');
var serveIndex = require('serve-index');


var app = express();


// Serve URLs like /ftp/thing as public/ftp/thing
// The express.static serves the file contents
// The serveIndex is this module serving the directory
app.use('/ftp', express.static('public/ftp'), serveIndex('public/ftp', { icons: true }));


// Listen
app.listen(3000);
```

## [License](#license)

[MIT](https://github.com/expressjs/serve-index/blob/HEAD/LICENSE). The [Silk](https://web.archive.org/web/20230105212205/http://www.famfamfam.com/lab/icons/silk/) icons are created by/copyright of [FAMFAMFAM](https://web.archive.org/web/20230109095739/http://www.famfamfam.com/).

----
url: https://expressjs.com/en/4x/guide/debugging
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/guide/debugging.mdx)

# [Debugging Express](#overview)

To see all the internal logs used in Express, set the `DEBUG` environment variable to `express:*` when launching your app.

Terminal window

```
$ DEBUG=express:* node index.js
```

On Windows, use the corresponding command.

Terminal window

```
> $env:DEBUG = "express:*"; node index.js
```

Running this command on the default app generated by the [express generator](/en/4x/starter/generator/) prints the following output:

Terminal window

```
$ DEBUG=express:* node ./bin/www
  express:router:route new / +0ms
  express:router:layer new / +1ms
  express:router:route get / +1ms
  express:router:layer new / +0ms
  express:router:route new / +1ms
  express:router:layer new / +0ms
  express:router:route get / +0ms
  express:router:layer new / +0ms
  express:application compile etag weak +1ms
  express:application compile query parser extended +0ms
  express:application compile trust proxy false +0ms
  express:application booting in development mode +1ms
  express:router use / query +0ms
  express:router:layer new / +0ms
  express:router use / expressInit +0ms
  express:router:layer new / +0ms
  express:router use / favicon +1ms
  express:router:layer new / +0ms
  express:router use / logger +0ms
  express:router:layer new / +0ms
  express:router use / jsonParser +0ms
  express:router:layer new / +1ms
  express:router use / urlencodedParser +0ms
  express:router:layer new / +0ms
  express:router use / cookieParser +0ms
  express:router:layer new / +0ms
  express:router use / stylus +90ms
  express:router:layer new / +0ms
  express:router use / serveStatic +0ms
  express:router:layer new / +0ms
  express:router use / router +0ms
  express:router:layer new / +1ms
  express:router use /users router +0ms
  express:router:layer new /users +0ms
  express:router use / &lt;anonymous&gt; +0ms
  express:router:layer new / +0ms
  express:router use / &lt;anonymous&gt; +0ms
  express:router:layer new / +0ms
  express:router use / &lt;anonymous&gt; +0ms
  express:router:layer new / +0ms
```

When a request is then made to the app, you will see the logs specified in the Express code:

Terminal window

```
  express:router dispatching GET / +4h
  express:router query  : / +2ms
  express:router expressInit  : / +0ms
  express:router favicon  : / +0ms
  express:router logger  : / +1ms
  express:router jsonParser  : / +0ms
  express:router urlencodedParser  : / +1ms
  express:router cookieParser  : / +0ms
  express:router stylus  : / +0ms
  express:router serveStatic  : / +2ms
  express:router router  : / +2ms
  express:router dispatching GET / +1ms
  express:view lookup "index.pug" +338ms
  express:view stat "/projects/example/views/index.pug" +0ms
  express:view render "/projects/example/views/index.pug" +1ms
```

To see the logs only from the router implementation, set the value of `DEBUG` to `express:router`. Likewise, to see logs only from the application implementation, set the value of `DEBUG` to `express:application`, and so on.

## [Using `debug` in your own code](#using-debug-in-your-own-code)

The same [debug](https://www.npmjs.com/package/debug) module that Express uses internally is available for your application code. Install it, create one or more loggers scoped to a namespace of your choosing, and call them wherever you would otherwise use `console.log`:

Terminal window

```
npm install debug
```

Terminal window

```
yarn add debug
```

Terminal window

```
pnpm add debug
```

Terminal window

```
bun add debug
```

index.cjs

```
const express = require('express');
const debug = require('debug')('myapp:server');


const app = express();


app.get('/', (req, res) => {
  debug('handling request from %s', req.ip);
  res.send('Hello World!');
});


app.listen(3000, () => {
  debug('listening on port 3000');
});
```

index.mjs

```
import express from 'express';
import debugModule from 'debug';


const debug = debugModule('myapp:server');
const app = express();


app.get('/', (req, res) => {
  debug('handling request from %s', req.ip);
  res.send('Hello World!');
});


app.listen(3000, () => {
  debug('listening on port 3000');
});
```

These statements print nothing by default. Enable them through the same `DEBUG` environment variable, using your own namespace:

Terminal window

```
$ DEBUG=myapp:* node index.js
```

You can specify more than one debug namespace by assigning a comma-separated list of names:

Terminal window

```
$ DEBUG=myapp:*,express:router node index.js
```

## [Setting DEBUG in your IDE](#setting-debug-in-your-ide)

The `DEBUG` environment variable can be set by any process launcher that supports environment variables, including the run and debug configurations of your IDE. For example, in VS Code you can set it in the `env` property of a launch configuration:

.vscode/launch.json

```
{
  "type": "node",
  "request": "launch",
  "name": "Launch Express app",
  "program": "${workspaceFolder}/index.js",
  "env": { "DEBUG": "express:*" }
}
```

See [Node.js debugging in VS Code](https://code.visualstudio.com/docs/nodejs/nodejs-debugging) for the full list of launch options.

## [Using the Node.js inspector](#using-the-nodejs-inspector)

Debug logs show what the app did; for stepping through your code with breakpoints, use the built-in Node.js inspector. Start your app with the `--inspect` flag:

Terminal window

```
$ node --inspect index.js
```

Then attach a debugging client, such as Chrome DevTools (open `chrome://inspect`), VS Code, or any other inspector-capable tool, to set breakpoints in your route handlers and middleware, step through code, and inspect variables.

If you need to debug something that happens during startup, use `--inspect-brk` instead, which pauses execution on the first line until a debugger attaches. See the [Node.js debugging guide](https://nodejs.org/learn/getting-started/debugging) for details.

## [Debugging the HTTP layer](#debugging-the-http-layer)

Express runs on top of the Node.js `http` module, which has its own debugging facilities that work with any Express app.

Setting the `NODE_DEBUG` environment variable to `http` makes Node.js print internal logs from the HTTP layer, such as connection handling and socket events:

Terminal window

```
$ NODE_DEBUG=http node index.js
```

You can combine it with other subsystems, such as `net` or `stream`, in a comma-separated list. Be aware that this output can expose sensitive data such as authentication headers, so use it only in development.

## [Diagnostics channels](#diagnostics-channels)

Node.js publishes an event for every HTTP request through the [diagnostics\_channel](https://nodejs.org/api/diagnostics_channel.html#http) module, which you can subscribe to without patching Express or adding middleware:

index.cjs

```
const { subscribe } = require('node:diagnostics_channel');


subscribe('http.server.request.start', ({ request }) => {
  console.log(`${request.method} ${request.url}`);
});
```

index.mjs

```
import { subscribe } from 'node:diagnostics_channel';


subscribe('http.server.request.start', ({ request }) => {
  console.log(`${request.method} ${request.url}`);
});
```

Other built-in channels cover the rest of the request lifecycle, such as `http.server.response.finish`, and the client side of `http.request` calls. See the [diagnostics\_channel documentation](https://nodejs.org/api/diagnostics_channel.html#http) for the full list.

## [Advanced options](#advanced-options)

When running through Node.js, you can set a few environment variables that will change the behavior of the debug logging:

| Name                | Purpose                                           |
| ------------------- | ------------------------------------------------- |
| `DEBUG`             | Enables/disables specific debugging namespaces.   |
| `DEBUG_COLORS`      | Whether or not to use colors in the debug output. |
| `DEBUG_DEPTH`       | Object inspection depth.                          |
| `DEBUG_FD`          | File descriptor to write debug output to.         |
| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects.     |

### Note

The environment variables beginning with `DEBUG_` end up being converted into an Options object that gets used with `%o`/`%O` formatters. See the Node.js documentation for [`util.inspect()`](https://nodejs.org/api/util.html#utilinspectobject-options) for the complete list.

----
url: https://expressjs.com/en/4x/guide/overriding-express-api
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/guide/overriding-express-api.mdx)

# [Overriding the Express API](#overview)

The Express API consists of various methods and properties on the [request](/en/4x/api/request/) and [response](/en/4x/api/response/) objects. These are inherited by prototype. There are two extension points for the Express API:

1. The global prototypes at `express.request` and `express.response`.
2. App-specific prototypes at `app.request` and `app.response`.

Altering the global prototypes will affect all loaded Express apps in the same process. If desired, alterations can be made app-specific by only altering the app-specific prototypes after creating a new app.

## [Methods](#methods)

You can override the signature and behavior of existing methods with your own, by assigning a custom function.

Following is an example of overriding the behavior of [res.sendStatus](/en/4x/api/response/#ressendstatus).

```
app.response.sendStatus = function (statusCode, type, message) {
  // code is intentionally kept simple for demonstration purpose
  return this.contentType(type).status(statusCode).send(message);
};
```

```
import { type Response } from 'express';


// Broaden the type of sendStatus so call sites accept the new arguments.
declare module 'express-serve-static-core' {
  interface Response {
    sendStatus(statusCode: number, type: string, message: string): this;
  }
}


app.response.sendStatus = function (
  this: Response,
  statusCode: number,
  type: string,
  message: string
) {
  // code is intentionally kept simple for demonstration purpose
  return this.contentType(type).status(statusCode).send(message);
} as Response['sendStatus'];
```

The above implementation completely changes the original signature of `res.sendStatus`. It now accepts a status code, encoding type, and the message to be sent to the client.

In TypeScript, augmenting `express-serve-static-core` adds the new overload to the `Response` type so call sites such as `res.sendStatus(404, 'application/json', body)` type-check. The assignment is cast with `as Response['sendStatus']` because replacing a method with a different signature cannot be checked against the original declaration.

The overridden method may now be used this way:

```
res.sendStatus(404, 'application/json', '{"error":"resource not found"}');
```

```
Object.defineProperty(app.request, 'ip', {
  configurable: true,
  enumerable: true,
  get() {
    return this.get('Client-IP');
  },
});
```

```
import { type Request } from 'express';


Object.defineProperty(app.request, 'ip', {
  configurable: true,
  enumerable: true,
  get(this: Request) {
    return this.get('Client-IP');
  },
});
```

## [Extending the API in TypeScript](#extending-the-api-in-typescript)

The sections above override members that Express already provides. To add your own properties or methods to the request or response, describe them to TypeScript with [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) on the `Express` namespace. Put the augmentation in a `.d.ts` file that is part of your project. No `tsconfig.json` change is needed unless a custom `include` does not cover its location.

For example, an authentication middleware may attach a `user` to the request, and you might add a `sendError` helper to the response:

types/express.d.ts

```
interface User {
  id: string;
  name: string;
}


declare global {
  namespace Express {
    interface Request {
      user?: User;
    }
    interface Response {
      sendError(status: number, message: string): this;
    }
  }
}


export {};
```

The additions are now known throughout the application:

```
import { type Request, type Response, type NextFunction } from 'express';


app.use((req: Request, res: Response, next: NextFunction) => {
  req.user = { id: '1', name: 'Tobi' };
  next();
});


app.response.sendError = function (this: Response, status: number, message: string) {
  return this.status(status).json({ error: message });
};


app.get('/', (req: Request, res: Response) => {
  if (!req.user) {
    res.sendError(401, 'unauthorized');
    return;
  }
  res.send(req.user.name);
});
```

### Caution

Declare custom request properties as optional (`user?`). The type applies to every request, but TypeScript cannot know which middleware ran before a given handler, so a required property would be a false guarantee. Check for the value (as with `if (!req.user)` above) before relying on it.

Adding a new method needs no cast, unlike [overriding](#methods) an existing method with a different signature, because the method did not previously exist on the type.

## [Prototype](#prototype)

In order to provide the Express API, the request/response objects passed to Express (via `app(req, res)`, for example) need to inherit from the same prototype chain. By default, this is `http.IncomingRequest.prototype` for the request and `http.ServerResponse.prototype` for the response.

Unless necessary, it is recommended that this be done only at the application level, rather than globally. Also, take care that the prototype that is being used matches the functionality as closely as possible to the default prototypes.

```
// Use FakeRequest and FakeResponse in place of http.IncomingRequest and http.ServerResponse
// for the given app reference
Object.setPrototypeOf(Object.getPrototypeOf(app.request), FakeRequest.prototype);
Object.setPrototypeOf(Object.getPrototypeOf(app.response), FakeResponse.prototype);
```

----
url: https://expressjs.com/en/5x/api/express/
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/5x/api/express/index.mdx)

# [Express Object](#overview)

Creates an Express application. The `express()` function is a top-level function exported by the `express` module.

index.cjs

```
const express = require('express');
const app = express();
```

index.mjs

```
import express from 'express';


const app = express();
```

index.ts

```
import express, { type Express } from 'express';


const app: Express = express();
```

## [Methods](#methods)

The Express object has the following methods that can be used to create middleware functions, routers and have some built-in middleware:

### [express.json()](#expressjson)

#### Arguments

`options`

Type:`Object | undefined`

Configures how the JSON body is parsed; it accepts the properties below.

`defaultCharset`

Type:`String`Default:`"utf-8"`

Specify the default character set for the JSON content if the charset is not specified in the `Content-Type` header of the request.

This is a built-in middleware function in Express. It parses incoming requests with JSON payloads and is based on [body-parser](/en/resources/middleware/body-parser/).

Returns middleware that only parses JSON and only looks at requests where the `Content-Type` header matches the `type` option. This parser accepts any Unicode encoding of the body and supports automatic inflation of `gzip` and `deflate` encodings.

A new `body` object containing the parsed data is populated on the `request` object after the middleware (i.e. `req.body`), or `undefined` if there was no body to parse, the `Content-Type` was not matched, or an error occurred.

### Warning

As `req.body`’s shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, `req.body.foo.toString()` may fail in multiple ways, for example `foo` may not be there or may not be a string, and `toString` may not be a function and instead a string or other user-input.

index.cjs

```
const express = require('express');
const app = express();


// parse requests with a Content-Type of application/json
app.use(express.json());


app.post('/profile', (req, res) => {
  console.dir(req.body);
  res.json(req.body);
});
```

index.mjs

```
import express from 'express';


const app = express();


// parse requests with a Content-Type of application/json
app.use(express.json());


app.post('/profile', (req, res) => {
  console.dir(req.body);
  res.json(req.body);
});
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


// parse requests with a Content-Type of application/json
app.use(express.json());


app.post('/profile', (req: Request, res: Response) => {
  console.dir(req.body);
  res.json(req.body);
});
```

This is a built-in middleware function in Express. It parses incoming request payloads into a `Buffer` and is based on [body-parser](/en/resources/middleware/body-parser/).

Returns middleware that parses all bodies as a `Buffer` and only looks at requests where the `Content-Type` header matches the `type` option. This parser accepts any Unicode encoding of the body and supports automatic inflation of `gzip` and `deflate` encodings.

A new `body` `Buffer` containing the parsed data is populated on the `request` object after the middleware (i.e. `req.body`), or `undefined` if there was no body to parse, the `Content-Type` was not matched, or an error occurred.

### Warning

As `req.body`’s shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, `req.body.toString()` may fail in multiple ways, for example stacking multiple parsers `req.body` may be from a different parser. Testing that `req.body` is a `Buffer` before calling buffer methods is recommended.

index.cjs

```
const express = require('express');
const app = express();


// parse requests with a Content-Type of application/octet-stream into a Buffer
app.use(express.raw());


app.post('/upload', (req, res) => {
  console.dir(Buffer.isBuffer(req.body)); // => true
  res.send(`received ${req.body.length} bytes`);
});
```

index.mjs

```
import express from 'express';


const app = express();


// parse requests with a Content-Type of application/octet-stream into a Buffer
app.use(express.raw());


app.post('/upload', (req, res) => {
  console.dir(Buffer.isBuffer(req.body)); // => true
  res.send(`received ${req.body.length} bytes`);
});
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


// parse requests with a Content-Type of application/octet-stream into a Buffer
app.use(express.raw());


app.post('/upload', (req: Request, res: Response) => {
  console.dir(Buffer.isBuffer(req.body)); // => true
  res.send(`received ${req.body.length} bytes`);
});
```

### [express.Router()](#expressrouter)

#### Arguments

`caseSensitive`

Type:`Boolean`Default:`false`

Enable case sensitivity. Disabled by default, treating `/Foo` and `/foo` as the same.

`mergeParams`

Type:`Boolean`Default:`false`

Preserve the `req.params` values from the parent router. If the parent and the child have conflicting param names, the child’s value take precedence.

`strict`

Type:`Boolean`Default:`false`

Enable strict routing. Disabled by default, `/foo` and `/foo/` are treated the same by the router.

↵Returns:`Router`

Creates a new [router](/en/5x/api/router/) object.

```
const router = express.Router([options]);
```

You can add middleware and HTTP method routes (such as `get`, `put`, `post`, and so on) to `router` just like an application.

For more information, see [Router](/en/5x/api/router/).

Type:`String`Default:`"ignore"`

The `root` argument specifies the root directory from which to serve static assets. The function determines the file to serve by combining `req.url` with the provided `root` directory. When a file is not found, instead of sending a 404 response, it instead calls `next()` to move on to the next middleware, allowing for stacking and fall-backs.

For more information, see [Serving static files in Express](/en/5x/starter/static-files/). and [Using middleware - Built-in middleware](/en/5x/guide/using-middleware/#built-in-middleware).

#### [dotfiles](#dotfiles)

Possible values for this option are:

* “allow” - No special treatment for dotfiles.
* “deny” - Deny a request for a dotfile, respond with `403`, then call `next()`.
* “ignore” - Act as if the dotfile does not exist, respond with `404`, then call `next()`.

```
fn(res, path, stat);
```

Arguments:

* `res`, the [response object](/en/5x/api/response/).
* `path`, the file path that is being sent.
* `stat`, the `stat` object of the file that is being sent.

#### [Example of express.static](#example-of-expressstatic)

Here is an example of using the `express.static` middleware function with an elaborate options object:

index.cjs

```
const express = require('express');
const app = express();


const options = {
  dotfiles: 'ignore',
  etag: false,
  extensions: ['htm', 'html'],
  index: false,
  maxAge: '1d',
  redirect: false,
  setHeaders(res, path, stat) {
    res.set('x-timestamp', Date.now());
  },
};


app.use(express.static('public', options));
```

index.mjs

```
import express from 'express';


const app = express();


const options = {
  dotfiles: 'ignore',
  etag: false,
  extensions: ['htm', 'html'],
  index: false,
  maxAge: '1d',
  redirect: false,
  setHeaders(res, path, stat) {
    res.set('x-timestamp', Date.now());
  },
};


app.use(express.static('public', options));
```

index.ts

```
import express, { type Express } from 'express';


const app: Express = express();


const options = {
  dotfiles: 'ignore',
  etag: false,
  extensions: ['htm', 'html'],
  index: false,
  maxAge: '1d',
  redirect: false,
  setHeaders(res, path, stat) {
    res.set('x-timestamp', Date.now());
  },
};


app.use(express.static('public', options));
```

This is a built-in middleware function in Express. It parses incoming request payloads into a string and is based on [body-parser](/en/resources/middleware/body-parser/).

Returns middleware that parses all bodies as a string and only looks at requests where the `Content-Type` header matches the `type` option. This parser accepts any Unicode encoding of the body and supports automatic inflation of `gzip` and `deflate` encodings.

A new `body` string containing the parsed data is populated on the `request` object after the middleware (i.e. `req.body`), or `undefined` if there was no body to parse, the `Content-Type` was not matched, or an error occurred.

### Warning

As `req.body`’s shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, `req.body.trim()` may fail in multiple ways, for example stacking multiple parsers `req.body` may be from a different parser. Testing that `req.body` is a string before calling string methods is recommended.

index.cjs

```
const express = require('express');
const app = express();


// parse requests with a Content-Type of text/plain into a string
app.use(express.text());


app.post('/', (req, res) => {
  console.dir(typeof req.body); // => 'string'
  res.send(req.body);
});
```

index.mjs

```
import express from 'express';


const app = express();


// parse requests with a Content-Type of text/plain into a string
app.use(express.text());


app.post('/', (req, res) => {
  console.dir(typeof req.body); // => 'string'
  res.send(req.body);
});
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


// parse requests with a Content-Type of text/plain into a string
app.use(express.text());


app.post('/', (req: Request, res: Response) => {
  console.dir(typeof req.body); // => 'string'
  res.send(req.body);
});
```

### [express.urlencoded()](#expressurlencoded)

#### Arguments

`options`

Type:`Object | undefined`

Configures how the URL-encoded body is parsed; it accepts the properties below.

`extended`

Type:`Boolean`Default:`false`

`defaultCharset`

Type:`String`Default:`"utf-8"`

The default charset to parse as, if not specified in content-type. Must be either `utf-8` or `iso-8859-1`.

`charsetSentinel`

Type:`Boolean`Default:`false`

Whether to let the value of the `utf8` parameter take precedence as the charset selector. It requires the form to contain a parameter named `utf8` with a value of `✓`.

`interpretNumericEntities`

Type:`Boolean`Default:`false`

Whether to decode numeric entities such as `&#9786;` when parsing an iso-8859-1 form.

`depth`

Type:`Number`Default:`32`

Configure the maximum depth of the `qs` library when `extended` is `true`. This allows you to limit the amount of keys that are parsed and can be useful to prevent certain types of abuse. It is recommended to keep this value as low as possible.

↵Returns:`Function`

This is a built-in middleware function in Express. It parses incoming requests with urlencoded payloads and is based on [body-parser](/en/resources/middleware/body-parser/).

Returns middleware that only parses urlencoded bodies and only looks at requests where the `Content-Type` header matches the `type` option. This parser accepts only UTF-8 encoding of the body and supports automatic inflation of `gzip` and `deflate` encodings.

A new `body` object containing the parsed data is populated on the `request` object after the middleware (i.e. `req.body`), or `undefined` if there was no body to parse, the `Content-Type` was not matched, or an error occurred. This object will contain key-value pairs, where the value can be a string or array (when `extended` is `false`), or any type (when `extended` is `true`).

### Warning

As `req.body`’s shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, `req.body.foo.toString()` may fail in multiple ways, for example `foo` may not be there or may not be a string, and `toString` may not be a function and instead a string or other user-input.

index.cjs

```
const express = require('express');
const app = express();


// parse requests with a Content-Type of application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));


app.post('/profile', (req, res) => {
  console.dir(req.body);
  res.json(req.body);
});
```

index.mjs

```
import express from 'express';


const app = express();


// parse requests with a Content-Type of application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));


app.post('/profile', (req, res) => {
  console.dir(req.body);
  res.json(req.body);
});
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


// parse requests with a Content-Type of application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));


app.post('/profile', (req: Request, res: Response) => {
  console.dir(req.body);
  res.json(req.body);
});
```

----
url: https://expressjs.com/en/resources/middleware/timeout
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/timeout.mdx)

# [timeout middleware](#overview)

v1.9.1[GitHub](https://github.com/expressjs/timeout)[Changelog](https://github.com/expressjs/timeout/releases)[npm](https://www.npmjs.com/package/connect-timeout)

Times out a request in the Connect/Express application framework.

## [Install](#install)

This is a [Node.js](https://nodejs.org/en/) module available through the [npm registry](https://www.npmjs.com/). Installation is done using the [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):

Terminal window

```
npm install connect-timeout
```

Terminal window

```
yarn add connect-timeout
```

Terminal window

```
pnpm add connect-timeout
```

Terminal window

```
bun add connect-timeout
```

### Note

`connect-timeout` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/connect-timeout
```

Terminal window

```
yarn add --dev @types/connect-timeout
```

Terminal window

```
pnpm add --save-dev @types/connect-timeout
```

Terminal window

```
bun add --dev @types/connect-timeout
```

## [API](#api)

**NOTE** This module is not recommend as a “top-level” middleware (i.e. `app.use(timeout('5s'))`) unless you take precautions to halt your own middleware processing. See [as top-level middleware](#as-top-level-middleware) for how to use as a top-level middleware.

While the library will emit a ‘timeout’ event when requests exceed the given timeout, node will continue processing the slow request until it terminates. Slow requests will continue to use CPU and memory, even if you are returning a HTTP response in the timeout callback. For better control over CPU/memory, you may need to find the events that are taking a long time (3rd party HTTP requests, disk I/O, database calls) and find a way to cancel them, and/or close the attached sockets.

### [timeout(time, \[options\])](#timeouttime-options)

Returns middleware that times out in `time` milliseconds. `time` can also be a string accepted by the [ms](https://www.npmjs.org/package/ms#readme) module. On timeout, `req` will emit `"timeout"`.

#### [Options](#options)

The `timeout` function takes an optional `options` object that may contain any of the following keys:

##### [respond](#respond)

Controls if this module will “respond” in the form of forwarding an error. If `true`, the timeout error is passed to `next()` so that you may customize the response behavior. This error has a `.timeout` property as well as `.status == 503`. This defaults to `true`.

### [req.clearTimeout()](#reqcleartimeout)

Clears the timeout on the request. The timeout is completely removed and will not fire for this request in the future.

### [req.timedout](#reqtimedout)

`true` if timeout fired; `false` otherwise.

## [Examples](#examples)

### [as top-level middleware](#as-top-level-middleware)

Because of the way middleware processing works, once this module passes the request to the next middleware (which it has to do in order for you to do work), it can no longer stop the flow, so you must take care to check if the request has timedout before you continue to act on the request.

```
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var express = require('express');
var timeout = require('connect-timeout');


// example of using this top-level; note the use of haltOnTimedout
// after every middleware; it will stop the request flow on a timeout
var app = express();
app.use(timeout('5s'));
app.use(bodyParser());
app.use(haltOnTimedout);
app.use(cookieParser());
app.use(haltOnTimedout);


// Add your routes here, etc.


function haltOnTimedout(req, res, next) {
  if (!req.timedout) next();
}


app.listen(3000);
```

### [express 3.x](#express-3x)

```
var express = require('express');
var bodyParser = require('body-parser');
var timeout = require('connect-timeout');


var app = express();
app.post('/save', timeout('5s'), bodyParser.json(), haltOnTimedout, function (req, res, next) {
  savePost(req.body, function (err, id) {
    if (err) return next(err);
    if (req.timedout) return;
    res.send('saved as id ' + id);
  });
});


function haltOnTimedout(req, res, next) {
  if (!req.timedout) next();
}


function savePost(post, cb) {
  setTimeout(
    function () {
      cb(null, (Math.random() * 40000) >>> 0);
    },
    (Math.random() * 7000) >>> 0
  );
}


app.listen(3000);
```

### [connect](#connect)

```
var bodyParser = require('body-parser');
var connect = require('connect');
var timeout = require('connect-timeout');


var app = connect();
app.use('/save', timeout('5s'), bodyParser.json(), haltOnTimedout, function (req, res, next) {
  savePost(req.body, function (err, id) {
    if (err) return next(err);
    if (req.timedout) return;
    res.send('saved as id ' + id);
  });
});


function haltOnTimedout(req, res, next) {
  if (!req.timedout) next();
}


function savePost(post, cb) {
  setTimeout(
    function () {
      cb(null, (Math.random() * 40000) >>> 0);
    },
    (Math.random() * 7000) >>> 0
  );
}


app.listen(3000);
```

## [License](#license)

[MIT](https://github.com/expressjs/timeout/blob/HEAD/LICENSE)

----
url: https://expressjs.com/en/
----

### September 2026 Security Releases

Security releases for compression, cookies, hbs, morgan, multer, multiparty, and proxy-addr have been published. We recommend that all users upgrade as soon as possible. [Check out our latest blog](/en/blog/2026-09-30-security-releases)

5.3.0

# Fast, unopinionated, minimalist web framework for Node.js

```
npm install express
```

[Get Started](/en/5x/starter/installing)

```
const express = require('express');
const app = express()
const port = 3000


app.get('/', (req, res) => {
  res.send('Hello World!')
})


app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})
```

## Clarity over complexity. For every developer.

### Web Applications

Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.

### APIs

With a myriad of HTTP utility methods and middleware at your disposal, creating a robust API is quick and easy.

### Performance

Express provides a thin layer of fundamental web application features, without obscuring Node.js features that you know and love.

### Middleware

Express is a lightweight and flexible routing framework with minimal core features meant to be augmented through the use of Express middleware modules.

----
url: https://expressjs.com/en/resources/middleware/serve-static
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/serve-static.mdx)

# [serve-static middleware](#overview)

v2.2.1[GitHub](https://github.com/expressjs/serve-static)[Changelog](https://github.com/expressjs/serve-static/releases)[npm](https://www.npmjs.com/package/serve-static)

## [Install](#install)

This is a [Node.js](https://nodejs.org/en/) module available through the [npm registry](https://www.npmjs.com/). Installation is done using the [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):

Terminal window

```
npm install serve-static
```

Terminal window

```
yarn add serve-static
```

Terminal window

```
pnpm add serve-static
```

Terminal window

```
bun add serve-static
```

### Note

`serve-static` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/serve-static
```

Terminal window

```
yarn add --dev @types/serve-static
```

Terminal window

```
pnpm add --save-dev @types/serve-static
```

Terminal window

```
bun add --dev @types/serve-static
```

## [API](#api)

```
const serveStatic = require('serve-static');
```

### [serveStatic(root, options)](#servestaticroot-options)

Create a new middleware function to serve files from within a given root directory. The file to serve will be determined by combining `req.url` with the provided root directory. When a file is not found, instead of sending a 404 response, this module will instead call `next()` to move on to the next middleware, allowing for stacking and fall-backs.

#### [Options](#options)

##### [acceptRanges](#acceptranges)

Enable or disable accepting ranged requests, defaults to true. Disabling this will not send `Accept-Ranges` and ignore the contents of the `Range` request header.

##### [cacheControl](#cachecontrol)

Enable or disable setting `Cache-Control` response header, defaults to true. Disabling this will ignore the `immutable` and `maxAge` options.

##### [dotfiles](#dotfiles)

Set how “dotfiles” are treated when encountered. A dotfile is a file or directory that begins with a dot (”.”). Note this check is done on the path itself without checking if the path actually exists on the disk. If `root` is specified, only the dotfiles above the root are checked (i.e. the root itself can be within a dotfile when set to “deny”).

* `'allow'` No special treatment for dotfiles.
* `'deny'` Deny a request for a dotfile and 403/`next()`.
* `'ignore'` Pretend like the dotfile does not exist and 404/`next()`.

The default value is `'ignore'`.

##### [etag](#etag)

Enable or disable etag generation, defaults to true.

##### [extensions](#extensions)

Set file extension fallbacks. When set, if a file is not found, the given extensions will be added to the file name and search for. The first that exists will be served. Example: `['html', 'htm']`.

The default value is `false`.

##### [fallthrough](#fallthrough)

Set the middleware to have client errors fall-through as just unhandled requests, otherwise forward a client error. The difference is that client errors like a bad request or a request to a non-existent file will cause this middleware to simply `next()` to your next middleware when this value is `true`. When this value is `false`, these errors (even 404s), will invoke `next(err)`.

Typically `true` is desired such that multiple physical directories can be mapped to the same web address or for routes to fill in non-existent files.

The value `false` can be used if this middleware is mounted at a path that is designed to be strictly a single file system directory, which allows for short-circuiting 404s for less overhead. This middleware will also reply to all methods.

The default value is `true`.

##### [immutable](#immutable)

Enable or disable the `immutable` directive in the `Cache-Control` response header, defaults to `false`. If set to `true`, the `maxAge` option should also be specified to enable caching. The `immutable` directive will prevent supported clients from making conditional requests during the life of the `maxAge` option to check if the file has changed.

##### [index](#index)

By default this module will send “index.html” files in response to a request on a directory. To disable this set `false` or to supply a new index pass a string or an array in preferred order.

##### [lastModified](#lastmodified)

Enable or disable `Last-Modified` header, defaults to true. Uses the file system’s last modified value.

##### [maxAge](#maxage)

Provide a max-age in milliseconds for http caching, defaults to 0. This can also be a string accepted by the [ms](https://www.npmjs.org/package/ms#readme) module.

##### [redirect](#redirect)

Redirect to trailing ”/” when the pathname is a dir. Defaults to `true`.

##### [setHeaders](#setheaders)

Function to set custom headers on response. Alterations to the headers need to occur synchronously. The function is called as `fn(res, path, stat)`, where the arguments are:

* `res` the response object
* `path` the file path that is being sent
* `stat` the stat object of the file that is being sent

## [Examples](#examples)

### [Serve files with vanilla node.js http server](#serve-files-with-vanilla-nodejs-http-server)

```
const finalhandler = require('finalhandler');
const http = require('http');
const serveStatic = require('serve-static');


// Serve up public/ftp folder
const serve = serveStatic('public/ftp', { index: ['index.html', 'index.htm'] });


// Create server
const server = http.createServer((req, res) => {
  serve(req, res, finalhandler(req, res));
});


// Listen
server.listen(3000);
```

### [Serve all files as downloads](#serve-all-files-as-downloads)

```
const contentDisposition = require('content-disposition');
const finalhandler = require('finalhandler');
const http = require('http');
const serveStatic = require('serve-static');


// Serve up public/ftp folder
const serve = serveStatic('public/ftp', {
  index: false,
  setHeaders: setHeaders,
});


// Set header to force download
function setHeaders(res, path) {
  res.setHeader('Content-Disposition', contentDisposition(path));
}


// Create server
const server = http.createServer((req, res) => {
  serve(req, res, finalhandler(req, res));
});


// Listen
server.listen(3000);
```

### [Serving using express](#serving-using-express)

#### [Simple](#simple)

This is a simple example of using Express.

```
const express = require('express');
const serveStatic = require('serve-static');


const app = express();


app.use(serveStatic('public/ftp', { index: ['default.html', 'default.htm'] }));
app.listen(3000);
```

#### [Multiple roots](#multiple-roots)

This example shows a simple way to search through multiple directories. Files are searched for in `public-optimized/` first, then `public/` second as a fallback.

```
const express = require('express');
const path = require('path');
const serveStatic = require('serve-static');


const app = express();


app.use(serveStatic(path.join(__dirname, 'public-optimized')));
app.use(serveStatic(path.join(__dirname, 'public')));
app.listen(3000);
```

#### [Different settings for paths](#different-settings-for-paths)

This example shows how to set a different max age depending on the served file. In this example, HTML files are not cached, while everything else is for 1 day.

```
const express = require('express');
const path = require('path');
const serveStatic = require('serve-static');


const app = express();


app.use(
  serveStatic(path.join(__dirname, 'public'), {
    maxAge: '1d',
    setHeaders: setCustomCacheControl,
  })
);


app.listen(3000);


function setCustomCacheControl(res, file) {
  if (path.extname(file) === '.html') {
    // Custom Cache-Control for HTML files
    res.setHeader('Cache-Control', 'public, max-age=0');
  }
}
```

## [License](#license)

[MIT](https://github.com/expressjs/serve-static/blob/HEAD/LICENSE)

----
url: https://expressjs.com/en/blog/4
----

# Blog

Stay tuned for details on new releases, enhancements, and everything you need to know to make the most of your Express applications. Let's dive into what's new!

[Announcements](/en/blog/2024-10-15-v5-release)

## [Introducing Express v5: A New Era for the Node.js Framework](/en/blog/2024-10-15-v5-release)

[Wes Todd, Express Technical CommitteeOct 15, 2024](/en/blog/2024-10-15-v5-release)

[Announcements](/en/blog/2024-10-01-herodevs-partnership-announcement)

## [Express Never Ending Support Launched by HeroDevs and Express.js](/en/blog/2024-10-01-herodevs-partnership-announcement)

[Express Technical CommitteeOct 1, 2024](/en/blog/2024-10-01-herodevs-partnership-announcement)

[Security](/en/blog/2024-09-29-security-releases)

## [September 2024 Security Releases](/en/blog/2024-09-29-security-releases)

[Ulises GascónSep 29, 2024](/en/blog/2024-09-29-security-releases)

[Announcements](/en/blog/2024-07-16-welcome-post)

## [Welcome to The Express Blog!](/en/blog/2024-07-16-welcome-post)

[Rand McKinney, Chris DelJul 16, 2024](/en/blog/2024-07-16-welcome-post)

----
url: https://expressjs.com/en/resources/middleware/cookie-parser
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/cookie-parser.mdx)

# [cookie-parser middleware](#overview)

v1.4.7[GitHub](https://github.com/expressjs/cookie-parser)[Changelog](https://github.com/expressjs/cookie-parser/releases)[npm](https://www.npmjs.com/package/cookie-parser)

Parse `Cookie` header and populate `req.cookies` with an object keyed by the cookie names. Optionally you may enable signed cookie support by passing a `secret` string, which assigns `req.secret` so it may be used by other middleware.

## [Installation](#installation)

Terminal window

```
npm install cookie-parser
```

Terminal window

```
yarn add cookie-parser
```

Terminal window

```
pnpm add cookie-parser
```

Terminal window

```
bun add cookie-parser
```

### Note

`cookie-parser` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/cookie-parser
```

Terminal window

```
yarn add --dev @types/cookie-parser
```

Terminal window

```
pnpm add --save-dev @types/cookie-parser
```

Terminal window

```
bun add --dev @types/cookie-parser
```

## [API](#api)

```
var cookieParser = require('cookie-parser');
```

### [cookieParser(secret, options)](#cookieparsersecret-options)

Create a new cookie parser middleware function using the given `secret` and `options`.

* `secret` a string or array used for signing cookies. This is optional and if not specified, will not parse signed cookies. If a string is provided, this is used as the secret. If an array is provided, an attempt will be made to unsign the cookie with each secret in order.
* `options` an object that is passed to `cookie.parse` as the second option. See [cookie](https://www.npmjs.org/package/cookie) for more information.
  * `decode` a function to decode the value of the cookie

The middleware will parse the `Cookie` header on the request and expose the cookie data as the property `req.cookies` and, if a `secret` was provided, as the property `req.signedCookies`. These properties are name value pairs of the cookie name to cookie value.

When `secret` is provided, this module will unsign and validate any signed cookie values and move those name value pairs from `req.cookies` into `req.signedCookies`. A signed cookie is a cookie that has a value prefixed with `s:`. Signed cookies that fail signature validation will have the value `false` instead of the tampered value.

In addition, this module supports special “JSON cookies”. These are cookie where the value is prefixed with `j:`. When these values are encountered, the value will be exposed as the result of `JSON.parse`. If parsing fails, the original value will remain.

### [cookieParser.JSONCookie(str)](#cookieparserjsoncookiestr)

Parse a cookie value as a JSON cookie. This will return the parsed JSON value if it was a JSON cookie, otherwise, it will return the passed value.

### [cookieParser.JSONCookies(cookies)](#cookieparserjsoncookiescookies)

Given an object, this will iterate over the keys and call `JSONCookie` on each value, replacing the original value with the parsed value. This returns the same object that was passed in.

### [cookieParser.signedCookie(str, secret)](#cookieparsersignedcookiestr-secret)

Parse a cookie value as a signed cookie. This will return the parsed unsigned value if it was a signed cookie and the signature was valid. If the value was not signed, the original value is returned. If the value was signed but the signature could not be validated, `false` is returned.

The `secret` argument can be an array or string. If a string is provided, this is used as the secret. If an array is provided, an attempt will be made to unsign the cookie with each secret in order.

### [cookieParser.signedCookies(cookies, secret)](#cookieparsersignedcookiescookies-secret)

Given an object, this will iterate over the keys and check if any value is a signed cookie. If it is a signed cookie and the signature is valid, the key will be deleted from the object and added to the new object that is returned.

The `secret` argument can be an array or string. If a string is provided, this is used as the secret. If an array is provided, an attempt will be made to unsign the cookie with each secret in order.

## [Example](#example)

```
var express = require('express');
var cookieParser = require('cookie-parser');


var app = express();
app.use(cookieParser());


app.get('/', function (req, res) {
  // Cookies that have not been signed
  console.log('Cookies: ', req.cookies);


  // Cookies that have been signed
  console.log('Signed Cookies: ', req.signedCookies);
});


app.listen(8080);


// curl command that sends an HTTP request with two cookies
// curl http://127.0.0.1:8080 --cookie "Cho=Kim;Greet=Hello"
```

## [License](#license)

[MIT](https://github.com/expressjs/cookie-parser/blob/HEAD/LICENSE)

----
url: https://expressjs.com/en/support
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/support.mdx)

# [Version Support](#overview)

Only the latest version of any given major release line is supported.

Versions that are EOL (end-of-life) *may* receive updates for critical security vulnerabilities, but the Express team offers no guarantee and does not plan to address or release fixes for any issues found.

| Major Version                                                  | Minimum Node.js Version | Support Start Date | Support End Date |
| -------------------------------------------------------------- | ----------------------- | ------------------ | ---------------- |
| [**v5.x**](/en/5x/api/)                                        | 18                      | September 2024     | **ongoing**      |
| [**v4.x**](/en/4x/api/)                                        | 0.10.0                  | April 2014         | **ongoing**      |
| [**v3.x**](/en/3x/api/)                                        | 0.8.0                   | October 2012       | July 2015        |
| [**v2.x**](https://github.com/expressjs/expressjs.com/tree/2x) | 0.4.1                   | March 2011         | July 2012        |
| **v1.x**                                                       | 0.2.0                   | December 2010      | March 2011       |
| **v0.14.x**                                                    | 0.1.98                  | December 2010      | December 2010    |

## [Commercial Support Options](#commercial-support-options)

If you are unable to update to a supported version of Express, please contact one of our partners to receive security updates:

* [HeroDevs Never-Ending Support](https://www.herodevs.com/support/express-nes?utm_source=expressjs\&utm_medium=link\&utm_campaign=express_eol_page)

----
url: https://expressjs.com/en/guide/database-integration
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/guide/database-integration.mdx)

# [Database integration](#overview)

Adding the capability to connect databases to Express apps is just a matter of loading an appropriate Node.js driver for the database in your app. This document briefly explains how to add and use some of the most popular Node.js modules for database systems in your Express app:

* [Cassandra](#cassandra)
* [Couchbase](#couchbase)
* [CouchDB](#couchdb)
* [LevelDB](#leveldb)
* [MySQL](#mysql)
* [MongoDB](#mongodb)
* [Neo4j](#neo4j)
* [Oracle](#oracle)
* [PostgreSQL](#postgresql)
* [Redis](#redis)
* [SQL Server](#sql-server)
* [SQLite](#sqlite)
* [Elasticsearch](#elasticsearch)

### Caution

These database drivers are among many that are available. For other options, search on the [npm](https://www.npmjs.com/) site.

## [Cassandra](#cassandra)

**Module**: [cassandra-driver](https://github.com/datastax/nodejs-driver)

### [Installation](#installation)

Terminal window

```
npm install cassandra-driver
```

Terminal window

```
yarn add cassandra-driver
```

Terminal window

```
pnpm add cassandra-driver
```

Terminal window

```
bun add cassandra-driver
```

### [Example](#example)

index.cjs

```
const cassandra = require('cassandra-driver');
const client = new cassandra.Client({ contactPoints: ['localhost'] });


client.execute('select key from system.local', (err, result) => {
  if (err) throw err;
  console.log(result.rows[0]);
});
```

index.mjs

```
import cassandra from 'cassandra-driver';


const client = new cassandra.Client({ contactPoints: ['localhost'] });


client.execute('select key from system.local', (err, result) => {
  if (err) throw err;
  console.log(result.rows[0]);
});
```

## [Couchbase](#couchbase)

**Module**: [couchnode](https://github.com/couchbase/couchnode)

### [Installation](#installation-1)

Terminal window

```
npm install couchbase
```

Terminal window

```
yarn add couchbase
```

Terminal window

```
pnpm add couchbase
```

Terminal window

```
bun add couchbase
```

### [Example](#example-1)

index.cjs

```
const couchbase = require('couchbase');
const bucket = new couchbase.Cluster('http://localhost:8091').openBucket('bucketName');


// add a document to a bucket
bucket.insert('document-key', { name: 'Matt', shoeSize: 13 }, (err, result) => {
  if (err) {
    console.log(err);
  } else {
    console.log(result);
  }
});


// get all documents with shoe size 13
const n1ql = 'SELECT d.* FROM `bucketName` d WHERE shoeSize = $1';
const query = N1qlQuery.fromString(n1ql);
bucket.query(query, [13], (err, result) => {
  if (err) {
    console.log(err);
  } else {
    console.log(result);
  }
});
```

index.mjs

```
import couchbase from 'couchbase';


const bucket = new couchbase.Cluster('http://localhost:8091').openBucket('bucketName');


// add a document to a bucket
bucket.insert('document-key', { name: 'Matt', shoeSize: 13 }, (err, result) => {
  if (err) {
    console.log(err);
  } else {
    console.log(result);
  }
});


// get all documents with shoe size 13
const n1ql = 'SELECT d.* FROM `bucketName` d WHERE shoeSize = $1';
const query = N1qlQuery.fromString(n1ql);
bucket.query(query, [13], (err, result) => {
  if (err) {
    console.log(err);
  } else {
    console.log(result);
  }
});
```

## [CouchDB](#couchdb)

**Module**: [nano](https://github.com/dscape/nano)

### [Installation](#installation-2)

Terminal window

```
npm install nano
```

Terminal window

```
yarn add nano
```

Terminal window

```
pnpm add nano
```

Terminal window

```
bun add nano
```

### [Example](#example-2)

index.js

```
const nano = require('nano')('http://localhost:5984');
nano.db.create('books');
const books = nano.db.use('books');


// Insert a book document in the books database
books.insert({ name: 'The Art of war' }, null, (err, body) => {
  if (err) {
    console.log(err);
  } else {
    console.log(body);
  }
});


// Get a list of all books
books.list((err, body) => {
  if (err) {
    console.log(err);
  } else {
    console.log(body.rows);
  }
});
```

## [LevelDB](#leveldb)

**Module**: [levelup](https://github.com/rvagg/node-levelup)

### [Installation](#installation-3)

Terminal window

```
npm install level levelup leveldown
```

Terminal window

```
yarn add level levelup leveldown
```

Terminal window

```
pnpm add level levelup leveldown
```

Terminal window

```
bun add level levelup leveldown
```

### [Example](#example-3)

index.cjs

```
const levelup = require('levelup');
const db = levelup('./mydb');


db.put('name', 'LevelUP', (err) => {
  if (err) return console.log('Ooops!', err);


  db.get('name', (err, value) => {
    if (err) return console.log('Ooops!', err);


    console.log(`name=${value}`);
  });
});
```

index.mjs

```
import levelup from 'levelup';


const db = levelup('./mydb');


db.put('name', 'LevelUP', (err) => {
  if (err) return console.log('Ooops!', err);


  db.get('name', (err, value) => {
    if (err) return console.log('Ooops!', err);


    console.log(`name=${value}`);
  });
});
```

## [MySQL](#mysql)

**Module**: [mysql](https://github.com/felixge/node-mysql/)

### [Installation](#installation-4)

Terminal window

```
npm install mysql
```

Terminal window

```
yarn add mysql
```

Terminal window

```
pnpm add mysql
```

Terminal window

```
bun add mysql
```

### [Example](#example-4)

index.cjs

```
const mysql = require('mysql');
const connection = mysql.createConnection({
  host: 'localhost',
  user: 'dbuser',
  password: 's3kreee7',
  database: 'my_db',
});


connection.connect();


connection.query('SELECT 1 + 1 AS solution', (err, rows, fields) => {
  if (err) throw err;


  console.log('The solution is: ', rows[0].solution);
});


connection.end();
```

index.mjs

```
import mysql from 'mysql';


const connection = mysql.createConnection({
  host: 'localhost',
  user: 'dbuser',
  password: 's3kreee7',
  database: 'my_db',
});


connection.connect();


connection.query('SELECT 1 + 1 AS solution', (err, rows, fields) => {
  if (err) throw err;


  console.log('The solution is: ', rows[0].solution);
});


connection.end();
```

## [MongoDB](#mongodb)

**Module**: [mongodb](https://github.com/mongodb/node-mongodb-native)

### [Installation](#installation-5)

Terminal window

```
npm install mongodb
```

Terminal window

```
yarn add mongodb
```

Terminal window

```
pnpm add mongodb
```

Terminal window

```
bun add mongodb
```

### [Example (v2.\*)](#example-v2)

index.js

```
const MongoClient = require('mongodb').MongoClient;


MongoClient.connect('mongodb://localhost:27017/animals', (err, db) => {
  if (err) throw err;


  db.collection('mammals')
    .find()
    .toArray((err, result) => {
      if (err) throw err;


      console.log(result);
    });
});
```

### [Example (v3.\*)](#example-v3)

index.js

```
const MongoClient = require('mongodb').MongoClient;


MongoClient.connect('mongodb://localhost:27017/animals', (err, client) => {
  if (err) throw err;


  const db = client.db('animals');


  db.collection('mammals')
    .find()
    .toArray((err, result) => {
      if (err) throw err;


      console.log(result);
    });
});
```

If you want an object model driver for MongoDB, look at [Mongoose](https://github.com/LearnBoost/mongoose).

## [Neo4j](#neo4j)

**Module**: [neo4j-driver](https://github.com/neo4j/neo4j-javascript-driver)

### [Installation](#installation-6)

Terminal window

```
npm install neo4j-driver
```

Terminal window

```
yarn add neo4j-driver
```

Terminal window

```
pnpm add neo4j-driver
```

Terminal window

```
bun add neo4j-driver
```

### [Example](#example-5)

index.cjs

```
const neo4j = require('neo4j-driver');
const driver = neo4j.driver('neo4j://localhost:7687', neo4j.auth.basic('neo4j', 'letmein'));


const session = driver.session();


session.readTransaction((tx) => {
  return tx
    .run('MATCH (n) RETURN count(n) AS count')
    .then((res) => {
      console.log(res.records[0].get('count'));
    })
    .catch((error) => {
      console.log(error);
    });
});
```

index.mjs

```
import neo4j from 'neo4j-driver';


const driver = neo4j.driver('neo4j://localhost:7687', neo4j.auth.basic('neo4j', 'letmein'));


const session = driver.session();


session.readTransaction((tx) => {
  return tx
    .run('MATCH (n) RETURN count(n) AS count')
    .then((res) => {
      console.log(res.records[0].get('count'));
    })
    .catch((error) => {
      console.log(error);
    });
});
```

## [Oracle](#oracle)

**Module**: [oracledb](https://github.com/oracle/node-oracledb)

### [Installation](#installation-7)

NOTE: [See installation prerequisites](https://github.com/oracle/node-oracledb#-installation).

Terminal window

```
npm install oracledb
```

Terminal window

```
yarn add oracledb
```

Terminal window

```
pnpm add oracledb
```

Terminal window

```
bun add oracledb
```

### [Example](#example-6)

index.cjs

```
const oracledb = require('oracledb');
const config = {
  user: '<your db user>',
  password: '<your db password>',
  connectString: 'localhost:1521/orcl',
};


async function getEmployee(empId) {
  let conn;


  try {
    conn = await oracledb.getConnection(config);


    const result = await conn.execute('select * from employees where employee_id = :id', [empId]);


    console.log(result.rows[0]);
  } catch (err) {
    console.log('Ouch!', err);
  } finally {
    if (conn) {
      // conn assignment worked, need to close
      await conn.close();
    }
  }
}


getEmployee(101);
```

index.mjs

```
import oracledb from 'oracledb';


const config = {
  user: '<your db user>',
  password: '<your db password>',
  connectString: 'localhost:1521/orcl',
};


async function getEmployee(empId) {
  let conn;


  try {
    conn = await oracledb.getConnection(config);


    const result = await conn.execute('select * from employees where employee_id = :id', [empId]);


    console.log(result.rows[0]);
  } catch (err) {
    console.log('Ouch!', err);
  } finally {
    if (conn) {
      // conn assignment worked, need to close
      await conn.close();
    }
  }
}


getEmployee(101);
```

## [PostgreSQL](#postgresql)

**Module**: [pg-promise](https://github.com/vitaly-t/pg-promise)

### [Installation](#installation-8)

Terminal window

```
npm install pg-promise
```

Terminal window

```
yarn add pg-promise
```

Terminal window

```
pnpm add pg-promise
```

Terminal window

```
bun add pg-promise
```

### [Example](#example-7)

index.js

```
const pgp = require('pg-promise')(/* options */);
const db = pgp('postgres://username:password@host:port/database');


db.one('SELECT $1 AS value', 123)
  .then((data) => {
    console.log('DATA:', data.value);
  })
  .catch((error) => {
    console.log('ERROR:', error);
  });
```

## [Redis](#redis)

**Module**: [redis](https://github.com/mranney/node_redis)

### [Installation](#installation-9)

Terminal window

```
npm install redis
```

Terminal window

```
yarn add redis
```

Terminal window

```
pnpm add redis
```

Terminal window

```
bun add redis
```

### [Example](#example-8)

index.cjs

```
const redis = require('redis');
const client = redis.createClient();


client.on('error', (err) => {
  console.log(`Error ${err}`);
});


client.set('string key', 'string val', redis.print);
client.hset('hash key', 'hashtest 1', 'some value', redis.print);
client.hset(['hash key', 'hashtest 2', 'some other value'], redis.print);


client.hkeys('hash key', (err, replies) => {
  console.log(`${replies.length} replies:`);


  replies.forEach((reply, i) => {
    console.log(`    ${i}: ${reply}`);
  });


  client.quit();
});
```

index.mjs

```
import redis from 'redis';


const client = redis.createClient();


client.on('error', (err) => {
  console.log(`Error ${err}`);
});


client.set('string key', 'string val', redis.print);
client.hset('hash key', 'hashtest 1', 'some value', redis.print);
client.hset(['hash key', 'hashtest 2', 'some other value'], redis.print);


client.hkeys('hash key', (err, replies) => {
  console.log(`${replies.length} replies:`);


  replies.forEach((reply, i) => {
    console.log(`    ${i}: ${reply}`);
  });


  client.quit();
});
```

## [SQL Server](#sql-server)

**Module**: [tedious](https://github.com/tediousjs/tedious)

### [Installation](#installation-10)

Terminal window

```
npm install tedious
```

Terminal window

```
yarn add tedious
```

Terminal window

```
pnpm add tedious
```

Terminal window

```
bun add tedious
```

### [Example](#example-9)

index.js

```
const Connection = require('tedious').Connection;
const Request = require('tedious').Request;


const config = {
  server: 'localhost',
  authentication: {
    type: 'default',
    options: {
      userName: 'your_username', // update me
      password: 'your_password', // update me
    },
  },
};


const connection = new Connection(config);


connection.on('connect', (err) => {
  if (err) {
    console.log(err);
  } else {
    executeStatement();
  }
});


function executeStatement() {
  request = new Request("select 123, 'hello world'", (err, rowCount) => {
    if (err) {
      console.log(err);
    } else {
      console.log(`${rowCount} rows`);
    }
    connection.close();
  });


  request.on('row', (columns) => {
    columns.forEach((column) => {
      if (column.value === null) {
        console.log('NULL');
      } else {
        console.log(column.value);
      }
    });
  });


  connection.execSql(request);
}
```

## [SQLite](#sqlite)

**Module**: [sqlite3](https://github.com/mapbox/node-sqlite3)

### [Installation](#installation-11)

Terminal window

```
npm install sqlite3
```

Terminal window

```
yarn add sqlite3
```

Terminal window

```
pnpm add sqlite3
```

Terminal window

```
bun add sqlite3
```

### [Example](#example-10)

index.js

```
const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database(':memory:');


db.serialize(() => {
  db.run('CREATE TABLE lorem (info TEXT)');
  const stmt = db.prepare('INSERT INTO lorem VALUES (?)');


  for (let i = 0; i < 10; i++) {
    stmt.run(`Ipsum ${i}`);
  }


  stmt.finalize();


  db.each('SELECT rowid AS id, info FROM lorem', (err, row) => {
    console.log(`${row.id}: ${row.info}`);
  });
});


db.close();
```

## [Elasticsearch](#elasticsearch)

**Module**: [elasticsearch](https://github.com/elastic/elasticsearch-js)

### [Installation](#installation-12)

Terminal window

```
npm install elasticsearch
```

Terminal window

```
yarn add elasticsearch
```

Terminal window

```
pnpm add elasticsearch
```

Terminal window

```
bun add elasticsearch
```

### [Example](#example-11)

index.cjs

```
const elasticsearch = require('elasticsearch');
const client = elasticsearch.Client({
  host: 'localhost:9200',
});


client
  .search({
    index: 'books',
    type: 'book',
    body: {
      query: {
        multi_match: {
          query: 'express js',
          fields: ['title', 'description'],
        },
      },
    },
  })
  .then(
    (response) => {
      const hits = response.hits.hits;
    },
    (error) => {
      console.trace(error.message);
    }
  );
```

index.mjs

```
import elasticsearch from 'elasticsearch';


const client = elasticsearch.Client({
  host: 'localhost:9200',
});


client
  .search({
    index: 'books',
    type: 'book',
    body: {
      query: {
        multi_match: {
          query: 'express js',
          fields: ['title', 'description'],
        },
      },
    },
  })
  .then(
    (response) => {
      const hits = response.hits.hits;
    },
    (error) => {
      console.trace(error.message);
    }
  );
```

----
url: https://expressjs.com/en/5x/guide/using-middleware
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/guide/using-middleware.mdx)

# [Using middleware](#overview)

Express is a routing and middleware web framework with minimal functionality of its own: an Express application is essentially a series of middleware function calls executed during the request-response cycle.

*Middleware* functions are functions that have access to:

* The [request object](/en/5x/api/request/) (`req`)
* The [response object](/en/5x/api/response/) (`res`)

Bind application-level middleware to an instance of the [app object](/en/5x/api/application/) by using the `app.use()` and `app.METHOD()` functions, where `METHOD` is the lowercase HTTP method of the request that the middleware function handles, such as `get`, `post`, `put`, or `delete`.

### [Middleware without a mount path](#middleware-without-a-mount-path)

The following middleware function runs every time the app receives a request:

index.cjs

```
const express = require('express');
const app = express();


app.use((req, res, next) => {
  console.log('Time:', Date.now());
  next();
});
```

index.mjs

```
import express from 'express';


const app = express();


app.use((req, res, next) => {
  console.log('Time:', Date.now());
  next();
});
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();


app.use((req: Request, res: Response, next: NextFunction) => {
  console.log('Time:', Date.now());
  next();
});
```

### [Middleware mounted on a path](#middleware-mounted-on-a-path)

The following middleware function runs for any type of HTTP request on the `/user/:id` path:

```
app.use('/user/:id', (req, res, next) => {
  console.log('Request Type:', req.method);
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use('/user/:id', (req: Request, res: Response, next: NextFunction) => {
  console.log('Request Type:', req.method);
  next();
});
```

### [Route handlers](#route-handlers)

This example shows a route and its handler function (middleware system). The function handles GET requests to the `/user/:id` path:

```
app.get('/user/:id', (req, res) => {
  res.send('USER');
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/:id', (req: Request, res: Response) => {
  res.send('USER');
});
```

### [Middleware sub-stacks](#middleware-sub-stacks)

Multiple middleware functions can be loaded together at a mount point to form a middleware sub-stack. This example prints request info for any type of HTTP request to the `/user/:id` path:

```
app.use(
  '/user/:id',
  (req, res, next) => {
    console.log('Request URL:', req.originalUrl);
    next();
  },
  (req, res, next) => {
    console.log('Request Type:', req.method);
    next();
  }
);
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use(
  '/user/:id',
  (req: Request, res: Response, next: NextFunction) => {
    console.log('Request URL:', req.originalUrl);
    next();
  },
  (req: Request, res: Response, next: NextFunction) => {
    console.log('Request Type:', req.method);
    next();
  }
);
```

### [Multiple route handlers](#multiple-route-handlers)

Route handlers enable you to define multiple routes for a path. The example below defines two routes for GET requests to the `/user/:id` path. The second route will not cause any problems, but it will never get called because the first route ends the request-response cycle.

```
app.get(
  '/user/:id',
  (req, res, next) => {
    console.log('ID:', req.params.id);
    next();
  },
  (req, res) => {
    res.send('User Info');
  }
);


// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', (req, res) => {
  res.send(req.params.id);
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get(
  '/user/:id',
  (req: Request, res: Response, next: NextFunction) => {
    console.log('ID:', req.params.id);
    next();
  },
  (req: Request, res: Response) => {
    res.send('User Info');
  }
);


// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', (req: Request, res: Response) => {
  res.send(req.params.id);
});
```

### [Skipping to the next route](#skipping-to-the-next-route)

Call `next('route')` to skip the remaining middleware functions in a router middleware stack and pass control to the next route.

### Note

`next('route')` will work only in middleware functions that were loaded by using the `app.METHOD()` or `router.METHOD()` functions.

In the following example, if the user ID is `0`, the first handler skips to the next route, which sends a special response:

```
app.get(
  '/user/:id',
  (req, res, next) => {
    // if the user ID is 0, skip to the next route
    if (req.params.id === '0') next('route');
    // otherwise pass the control to the next middleware function in this stack
    else next();
  },
  (req, res) => {
    // send a regular response
    res.send('regular');
  }
);


// handler for the /user/:id path, which sends a special response
app.get('/user/:id', (req, res) => {
  res.send('special');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get(
  '/user/:id',
  (req: Request, res: Response, next: NextFunction) => {
    // if the user ID is 0, skip to the next route
    if (req.params.id === '0') next('route');
    // otherwise pass the control to the next middleware function in this stack
    else next();
  },
  (req: Request, res: Response) => {
    // send a regular response
    res.send('regular');
  }
);


// handler for the /user/:id path, which sends a special response
app.get('/user/:id', (req: Request, res: Response) => {
  res.send('special');
});
```

### [Reusable middleware arrays](#reusable-middleware-arrays)

Middleware functions can also be grouped into arrays for better reusability. This example shows an array with a middleware sub-stack that handles GET requests to the `/user/:id` path:

```
function logOriginalUrl(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
}


function logMethod(req, res, next) {
  console.log('Request Type:', req.method);
  next();
}


const logStuff = [logOriginalUrl, logMethod];
app.get('/user/:id', logStuff, (req, res) => {
  res.send('User Info');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


function logOriginalUrl(req: Request, res: Response, next: NextFunction) {
  console.log('Request URL:', req.originalUrl);
  next();
}


function logMethod(req: Request, res: Response, next: NextFunction) {
  console.log('Request Type:', req.method);
  next();
}


const logStuff = [logOriginalUrl, logMethod];
app.get('/user/:id', logStuff, (req: Request, res: Response) => {
  res.send('User Info');
});
```

## [Router-level middleware](#router-level-middleware)

Router-level middleware works the same way as application-level middleware, except it is bound to an instance of `express.Router()`.

```
const router = express.Router();
```

```
import express from 'express';


const router = express.Router();
```

Load router-level middleware by using the `router.use()` and `router.METHOD()` functions.

The following example code replicates the middleware system that is shown above for application-level middleware, by using router-level middleware:

index.cjs

```
const express = require('express');
const app = express();
const router = express.Router();


// a middleware function with no mount path. This code is executed for every request to the router
router.use((req, res, next) => {
  console.log('Time:', Date.now());
  next();
});


// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use(
  '/user/:id',
  (req, res, next) => {
    console.log('Request URL:', req.originalUrl);
    next();
  },
  (req, res, next) => {
    console.log('Request Type:', req.method);
    next();
  }
);


// a middleware sub-stack that handles GET requests to the /user/:id path
router.get(
  '/user/:id',
  (req, res, next) => {
    // if the user ID is 0, skip to the next route
    if (req.params.id === '0') next('route');
    // otherwise pass control to the next middleware function in this stack
    else next();
  },
  (req, res) => {
    // render a regular page
    res.render('regular');
  }
);


// handler for the /user/:id path, which renders a special page
router.get('/user/:id', (req, res) => {
  console.log(req.params.id);
  res.render('special');
});


// mount the router on the app
app.use('/', router);
```

index.mjs

```
import express from 'express';


const app = express();
const router = express.Router();


// a middleware function with no mount path. This code is executed for every request to the router
router.use((req, res, next) => {
  console.log('Time:', Date.now());
  next();
});


// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use(
  '/user/:id',
  (req, res, next) => {
    console.log('Request URL:', req.originalUrl);
    next();
  },
  (req, res, next) => {
    console.log('Request Type:', req.method);
    next();
  }
);


// a middleware sub-stack that handles GET requests to the /user/:id path
router.get(
  '/user/:id',
  (req, res, next) => {
    // if the user ID is 0, skip to the next route
    if (req.params.id === '0') next('route');
    // otherwise pass control to the next middleware function in this stack
    else next();
  },
  (req, res) => {
    // render a regular page
    res.render('regular');
  }
);


// handler for the /user/:id path, which renders a special page
router.get('/user/:id', (req, res) => {
  console.log(req.params.id);
  res.render('special');
});


// mount the router on the app
app.use('/', router);
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();
const router = express.Router();


// a middleware function with no mount path. This code is executed for every request to the router
router.use((req: Request, res: Response, next: NextFunction) => {
  console.log('Time:', Date.now());
  next();
});


// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use(
  '/user/:id',
  (req: Request, res: Response, next: NextFunction) => {
    console.log('Request URL:', req.originalUrl);
    next();
  },
  (req: Request, res: Response, next: NextFunction) => {
    console.log('Request Type:', req.method);
    next();
  }
);


// a middleware sub-stack that handles GET requests to the /user/:id path
router.get(
  '/user/:id',
  (req: Request, res: Response, next: NextFunction) => {
    // if the user ID is 0, skip to the next route
    if (req.params.id === '0') next('route');
    // otherwise pass control to the next middleware function in this stack
    else next();
  },
  (req: Request, res: Response) => {
    // render a regular page
    res.render('regular');
  }
);


// handler for the /user/:id path, which renders a special page
router.get('/user/:id', (req: Request, res: Response) => {
  console.log(req.params.id);
  res.render('special');
});


// mount the router on the app
app.use('/', router);
```

### [Skipping out of a router](#skipping-out-of-a-router)

Use `next('router')` to skip the rest of the router’s middleware functions and pass control back out of the router instance.

In the following example, the router only responds when the request includes an `x-auth` header. Otherwise, `next('router')` exits the router and the app responds with a 401 status:

index.cjs

```
const express = require('express');
const app = express();
const router = express.Router();


// predicate the router with a check and bail out when needed
router.use((req, res, next) => {
  if (!req.headers['x-auth']) return next('router');
  next();
});


router.get('/user/:id', (req, res) => {
  res.send('hello, user!');
});


// use the router and 401 anything falling through
app.use('/admin', router, (req, res) => {
  res.sendStatus(401);
});
```

index.mjs

```
import express from 'express';


const app = express();
const router = express.Router();


// predicate the router with a check and bail out when needed
router.use((req, res, next) => {
  if (!req.headers['x-auth']) return next('router');
  next();
});


router.get('/user/:id', (req, res) => {
  res.send('hello, user!');
});


// use the router and 401 anything falling through
app.use('/admin', router, (req, res) => {
  res.sendStatus(401);
});
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();
const router = express.Router();


// predicate the router with a check and bail out when needed
router.use((req: Request, res: Response, next: NextFunction) => {
  if (!req.headers['x-auth']) return next('router');
  next();
});


router.get('/user/:id', (req: Request, res: Response) => {
  res.send('hello, user!');
});


// use the router and 401 anything falling through
app.use('/admin', router, (req: Request, res: Response) => {
  res.sendStatus(401);
});
```

## [Error-handling middleware](#error-handling-middleware)

Define error-handling middleware functions in the same way as other middleware functions, except with four arguments instead of three, specifically with the signature `(err, req, res, next)`:

```
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

### Caution

Error-handling middleware always takes *four* arguments. You must provide four arguments to identify it as an error-handling middleware function. Even if you don’t need to use the `next` object, you must specify it to maintain the signature. Otherwise, the `next` object will be interpreted as regular middleware and will fail to handle errors.

## [Built-in middleware](#built-in-middleware)

Express has the following built-in middleware functions:

* [express.static](/en/5x/api/express/#expressstatic) serves static assets such as HTML files, images, and so on.
* [express.json](/en/5x/api/express/#expressjson) parses incoming requests with JSON payloads.
* [express.raw](/en/5x/api/express/#expressraw) parses incoming requests with Buffer payloads.
* [express.text](/en/5x/api/express/#expresstext) parses incoming requests with text payloads.
* [express.urlencoded](/en/5x/api/express/#expressurlencoded) parses incoming requests with URL-encoded payloads.

## [Third-party middleware](#third-party-middleware)

Use third-party middleware to add functionality to Express apps.

Install the Node.js module for the required functionality, then load it in your app at the application level or at the router level.

The following example illustrates installing and loading the cookie-parsing middleware function `cookie-parser`:

Terminal window

```
npm install cookie-parser
```

Terminal window

```
yarn add cookie-parser
```

Terminal window

```
pnpm add cookie-parser
```

Terminal window

```
bun add cookie-parser
```

index.cjs

```
const express = require('express');
const app = express();
const cookieParser = require('cookie-parser');


// load the cookie-parsing middleware
app.use(cookieParser());
```

index.mjs

```
import express from 'express';
import cookieParser from 'cookie-parser';


const app = express();


// load the cookie-parsing middleware
app.use(cookieParser());
```

index.ts

```
import express, { type Express } from 'express';
import cookieParser from 'cookie-parser';


const app: Express = express();


// load the cookie-parsing middleware
app.use(cookieParser());
```

----
url: https://expressjs.com/en/blog/2024-07-16-welcome-post
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2024-07-16-welcome-post)

announcements

# [Welcome to The Express Blog!](#overview)

Rand McKinney, Chris DelJuly 16, 2024

[](https://x.com/intent/tweet?text=Welcome%20to%20The%20Express%20Blog!\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-07-16-welcome-post%2F)[](https://bsky.app/intent/compose?text=Welcome%20to%20The%20Express%20Blog!%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-07-16-welcome-post%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-07-16-welcome-post%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-07-16-welcome-post%2F\&text=Welcome%20to%20The%20Express%20Blog!)[](https://wa.me/?text=Welcome%20to%20The%20Express%20Blog!%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-07-16-welcome-post%2F)[](/feed.xml)

Welcome to the new Express blog! The blog is meant to be a primary means of communication for the Express technical committee (TC). While we currently have other channels such as X, LinkedIn, and of course GitHub, there’s no authoritative “soapbox” for announcements and general communication.

Initially, the Express blog will be a venue:

* For periodic announcements of new releases, pre-releases, plans, and ongoing work on the project.
* For the Express TC to discuss issues of particular importance to the Express community.
* To highlight security issues or other urgent information.

Eventually, we hope the blog will evolve into a more general communication hub for the entire Express community; for example to share examples, tips, and experiences with the Express ecosystem and other information that’s not simply technical documentation or GitHub discussion.

Initially, posts will be written by TC members (potentially collaborating others), mainly because we don’t have bandwidth to review general posts from the broader community. Eventually, we would love to open up the blog for broader contributions, but for now the focus is on trying to release Express 5.0, and the reality of an open-source project is that everyone has finite time to contribute.

Express TC member [Ulises Gascón](https://github.com/UlisesGascon) suggested a number of interesting topics for blog posts in [expressjs.com issue 1500](https://github.com/expressjs/expressjs.com/issues/1500), but there are undoubtedly many others.

If you have an idea for a post, feel free to pitch the idea! You can add a comment to [expressjs.com issue 1500](https://github.com/expressjs/expressjs.com/issues/1500) or open a new issue, and then after appropriate discussion, open a PR. We’ve also written up simple instructions to create a blog post.

Happy blogging!

----
url: https://expressjs.com/en/resources/middleware/multer
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/multer.mdx)

# [multer middleware](#overview)

v2.4.0[GitHub](https://github.com/expressjs/multer)[Changelog](https://github.com/expressjs/multer/releases)[npm](https://www.npmjs.com/package/multer)

Multer is a node.js middleware for handling `multipart/form-data`, which is primarily used for uploading files. It is written on top of [busboy](https://github.com/mscdex/busboy) for maximum efficiency.

**NOTE**: Multer will not process any form which is not multipart (`multipart/form-data`).

## [Installation](#installation)

Terminal window

```
npm install multer
```

Terminal window

```
yarn add multer
```

Terminal window

```
pnpm add multer
```

Terminal window

```
bun add multer
```

### Note

`multer` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/multer
```

Terminal window

```
yarn add --dev @types/multer
```

Terminal window

```
pnpm add --save-dev @types/multer
```

Terminal window

```
bun add --dev @types/multer
```

## [Usage](#usage)

Multer adds a `body` object and a `file` or `files` object to the `request` object. The `body` object contains the values of the text fields of the form, the `file` or `files` object contains the files uploaded via the form.

Basic usage example:

Don’t forget the `enctype="multipart/form-data"` in your form.

```
<form action="/profile" method="post" enctype="multipart/form-data">
  <input type="file" name="avatar" />
</form>
```

```
const express = require('express');
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });


const app = express();


app.post('/profile', upload.single('avatar'), function (req, res, next) {
  // req.file is the `avatar` file
  // req.body will hold the text fields, if there were any
});


app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {
  // req.files is array of `photos` files
  // req.body will contain the text fields, if there were any
});


const uploadMiddleware = upload.fields([
  { name: 'avatar', maxCount: 1 },
  { name: 'gallery', maxCount: 8 },
]);
app.post('/cool-profile', uploadMiddleware, function (req, res, next) {
  // req.files is an object (String -> Array) where fieldname is the key, and the value is array of files
  //
  // e.g.
  //  req.files['avatar'][0] -> File
  //  req.files['gallery'] -> Array
  //
  // req.body will contain the text fields, if there were any
});
```

In case you need to handle a text-only multipart form, you should use the `.none()` method:

```
const express = require('express');
const app = express();
const multer = require('multer');
const upload = multer();


app.post('/profile', upload.none(), function (req, res, next) {
  // req.body contains the text fields
});
```

Here’s an example on how multer is used in a HTML form. Take special note of the `enctype="multipart/form-data"` and `name="uploaded_file"` fields:

```
<form action="/stats" enctype="multipart/form-data" method="post">
  <div class="form-group">
    <input type="file" class="form-control-file" name="uploaded_file" />
    <input type="text" class="form-control" placeholder="Number of speakers" name="nspeakers" />
    <input type="submit" value="Get me the stats!" class="btn btn-default" />
  </div>
</form>
```

Then in your javascript file you would add these lines to access both the file and the body. It is important that you use the `name` field value from the form in your upload function. This tells multer which field on the request it should look for the files in. If these fields aren’t the same in the HTML form and on your server, your upload will fail:

```
const multer = require('multer');
const upload = multer({ dest: './public/data/uploads/' });
app.post('/stats', upload.single('uploaded_file'), function (req, res) {
  // req.file is the name of your file in the form above, here 'uploaded_file'
  // req.body will hold the text fields, if there were any
  console.log(req.file, req.body);
});
```

Complete client-side and server-side examples (browser `FormData` uploads of a blob and of an image) are in the [`examples/`](https://github.com/expressjs/multer/blob/HEAD/examples/) folder.

## [API](#api)

### [File information](#file-information)

Each file contains the following information:

| Key            | Description                                                                         | Note            |
| -------------- | ----------------------------------------------------------------------------------- | --------------- |
| `fieldname`    | Field name specified in the form                                                    |                 |
| `originalname` | Name of the file on the user’s computer, or the full path when `preservePath: true` |                 |
| `encoding`     | Encoding type of the file                                                           |                 |
| `mimetype`     | Mime type of the file                                                               |                 |
| `size`         | Size of the file in bytes                                                           |                 |
| `destination`  | The folder to which the file has been saved                                         | `DiskStorage`   |
| `filename`     | The name of the file within the `destination`                                       | `DiskStorage`   |
| `path`         | The full path to the uploaded file                                                  | `DiskStorage`   |
| `buffer`       | A `Buffer` of the entire file                                                       | `MemoryStorage` |

### [`multer(opts)`](#multeropts)

Multer accepts an options object, the most basic of which is the `dest` property, which tells Multer where to upload the files. In case you omit the options object, the files will be kept in memory and never written to disk.

By default, Multer will rename the files so as to avoid naming conflicts. The renaming function can be customized according to your needs.

The following are the options that can be passed to Multer.

| Key                 | Description                                                                                                                                                                |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `defCharset`        | Default character set to use for text field values that do not declare one. Default: `'utf8'`                                                                              |
| `defParamCharset`   | Default character set to use for values of part header parameters (e.g. filename) that are not extended parameters (that contain an explicit charset). Default: `'latin1'` |
| `dest` or `storage` | Where to store the files                                                                                                                                                   |
| `fileFilter`        | Function to control which files are accepted                                                                                                                               |
| `fileHwm`           | `highWaterMark` of each file stream (`file.stream`). Default: busboy’s default                                                                                             |
| `highWaterMark`     | `highWaterMark` of the multipart parser stream. Default: busboy’s default                                                                                                  |
| `limits`            | Limits of the uploaded data                                                                                                                                                |
| `preservePath`      | Keep the full client-supplied path in `file.originalname` instead of just the base name                                                                                    |
| `streamHandler`     | Function that feeds the request body to busboy; defaults to `req.pipe(busboy)`                                                                                             |

In an average web app, only `dest` might be required, and configured as shown in the following example.

```
const upload = multer({ dest: 'uploads/' });
```

When `preservePath` is enabled, Multer passes the incoming filename through with any path segments provided by the client. This is exposed as `file.originalname`; it does not change the destination folder, create directories, or sanitize the path for you. `file.originalname` is always client-supplied and should be treated as untrusted; with `preservePath` it additionally contains the path segments the client sent. Normalize or validate it before using it in a custom `filename` or storage engine.

If you want more control over your uploads, you’ll want to use the `storage` option instead of `dest`. Multer ships with storage engines `DiskStorage` and `MemoryStorage`; More engines are available from third parties.

#### [`.single(fieldname)`](#singlefieldname)

Accept a single file with the name `fieldname`. The single file will be stored in `req.file`.

#### [`.array(fieldname[, maxCount])`](#arrayfieldname-maxcount)

Accept an array of files, all with the name `fieldname`. Optionally error out if more than `maxCount` files are uploaded. The array of files will be stored in `req.files`.

Files skipped by `fileFilter` do not count towards `maxCount`. Use `limits.files` to bound how many files are read from a request.

#### [`.fields(fields)`](#fieldsfields)

Accept a mix of files, specified by `fields`. An object with arrays of files will be stored in `req.files`.

`fields` should be an array of objects with `name` and optionally a `maxCount`. Example:

```
[
  { name: 'avatar', maxCount: 1 },
  { name: 'gallery', maxCount: 8 },
];
```

#### [`.none()`](#none)

Accept only text fields. If any file upload is made, error with code “LIMIT\_UNEXPECTED\_FILE” will be issued.

#### [`.any()`](#any)

Accepts all files that comes over the wire. An array of files will be stored in `req.files`.

**WARNING:** Make sure that you always handle the files that a user uploads. Never add multer as a global middleware since a malicious user could upload files to a route that you didn’t anticipate. Only use this function on routes where you are handling the uploaded files.

### [`storage`](#storage)

#### [`DiskStorage`](#diskstorage)

The disk storage engine gives you full control on storing files to disk.

```
const crypto = require('crypto');


const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, '/tmp/my-uploads');
  },
  filename: function (req, file, cb) {
    crypto.randomBytes(16, function (err, raw) {
      if (err) return cb(err);
      cb(null, file.fieldname + '-' + raw.toString('hex'));
    });
  },
});


const upload = multer({ storage: storage });
```

There are three options available: `destination`, `filename` and `flush`. All of them except `flush` are functions that determine where the file should be stored.

`destination` is used to determine within which folder the uploaded files should be stored. This can also be given as a `string` (e.g. `'/tmp/uploads'`). If no `destination` is given, the operating system’s default directory for temporary files is used.

**Note:** You are responsible for creating the directory when providing `destination` as a function. When passing a string, multer will make sure that the directory is created for you.

`filename` is used to determine what the file should be named inside the folder. If no `filename` is given, each file will be given a random name that doesn’t include any file extension.

**Note:** Multer will not append any file extension for you, your function should return a filename complete with a file extension.

Each function gets passed both the request (`req`) and some information about the file (`file`) to aid with the decision.

Note that `req.body` might not have been fully populated yet. It depends on the order that the client transmits fields and files to the server.

For understanding the calling convention used in the callback (needing to pass null as the first param), refer to [Node.js error handling](https://web.archive.org/web/20220417042018/https://www.joyent.com/node-js/production/design/errors)

`flush` is an optional boolean. When set to `true`, the file data is flushed to disk with an `fsync` call before the upload handler runs, which prevents data loss if the process or the system crashes while the data is still sitting in the operating system’s page cache. It is disabled by default because forcing a disk flush on every upload has a performance cost. Note that this syncs the file contents only; if the new directory entry must survive a crash as well, fsync the destination directory yourself.

#### [`MemoryStorage`](#memorystorage)

The memory storage engine stores the files in memory as `Buffer` objects. It doesn’t have any options.

```
const storage = multer.memoryStorage();
const upload = multer({ storage: storage });
```

When using memory storage, the file info will contain a field called `buffer` that contains the entire file.

**WARNING**: Uploading very large files, or relatively small files in large numbers very quickly, can cause your application to run out of memory when memory storage is used.

### [`limits`](#limits)

An object specifying the size limits of the following optional properties. Multer passes this object into busboy directly, and the details of the properties can be found on [busboy’s page](https://github.com/mscdex/busboy#exports).

`limits` can also be a function that receives the request and returns such an object. It is called once per request, before parsing starts, so limits can depend on e.g. the authenticated user:

```
const upload = multer({
  limits: function (req) {
    return { fileSize: req.user.maxUploadSize };
  },
});
```

Limits apply to the whole request; there is no per-file limit. To restrict individual files by type or name, use `fileFilter` or a custom storage engine.

The following integer values are available:

| Key                    | Description                                                                     | Default  |
| ---------------------- | ------------------------------------------------------------------------------- | -------- |
| `fieldNameSize`        | Max field name size                                                             | Infinity |
| `fieldSize`            | Max field value size (in bytes)                                                 | 1MB      |
| `fields`               | Max number of non-file fields                                                   | Infinity |
| `fileSize`             | For multipart forms, the max file size (in bytes)                               | Infinity |
| `files`                | For multipart forms, the max number of file fields                              | Infinity |
| `parts`                | For multipart forms, the max number of parts (fields + files)                   | Infinity |
| `headerPairs`          | For multipart forms, the max number of header key=>value pairs to parse         | 2000     |
| `fieldNestingDepth`    | Max number of nesting levels for field names (e.g. `a[b][c]` has 2 levels)      | Infinity |
| `fieldArrayIndexLimit` | Max numeric array index accepted inside a field name (e.g. `a[3]` uses index 3) | Infinity |

Specifying the limits can help protect your site against denial of service (DoS) attacks.

### [`fileFilter`](#filefilter)

Set this to a function to control which files should be uploaded and which should be skipped. The function should look like this:

```
function fileFilter(req, file, cb) {
  // The function should call `cb` with a boolean
  // to indicate if the file should be accepted


  // To reject this file pass `false`, like so:
  cb(null, false);


  // To accept the file pass `true`, like so:
  cb(null, true);


  // You can always pass an error if something goes wrong:
  cb(new Error("I don't have a clue!"));
}
```

### [`streamHandler`](#streamhandler)

By default Multer reads the request with `req.pipe(busboy)`. Some platforms consume the request body before your handlers run, so there is nothing left to pipe. Google Cloud Functions and Firebase Functions, for example, expose the already-read body as `req.rawBody`. Provide a `streamHandler` to feed busboy yourself in that case:

```
const upload = multer({
  storage: multer.memoryStorage(),
  streamHandler: function (req, busboy) {
    if (req.rawBody) {
      busboy.end(req.rawBody);
    } else {
      req.pipe(busboy);
    }
  },
});
```

The function receives the request and the busboy instance and must write the whole multipart body to busboy and end it.

## [Security](#security)

Specifying the [limits](#limits) can help protect your site against denial of service (DoS) attacks. The following limits are recommended for most applications:

* `fileSize` — set to the maximum expected file size for your use case
* `files` — set to the maximum number of files per request
* `fields` — set to the maximum number of text fields per request
* `fieldNestingDepth` — set to the minimum depth your field names require (e.g. `3` for `a[b][c]`)
* `fieldArrayIndexLimit` — set to the largest array index your field names require (e.g. `100` for `a[99]`)

## [Error handling](#error-handling)

When encountering an error, Multer will delegate the error to Express. You can display a nice error page using [the standard express way](/en/5x/guide/error-handling/).

If you want to catch errors specifically from Multer, you can call the middleware function by yourself. Also, if you want to catch only [the Multer errors](https://github.com/expressjs/multer/blob/main/lib/multer-error.js), you can use the `MulterError` class that is attached to the `multer` object itself (e.g. `err instanceof multer.MulterError`).

Multer errors carry a `code` (e.g. `LIMIT_FILE_SIZE`) and, when the error concerns a specific field, its name in `field`. Errors about a specific file (`LIMIT_FILE_SIZE`, `LIMIT_UNEXPECTED_FILE`) also expose the client-supplied file name in `filename`; treat it as untrusted input, like `file.originalname`.

```
const multer = require('multer');
const upload = multer().single('avatar');


app.post('/profile', function (req, res) {
  upload(req, res, function (err) {
    if (err instanceof multer.MulterError) {
      // A Multer error occurred when uploading.
    } else if (err) {
      // An unknown error occurred when uploading.
    }


    // Everything went fine.
  });
});
```

## [Custom storage engine](#custom-storage-engine)

For information on how to build your own storage engine, see [Multer Storage Engine](https://github.com/expressjs/multer/blob/main/StorageEngine.md).

## [License](#license)

[MIT](https://github.com/expressjs/multer/blob/HEAD/LICENSE)

----
url: https://expressjs.com/en/4x/guide/using-template-engines
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/guide/using-template-engines.mdx)

# [Using template engines with Express](#overview)

A *template engine* enables you to use static template files in your application. At runtime, the template engine replaces variables in a template file with actual values, and transforms the template into an HTML file sent to the client. This approach makes it easier to design an HTML page.

The [Express application generator](/en/4x/starter/generator/) uses [Pug](https://pugjs.org/api/getting-started.html) as its default, but it can generate apps configured for Handlebars-compatible engines such as [hbs](https://www.npmjs.com/package/hbs), [EJS](https://www.npmjs.com/package/ejs), among others.

For apps created by the generator, these settings are added to the generated `app.js`. For apps you create without the generator, set the following [application setting properties](/en/4x/api/application/#appset) yourself:

* `views`, the directory where the template files are located. Eg: `app.set('views', './views')`. This defaults to the `views` directory in the application root directory.
* `view engine`, the template engine to use. For example, to use the Pug template engine: `app.set('view engine', 'pug')`.

Then install the corresponding Express-compatible template engine npm package; for example to install Pug:

Terminal window

```
npm install pug --save
```

Terminal window

```
yarn add pug
```

Terminal window

```
pnpm add pug
```

Terminal window

```
bun add pug
```

### Caution

Express-compliant template engines such as Pug export a function named `__express(filePath, options, callback)`, which `res.render()` calls to render the template code.

Some template engines do not follow this convention. The [@ladjs/consolidate](https://www.npmjs.com/package/@ladjs/consolidate) library follows this convention by mapping all of the popular Node.js template engines, and therefore works seamlessly within Express. For example, install [hbs](https://www.npmjs.com/package/hbs) or any other Express-compatible Handlebars view engine instead of the raw `handlebars` package by itself.

After the view engine is set, you don’t have to specify the engine or load the template engine module in your app; Express loads the module internally, for example:

```
app.set('view engine', 'pug');
```

Then, create a Pug template file named `index.pug` in the `views` directory, with the following content:

```
html
  head
    title= title
  body
    h1= message
```

Create a route to render the `index.pug` file. If the `view engine` property is not set, you must specify the extension of the `view` file. Otherwise, you can omit it.

```
app.get('/', (req, res) => {
  res.render('index', { title: 'Hey', message: 'Hello there!' });
});
```

```
import { type Request, type Response } from 'express';


app.get('/', (req: Request, res: Response) => {
  res.render('index', { title: 'Hey', message: 'Hello there!' });
});
```

When you make a request to the home page, the `index.pug` file will be rendered as HTML.

The view engine cache does not cache the contents of the template’s output, only the underlying template itself. The view is still re-rendered with every request even when the cache is on.

----
url: https://expressjs.com/en/5x/guide/routing
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/guide/routing.mdx)

# [Routing](#overview)

*Routing* refers to how an application’s endpoints (URIs) respond to client requests. For an introduction to routing, see [Basic routing](/en/5x/starter/basic-routing/).

You define routing using methods of the Express `app` object that correspond to HTTP methods; for example, `app.get()` to handle GET requests and `app.post` to handle POST requests. For a full list, see [app.METHOD](/en/5x/api/application/#appmethod). You can also use [app.all()](/en/5x/api/application/#appall) to handle all HTTP methods and [app.use()](/en/5x/api/application/#appuse) to specify middleware as the callback function (See [Using middleware](/en/5x/guide/using-middleware/) for details).

These routing methods specify a callback function (sometimes called a “handler function”) that Express automatically runs when the application receives a request matching the specified route (endpoint) and HTTP method. In other words, the application “listens” for requests that match the specified route(s) and method(s), and when it detects a match, it calls the specified callback function.

In fact, the routing methods can have more than one callback function as arguments. With multiple callback functions, it is important to provide `next` as an argument to the callback function and then call `next()` within the body of the function to hand off control to the next callback.

The following code is an example of a very basic route.

index.cjs

```
const express = require('express');
const app = express();


// respond with "hello world" when a GET request is made to the homepage
app.get('/', (req, res) => {
  res.send('hello world');
});
```

index.mjs

```
import express from 'express';


const app = express();


// respond with "hello world" when a GET request is made to the homepage
app.get('/', (req, res) => {
  res.send('hello world');
});
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


// respond with "hello world" when a GET request is made to the homepage
app.get('/', (req: Request, res: Response) => {
  res.send('hello world');
});
```

## [Route methods](#route-methods)

A route method is derived from one of the HTTP methods, and is attached to an instance of the `express` class.

The following code is an example of routes that are defined for the `GET` and the `POST` methods to the root of the app.

```
// GET method route
app.get('/', (req, res) => {
  res.send('GET request to the homepage');
});


// POST method route
app.post('/', (req, res) => {
  res.send('POST request to the homepage');
});
```

```
import { type Request, type Response } from 'express';


// GET method route
app.get('/', (req: Request, res: Response) => {
  res.send('GET request to the homepage');
});


// POST method route
app.post('/', (req: Request, res: Response) => {
  res.send('POST request to the homepage');
});
```

Express supports methods that correspond to all HTTP request methods: `get`, `post`, and so on. For a full list, see [app.METHOD](/en/5x/api/application/#appmethod).

There is a special routing method, `app.all()`, used to load middleware functions at a path for *all* HTTP request methods. For example, the following handler is executed for requests to the route `"/secret"` whether using `GET`, `QUERY`, `POST`, `PUT`, `DELETE`, or any other HTTP request method supported in the [http module](https://nodejs.org/api/http.html#httpmethods).

```
app.all('/secret', (req, res, next) => {
  console.log('Accessing the secret section ...');
  next(); // pass control to the next handler
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.all('/secret', (req: Request, res: Response, next: NextFunction) => {
  console.log('Accessing the secret section ...');
  next(); // pass control to the next handler
});
```

## [Route paths](#route-paths)

Route paths, in combination with a request method, define the endpoints at which requests can be made. Route paths can be strings or regular expressions. They can also capture values from the URL, as described in [Route parameters](#route-parameters) below.

### Note

Express uses [path-to-regexp](https://www.npmjs.com/package/path-to-regexp) v8 for matching the route paths; see the path-to-regexp documentation for all the possibilities in defining route paths. [Express Playground Router](https://bjohansebas.github.io/playground-router/) is a handy tool for testing basic Express routes, although it does not support pattern matching.

### [String paths](#string-paths)

String paths match requests exactly. The dot (`.`) and hyphen (`-`) are interpreted literally.

### Warning

Query strings are not part of the route path.

```
app.get('/', (req, res) => {
  res.send('root');
});


app.get('/about', (req, res) => {
  res.send('about');
});


app.get('/random.text', (req, res) => {
  res.send('random.text');
});
```

```
import { type Request, type Response } from 'express';


app.get('/', (req: Request, res: Response) => {
  res.send('root');
});


app.get('/about', (req: Request, res: Response) => {
  res.send('about');
});


app.get('/random.text', (req: Request, res: Response) => {
  res.send('random.text');
});
```

### Caution

The characters `?`, `+`, `*`, `[]`, `()`, and `!` are reserved and cannot be used as literal characters in route paths, and braces are reserved for [optional segments](#optional-segments). Use `\` to escape them if needed.

### [Regular expressions](#regular-expressions)

You can also use regular expressions as route paths. This is useful when you need more complex matching logic.

```
// Matches any path containing "a"
app.get(/a/, (req, res) => {
  res.send('/a/');
});


// Matches paths ending with "fly" (butterfly, dragonfly, etc.)
app.get(/.*fly$/, (req, res) => {
  res.send('/.*fly$/');
});
```

```
import { type Request, type Response } from 'express';


// Matches any path containing "a"
app.get(/a/, (req: Request, res: Response) => {
  res.send('/a/');
});


// Matches paths ending with "fly" (butterfly, dragonfly, etc.)
app.get(/.*fly$/, (req: Request, res: Response) => {
  res.send('/.*fly$/');
});
```

## [Route parameters](#route-parameters)

Route parameters are named URL segments that are used to capture the values specified at their position in the URL. The captured values are populated in the `req.params` object, with the name of the route parameter specified in the path as their respective keys. They come in three forms: [named parameters](#named-parameters) (`:name`), [wildcards](#wildcards) (`*name`), and [optional segments](#optional-segments), which wrap either of them in braces.

### [Named parameters](#named-parameters)

Named parameters capture a single path segment at their position in the URL, or part of one when combined with literal characters, as shown further below.

```
Route path: /users/:userId/books/:bookId
Request URL: http://localhost:3000/users/34/books/8989
req.params: { "userId": "34", "bookId": "8989" }
```

To define routes with route parameters, simply specify the route parameters in the path of the route as shown below.

```
app.get('/users/:userId/books/:bookId', (req, res) => {
  res.send(req.params);
});
```

In TypeScript, `@types/express` infers the parameters from the route path, so in the handler above `req.params.userId` and `req.params.bookId` are already typed as `string` with no extra annotation. Reading a name that is not in the route (such as `req.params.other`) is a type error. You only need to annotate the parameters when the handler is defined separately from the route, because the type checker can no longer see the path. In that case, pass them as the first type argument of `Request`:

```
import { type Request, type Response } from 'express';


const sendParams = (req: Request<{ userId: string; bookId: string }>, res: Response) => {
  res.send(req.params);
};


app.get('/users/:userId/books/:bookId', sendParams);
```

### Caution

The name of route parameters must be a valid JavaScript identifier. Other names can be used by quoting them, for example `:"user-name"`.

Since the hyphen (`-`) and the dot (`.`) are interpreted literally, they can be used along with route parameters for useful purposes.

```
Route path: /flights/:from-:to
Request URL: http://localhost:3000/flights/LAX-SFO
req.params: { "from": "LAX", "to": "SFO" }
```

```
Route path: /plantae/:genus.:species
Request URL: http://localhost:3000/plantae/Prunus.persica
req.params: { "genus": "Prunus", "species": "persica" }
```

### Caution

Regexp characters are not supported inside string paths, so a parameter cannot be restricted with a suffix such as `:userId(\d+)`. Use an array of paths or a full regular expression instead. See the [path route matching syntax](/en/guide/migrating-5/#path-route-matching-syntax) for more information.

### [Wildcards](#wildcards)

Wildcards match any path after a prefix. Like other route parameters they must have a name, but they are captured as an array of path segments instead of a string.

```
app.get('/files/*filepath', (req, res) => {
  // GET /files/images/logo.png
  console.dir(req.params.filepath);
  // => [ 'images', 'logo.png' ]
  res.send(`File: ${req.params.filepath.join('/')}`);
});
```

```
import { type Request, type Response } from 'express';


app.get('/files/*filepath', (req: Request<{ filepath: string[] }>, res: Response) => {
  // GET /files/images/logo.png
  console.dir(req.params.filepath);
  // => [ 'images', 'logo.png' ]
  res.send(`File: ${req.params.filepath.join('/')}`);
});
```

To also match the root path, wrap the wildcard in braces:

```
// Matches / , /foo , /foo/bar , etc.
app.get('/{*splat}', (req, res) => {
  // GET / => req.params = {}, splat is omitted
  // GET /foo/bar => req.params.splat = [ 'foo', 'bar' ]
  res.send('ok');
});
```

```
import { type Request, type Response } from 'express';


// Matches / , /foo , /foo/bar , etc.
app.get('/{*splat}', (req: Request, res: Response) => {
  // GET / => req.params = {}, splat is omitted
  // GET /foo/bar => req.params.splat = [ 'foo', 'bar' ]
  res.send('ok');
});
```

### [Optional segments](#optional-segments)

Use braces to define optional segments in a route path. When the segment is not present, the parameter is omitted from `req.params`.

```
app.get('/:file{.:ext}', (req, res) => {
  // GET /image.png => req.params = { file: 'image', ext: 'png' }
  // GET /image => req.params = { file: 'image' }
  res.send('ok');
});
```

```
import { type Request, type Response } from 'express';


app.get('/:file{.:ext}', (req: Request, res: Response) => {
  // GET /image.png => req.params = { file: 'image', ext: 'png' }
  // GET /image => req.params = { file: 'image' }
  res.send('ok');
});
```

The braces can also wrap a whole parameter to make it optional. Note that everything inside the braces is optional, so the position of the slash matters:

```
app.get('/user/{:id}', (req, res) => {
  // GET /user/42 => req.params = { id: '42' }
  // GET /user/ => req.params = {}
  // GET /user => 404, only the parameter is optional
  res.send('ok');
});


app.get('/order{/:id}', (req, res) => {
  // GET /order/42 => req.params = { id: '42' }
  // GET /order => req.params = {}, the whole segment is optional
  res.send('ok');
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/{:id}', (req: Request, res: Response) => {
  // GET /user/42 => req.params = { id: '42' }
  // GET /user/ => req.params = {}
  // GET /user => 404, only the parameter is optional
  res.send('ok');
});


app.get('/order{/:id}', (req: Request, res: Response) => {
  // GET /order/42 => req.params = { id: '42' }
  // GET /order => req.params = {}, the whole segment is optional
  res.send('ok');
});
```

Do not confuse the position of the slash in the route path with the [`strict routing` setting](/en/5x/api/application/#application-settings), which is about the request URL: it controls whether a URL ending in a slash that the route path does not require still matches. For example, a request for `/order/` matches the `/order{/:id}` route by default, but returns a 404 error when strict routing is enabled; the trailing slash of `/user/` is unaffected because the `/user/{:id}` route requires it. All the requests commented in the examples above behave the same regardless of that setting.

## [Route handlers](#route-handlers)

You can provide multiple callback functions that behave like [middleware](/en/5x/guide/using-middleware/) to handle a request. The only exception is that these callbacks might invoke `next('route')` to bypass the remaining route callbacks. You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there’s no reason to proceed with the current route.

```
app.get('/user/:id', (req, res, next) => {
  if (req.params.id === '0') {
    return next('route');
  }
  res.send(`User ${req.params.id}`);
});


app.get('/user/:id', (req, res) => {
  res.send('Special handler for user ID 0');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get('/user/:id', (req: Request, res: Response, next: NextFunction) => {
  if (req.params.id === '0') {
    return next('route');
  }
  res.send(`User ${req.params.id}`);
});


app.get('/user/:id', (req: Request, res: Response) => {
  res.send('Special handler for user ID 0');
});
```

In this example:

* `GET /user/5` → handled by first route → sends “User 5”
* `GET /user/0` → first route calls `next('route')`, skipping to the next matching `/user/:id` route

Route handlers can be in the form of a function, an array of functions, or combinations of both, as shown in the following examples.

A single callback function can handle a route. For example:

```
app.get('/example/a', (req, res) => {
  res.send('Hello from A!');
});
```

```
import { type Request, type Response } from 'express';


app.get('/example/a', (req: Request, res: Response) => {
  res.send('Hello from A!');
});
```

More than one callback function can handle a route (make sure you specify the `next` object). For example:

```
app.get(
  '/example/b',
  (req, res, next) => {
    console.log('the response will be sent by the next function ...');
    next();
  },
  (req, res) => {
    res.send('Hello from B!');
  }
);
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.get(
  '/example/b',
  (req: Request, res: Response, next: NextFunction) => {
    console.log('the response will be sent by the next function ...');
    next();
  },
  (req: Request, res: Response) => {
    res.send('Hello from B!');
  }
);
```

An array of callback functions can handle a route. For example:

```
const cb0 = function (req, res, next) {
  console.log('CB0');
  next();
};


const cb1 = function (req, res, next) {
  console.log('CB1');
  next();
};


const cb2 = function (req, res) {
  res.send('Hello from C!');
};


app.get('/example/c', [cb0, cb1, cb2]);
```

```
import { type Request, type Response, type NextFunction } from 'express';


const cb0 = function (req: Request, res: Response, next: NextFunction) {
  console.log('CB0');
  next();
};


const cb1 = function (req: Request, res: Response, next: NextFunction) {
  console.log('CB1');
  next();
};


const cb2 = function (req: Request, res: Response) {
  res.send('Hello from C!');
};


app.get('/example/c', [cb0, cb1, cb2]);
```

A combination of independent functions and arrays of functions can handle a route. For example:

```
const cb0 = function (req, res, next) {
  console.log('CB0');
  next();
};


const cb1 = function (req, res, next) {
  console.log('CB1');
  next();
};


app.get(
  '/example/d',
  [cb0, cb1],
  (req, res, next) => {
    console.log('the response will be sent by the next function ...');
    next();
  },
  (req, res) => {
    res.send('Hello from D!');
  }
);
```

```
import { type Request, type Response, type NextFunction } from 'express';


const cb0 = function (req: Request, res: Response, next: NextFunction) {
  console.log('CB0');
  next();
};


const cb1 = function (req: Request, res: Response, next: NextFunction) {
  console.log('CB1');
  next();
};


app.get(
  '/example/d',
  [cb0, cb1],
  (req: Request, res: Response, next: NextFunction) => {
    console.log('the response will be sent by the next function ...');
    next();
  },
  (req: Request, res: Response) => {
    res.send('Hello from D!');
  }
);
```

## [Response methods](#response-methods)

The methods on the [response object](/en/5x/api/response/) (`res`) in the following table can send a response to the client, and terminate the request-response cycle. If none of these methods are called from a route handler, the client request will be left hanging.

| Method                                                 | Description                                                                           |
| ------------------------------------------------------ | ------------------------------------------------------------------------------------- |
| [res.download()](/en/5x/api/response/#resdownload)     | Prompt a file to be downloaded.                                                       |
| [res.end()](/en/5x/api/response/#resend)               | End the response process.                                                             |
| [res.json()](/en/5x/api/response/#resjson)             | Send a JSON response.                                                                 |
| [res.jsonp()](/en/5x/api/response/#resjsonp)           | Send a JSON response with JSONP support.                                              |
| [res.redirect()](/en/5x/api/response/#resredirect)     | Redirect a request.                                                                   |
| [res.render()](/en/5x/api/response/#resrender)         | Render a view template.                                                               |
| [res.send()](/en/5x/api/response/#ressend)             | Send a response of various types.                                                     |
| [res.sendFile()](/en/5x/api/response/#ressendfile)     | Send a file as an octet stream.                                                       |
| [res.sendStatus()](/en/5x/api/response/#ressendstatus) | Set the response status code and send its string representation as the response body. |

## [app.route()](#approute)

You can create chainable route handlers for a route path by using `app.route()`. Because the path is specified in a single location, this helps to create modular routes and reduces redundancy and typos. For more information about routes, see the [Router() documentation](/en/5x/api/router/).

Here is an example of chained route handlers that are defined by using `app.route()`.

```
app
  .route('/book')
  .get((req, res) => {
    res.send('Get a random book');
  })
  .post((req, res) => {
    res.send('Add a book');
  })
  .put((req, res) => {
    res.send('Update the book');
  });
```

```
import { type Request, type Response } from 'express';


app
  .route('/book')
  .get((req: Request, res: Response) => {
    res.send('Get a random book');
  })
  .post((req: Request, res: Response) => {
    res.send('Add a book');
  })
  .put((req: Request, res: Response) => {
    res.send('Update the book');
  });
```

## [express.Router](#expressrouter)

Use the `express.Router` class to create modular, mountable route handlers. A `Router` instance is a complete middleware and routing system; for this reason, it is often referred to as a “mini-app”.

The following example creates a router as a module, loads a middleware function in it, defines some routes, and mounts the router module on a path in the main app.

Create a router file named `birds.js` in the app directory, with the following content:

birds.cjs

```
const express = require('express');
const router = express.Router();


// middleware that is specific to this router
const timeLog = (req, res, next) => {
  console.log('Time: ', Date.now());
  next();
};
router.use(timeLog);


// define the home page route
router.get('/', (req, res) => {
  res.send('Birds home page');
});
// define the about route
router.get('/about', (req, res) => {
  res.send('About birds');
});


module.exports = router;
```

birds.mjs

```
import express from 'express';


const router = express.Router();


// middleware that is specific to this router
const timeLog = (req, res, next) => {
  console.log('Time: ', Date.now());
  next();
};
router.use(timeLog);


// define the home page route
router.get('/', (req, res) => {
  res.send('Birds home page');
});
// define the about route
router.get('/about', (req, res) => {
  res.send('About birds');
});


export default router;
```

birds.ts

```
import express, { type Request, type Response, type NextFunction } from 'express';


const router = express.Router();


// middleware that is specific to this router
const timeLog = (req: Request, res: Response, next: NextFunction) => {
  console.log('Time: ', Date.now());
  next();
};
router.use(timeLog);


// define the home page route
router.get('/', (req: Request, res: Response) => {
  res.send('Birds home page');
});
// define the about route
router.get('/about', (req: Request, res: Response) => {
  res.send('About birds');
});


export default router;
```

Then, load the router module in the app:

index.cjs

```
const birds = require('./birds');


// ...


app.use('/birds', birds);
```

index.mjs

```
import birds from './birds';


// ...


app.use('/birds', birds);
```

The app will now be able to handle requests to `/birds` and `/birds/about`, as well as call the `timeLog` middleware function that is specific to the route.

But if the parent route `/birds` has path parameters, it will not be accessible by default from the sub-routes. To make it accessible, you will need to pass the `mergeParams` option to the [Router constructor](/en/5x/api/express/#expressrouter).

```
const router = express.Router({ mergeParams: true });
```

----
url: https://expressjs.com/en/blog/2026-08-31-security-releases
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2026-08-31-security-releases)

security

# [August 2026 Security Releases](#overview)

Ulises GasconAugust 31, 2026

[](https://x.com/intent/tweet?text=August%202026%20Security%20Releases\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-08-31-security-releases%2F)[](https://bsky.app/intent/compose?text=August%202026%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-08-31-security-releases%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-08-31-security-releases%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-08-31-security-releases%2F\&text=August%202026%20Security%20Releases)[](https://wa.me/?text=August%202026%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-08-31-security-releases%2F)[](/feed.xml)

The Express team has released [hbs](https://www.npmjs.com/package/hbs) 4.3.0, [multer](https://www.npmjs.com/package/multer) 2.3.0, and [morgan](https://www.npmjs.com/package/morgan) 1.12.0, addressing six vulnerabilities across template rendering, multipart parsing, and access logging.

### Warning

We recommend upgrading to the latest versions of hbs, multer, and morgan to secure your applications. If you have a `package-lock.json`, you can update the dependencies by running:

Terminal window

```
npm update hbs multer morgan
```

The following vulnerabilities have been addressed:

* [CVE-2026-16231 in hbs template engine (High)](#cve-2026-16231-in-hbs-template-engine-high)
* [CVE-2026-77037 in multer middleware (High)](#cve-2026-77037-in-multer-middleware-high)
* [CVE-2026-77078 in multer middleware (High)](#cve-2026-77078-in-multer-middleware-high)
* [CVE-2026-82333 in multer middleware (High)](#cve-2026-82333-in-multer-middleware-high)
* [CVE-2026-15603 in morgan middleware (Medium)](#cve-2026-15603-in-morgan-middleware-medium)
* [CVE-2026-77063 in multer middleware (Low)](#cve-2026-77063-in-multer-middleware-low)

## [CVE-2026-16231 in hbs template engine (High)](#cve-2026-16231-in-hbs-template-engine-high)

**[hbs](https://www.npmjs.com/package/hbs) versions `>= 2.1.0, <= 4.2.1` are vulnerable to cross-site scripting through helpers registered with `registerAsyncHelper`**

hbs did not escape the output of asynchronous helpers the way it does for synchronous helpers, so a helper registered through `registerAsyncHelper` that returned attacker-influenced data emitted that data into the rendered page without neutralization. Applications that used async helpers to render values derived from user input were exposed to cross-site scripting, allowing script execution in the victim’s browser. The fix in 4.3.0 escapes async helper output consistently with synchronous helpers.

**Affected versions**: `>= 2.1.0, <= 4.2.1`\
**Patched version**: `>= 4.3.0`

For more details, see [GHSA-rg36-rxv9-2m9q](https://github.com/pillarjs/hbs/security/advisories/GHSA-rg36-rxv9-2m9q).

***

## [CVE-2026-77037 in multer middleware (High)](#cve-2026-77037-in-multer-middleware-high)

**[multer](https://www.npmjs.com/package/multer) version `2.2.0` is vulnerable to denial of service through a file descriptor leak on aborted uploads**

When a disk-backed upload was aborted or truncated before the write stream finished, multer removed the visible file from the upload directory but did not close the underlying write file descriptor. A remote attacker able to reach an upload route using the built-in disk storage could send repeated aborted or malformed multipart uploads, each one leaking a file descriptor and retaining disk blocks until the process exits, leading to resource exhaustion and denial of service. The fix in 2.3.0 closes the destination write stream on abnormal source termination and defers cleanup until the stream has closed.

**Affected versions**: `= 2.2.0`\
**Patched version**: `>= 2.3.0`

For more details, see [GHSA-qfvm-cv95-jqjf](https://github.com/expressjs/multer/security/advisories/GHSA-qfvm-cv95-jqjf).

***

## [CVE-2026-77078 in multer middleware (High)](#cve-2026-77078-in-multer-middleware-high)

**[multer](https://www.npmjs.com/package/multer) versions `< 2.3.0` are vulnerable to denial of service through crafted multipart field names**

A small multipart request containing two specially crafted text field names caused an uncaught `RangeError` in multer’s field parser and terminated the Node.js process. The first field used a very large numeric array index to allocate a maximum-length sparse array, and a second field pushed past that length, which threw inside the append-field dependency and was not caught by multer. A single unauthenticated request was sufficient to crash the server, making this a remotely triggered denial of service. The fix in 2.3.0 handles the parser error and rejects the request instead of crashing.

**Affected versions**: `< 2.3.0`\
**Patched version**: `>= 2.3.0`

For more details, see [GHSA-wc9g-mqfw-jrwm](https://github.com/expressjs/multer/security/advisories/GHSA-wc9g-mqfw-jrwm).

***

## [CVE-2026-82333 in multer middleware (High)](#cve-2026-82333-in-multer-middleware-high)

**[multer](https://www.npmjs.com/package/multer) versions `< 2.3.0` are vulnerable to denial of service through an oversized array index in field names**

A multipart request with a first field using a very large numeric array index made multer allocate a maximum-length sparse array, and a second field with a non-numeric key then triggered a full-length iteration inside the append-field dependency that blocked the event loop and left the process unable to handle other requests. A single request was enough to make the worker unresponsive, so this is a remotely triggered denial of service. multer 2.3.0 adds an opt-in `limits.fieldArrayIndexLimit` option that rejects oversized indexes. We recommend upgrading to 2.3.0 and setting `limits.fieldArrayIndexLimit` to the largest array index your application needs.

**Affected versions**: `< 2.3.0`\
**Patched version**: `>= 2.3.0`

For more details, see [GHSA-535w-7cp7-47q4](https://github.com/expressjs/multer/security/advisories/GHSA-535w-7cp7-47q4).

***

## [CVE-2026-15603 in morgan middleware (Medium)](#cve-2026-15603-in-morgan-middleware-medium)

**[morgan](https://www.npmjs.com/package/morgan) versions `< 1.12.0` are vulnerable to log forging through unescaped Unicode line separators**

morgan’s log-field escaping did not neutralize the Unicode line separator characters U+0085, U+2028, and U+2029. An unauthenticated remote client could place these characters in an attacker-controlled log token, for example a Basic auth username surfaced through the remote-user token, so that Unicode-aware downstream log processing split a single request log into multiple logical records. This is a log forging issue and a follow-up to CVE-2026-5078, which only addressed ASCII control characters. The fix in 1.12.0 extends the escaping set to cover these Unicode line separators.

**Affected versions**: `< 1.12.0`\
**Patched version**: `>= 1.12.0`

For more details, see [GHSA-jxfw-x594-9x9m](https://github.com/expressjs/morgan/security/advisories/GHSA-jxfw-x594-9x9m).

***

## [CVE-2026-77063 in multer middleware (Low)](#cve-2026-77063-in-multer-middleware-low)

**[multer](https://www.npmjs.com/package/multer) versions `< 2.3.0` are vulnerable to a file size limit bypass through an asynchronous `fileFilter` race condition**

When an application used an asynchronous `fileFilter` together with the `fileSize` limit, a race condition in multer’s file stream handling could allow a file that exceeds the configured size limit to bypass the size-limit rejection. The impact is limited because the underlying multipart parser still truncates the stream at the size limit, so this is a bypass of the limit rejection rather than uncontrolled resource consumption. The fix in 2.3.0 registers the size-limit handling before the asynchronous filter runs.

**Affected versions**: `< 2.3.0`\
**Patched version**: `>= 2.3.0`

For more details, see [GHSA-qvfw-j98x-7q72](https://github.com/expressjs/multer/security/advisories/GHSA-qvfw-j98x-7q72).

***

We recommend upgrading to the latest versions of hbs, multer, and morgan to secure your applications.

[security](/en/blog/2026-07-31-security-releases)

## [July 2026 Security Releases](/en/blog/2026-07-31-security-releases)

[Ulises GasconJuly 31, 2026](/en/blog/2026-07-31-security-releases)

### Interested in writing a post? Check out our guidelines to get started.

[Read the guidelines](/en/blog/write-post)

----
url: https://expressjs.com/en/resources/middleware/errorhandler
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/errorhandler.mdx)

# [errorhandler middleware](#overview)

v1.5.2[GitHub](https://github.com/expressjs/errorhandler)[Changelog](https://github.com/expressjs/errorhandler/releases)[npm](https://www.npmjs.com/package/errorhandler)

Development-only error handler middleware.

This middleware is only intended to be used in a development environment, as the *full error stack traces and internal details of any object passed to this module* will be sent back to the client when an error occurs.

When an object is provided to Express as an error, this module will display as much about this object as possible, and will do so by using content negotiation for the response between HTML, JSON, and plain text.

* When the object is a standard `Error` object, the string provided by the `stack` property will be returned in HTML/text responses.
* When the object is a non-`Error` object, the result of [util.inspect](https://nodejs.org/api/util.html#util_util_inspect_object_options) will be returned in HTML/text responses.
* For JSON responses, the result will be an object with all enumerable properties from the object in the response.

## [Install](#install)

This is a [Node.js](https://nodejs.org/en/) module available through the [npm registry](https://www.npmjs.com/). Installation is done using the [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):

Terminal window

```
npm install errorhandler
```

Terminal window

```
yarn add errorhandler
```

Terminal window

```
pnpm add errorhandler
```

Terminal window

```
bun add errorhandler
```

### Note

`errorhandler` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/errorhandler
```

Terminal window

```
yarn add --dev @types/errorhandler
```

Terminal window

```
pnpm add --save-dev @types/errorhandler
```

Terminal window

```
bun add --dev @types/errorhandler
```

## [API](#api)

```
var errorhandler = require('errorhandler');
```

### [errorhandler(options)](#errorhandleroptions)

Create new middleware to handle errors and respond with content negotiation.

#### [Options](#options)

Error handler accepts these properties in the options object.

##### [log](#log)

Provide a function to be called with the error and a string representation of the error. Can be used to write the error to any desired location, or set to `false` to only send the error back in the response. Called as `log(err, str, req, res)` where `err` is the `Error` object, `str` is a string representation of the error, `req` is the request object and `res` is the response object (note, this function is invoked *after* the response has been written).

The default value for this option is `true` unless `process.env.NODE_ENV === 'test'`.

Possible values:

* `true`: Log errors using `console.error(str)`.
* `false`: Only send the error back in the response.
* A function: pass the error to a function for handling.

## [Examples](#examples)

### [Simple example](#simple-example)

Basic example of adding this middleware as the error handler only in development with `connect` (`express` also can be used in this example).

```
var connect = require('connect');
var errorhandler = require('errorhandler');


var app = connect();


// assumes NODE_ENV is set by the user
if (process.env.NODE_ENV === 'development') {
  // only use in development
  app.use(errorhandler());
}
```

### [Custom output location](#custom-output-location)

Sometimes you may want to output the errors to a different location than STDERR during development, like a system notification, for example.

```
var connect = require('connect');
var errorhandler = require('errorhandler');
var notifier = require('node-notifier');


var app = connect();


// assumes NODE_ENV is set by the user
if (process.env.NODE_ENV === 'development') {
  // only use in development
  app.use(errorhandler({ log: errorNotification }));
}


function errorNotification(err, str, req) {
  var title = 'Error in ' + req.method + ' ' + req.url;


  notifier.notify({
    title: title,
    message: str,
  });
}
```

## [License](#license)

[MIT](https://github.com/expressjs/errorhandler/blob/HEAD/LICENSE)

----
url: https://expressjs.com/en/blog/2024-10-15-v5-release
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2024-10-15-v5-release)

announcements

# [Introducing Express v5: A New Era for the Node.js Framework](#overview)

Wes Todd, Express Technical CommitteeOctober 15, 2024

[](https://x.com/intent/tweet?text=Introducing%20Express%20v5%3A%20A%20New%20Era%20for%20the%20Node.js%20Framework\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-10-15-v5-release%2F)[](https://bsky.app/intent/compose?text=Introducing%20Express%20v5%3A%20A%20New%20Era%20for%20the%20Node.js%20Framework%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-10-15-v5-release%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-10-15-v5-release%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-10-15-v5-release%2F\&text=Introducing%20Express%20v5%3A%20A%20New%20Era%20for%20the%20Node.js%20Framework)[](https://wa.me/?text=Introducing%20Express%20v5%3A%20A%20New%20Era%20for%20the%20Node.js%20Framework%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2024-10-15-v5-release%2F)[](/feed.xml)

Ten years ago (July 2014) the [Express v5 release pull request](https://github.com/expressjs/express/pull/2237) was opened, and now at long last it’s been merged and published!

We want to recognize the work of all our contributors, especially [Doug Wilson](https://github.com/dougwilson), who spent the last ten years ensuring Express was the most stable project around. Without his contributions and those of many others, this release could not have happened.

Eight months ago we went public with a plan to move [Express forward](https://github.com/expressjs/discussions/issues/160). This plan included re-committing to the governance outlined years ago and adding more contributors to help kickstart progress. Many people may not realize that robust project governance is critical to the health of a large open-source project. We want to thank the [OpenJS Foundation Cross Project Council](https://github.com/openjs-foundation/cross-project-council/) and its members for helping us put together this plan.

## [So what about v5?](#so-what-about-v5)

This release is designed to be boring! That may sound odd, but we’ve intentionally kept it simple to unblock the ecosystem and enable more impactful changes in future releases. This is also about signaling to the Node.js ecosystem that Express is moving again. The focus of this release is on dropping old Node.js version support, addressing security concerns, and simplifying maintenance.

Before going into the changes in this release, let’s address why it was released v5 on the `next` dist-tag. As part of reviving the project, we started a [Security working group](https://github.com/expressjs/security-wg) and [security triage team](https://github.com/expressjs/security-wg?tab=readme-ov-file#security-triage-team) to address the growing needs around open source supply chain security. We undertook a security audit (more details to come on that) and uncovered some problems that needed to be addressed. Thus, in addition to the “normal” work done in public issues, we also did a lot of security work in private forks. This security work required orchestration when releasing, to ensure the code and CVE reports went out together. You can find a summary of the most recent vulnerabilities patched in [our security release notes](/en/blog/2024-09-29-security-releases/).

While we weren’t able to simultaneously release v5, this blog post, the changelog, and documentation, we felt it was most important to have a secure and stable release.

As soon as possible, we’ll provide more details on our long-term support (LTS) plans, including when the release will move from `next` to `latest`. For now, if you are uncomfortable being on the bleeding edge (even if it is a rather dull edge) then you should wait to upgrade until the release is tagged `latest`. That said, we look forward to working with you to address any bugs you encounter as you upgrade.

## [Breaking changes](#breaking-changes)

The v5 release has the minimum possible number of breaking changes, listed here in order of impact to applications.

* [So what about v5?](#so-what-about-v5)

* [Breaking changes](#breaking-changes)

  * [Ending support for old Node.js versions](#ending-support-for-old-nodejs-versions)

  * [Changes to path matching and regular expressions](#changes-to-path-matching-and-regular-expressions)

    * [No more regex](#no-more-regex)
    * [Splats, optional, and captures oh my](#splats-optional-and-captures-oh-my)
    * [Name everything](#name-everything)

  * [Promise support](#promise-support)

  * [Body parser changes](#body-parser-changes)

  * [Removing deprecated method signatures](#removing-deprecated-method-signatures)

* [Migration and security guidance](#migration-and-security-guidance)

* [Our work is just starting](#our-work-is-just-starting)

There are also a number of subtle changes: for details, see [Migrating to Express 5](/en/guide/migrating-5/).

### [Ending support for old Node.js versions](#ending-support-for-old-nodejs-versions)

Goodbye Node.js 0.10, hello Node 18 and up!

This release drops support for Node.js versions before v18. This is an important change because supporting old Node.js versions has been holding back many critical performance and maintainability changes. This change also enables more stable and maintainable continuous integration (CI), adopting new language and runtime features, and dropping dependencies that are no longer required.

We recognize that this might cause difficulty for some enterprises with older or “parked” applications, and because of this we are working on a [partnership with HeroDevs](/en/blog/2024-10-01-herodevs-partnership-announcement/) to offer “never-ending support” that will include critical security patches even after v4 enters end-of-life (more on these plans soon). That said, we strongly suggest that you update to modern Node.js versions as soon as possible.

### [Changes to path matching and regular expressions](#changes-to-path-matching-and-regular-expressions)

The v5 releases updates to `path-to-regexp@8.x` from `path-to-regexp@0.x`, which incorporates many years of changes. If you were using any of the 5.0.0-beta releases, a last-minute update which greatly changed the path semantics to [remove the possibility of any ReDoS attacks](https://blakeembrey.com/posts/2024-09-web-redos/). For more detailed changes, [see the `path-to-regexp` readme](https://github.com/pillarjs/path-to-regexp?tab=readme-ov-file#express--4x).

#### [No more regex](#no-more-regex)

This release no longer supports “sub-expression” regular expressions, for example `/:foo(\\d+)`. This is a commonly-used pattern, but we removed it for security reasons. Unfortunately, it’s easy to write a regular expression that has exponential time behavior when parsing input: The dreaded regular expression denial of service (ReDoS) attack. It’s very difficult to prevent this, but as a library that converts strings to regular expressions, we are on the hook for such security aspects.

*How to migrate:* The best approach to prevent ReDoS attacks is to use a robust input validation library. [There are many on `npm`](https://www.npmjs.com/search?q=validate%20express) depending on your needs. TC member Wes Todd maintains [a middleware-based “code first” OpenAPI library](https://www.npmjs.com/package/@wesleytodd/openapi) for this kind of thing.

#### [Splats, optional, and captures oh my](#splats-optional-and-captures-oh-my)

This release includes simplified patterns for common route patterns. With the removal of regular expression semantics comes other small but impactful changes to how you write your routes.

1. `:name?` becomes `{:name}`. Usage of `{}` for optional parts of your route means you can now do things like `/base{/:optional}/:required` and what parts are actually optional is much more explicit.
2. `*` becomes `*name`.
3. New reserved characters: `(`, `)`, `[`, `]`, `?`, `+`, & `!`. These have been reserved to leave room for future improvements and to prevent mistakes when migrating where those characters mean specific things in previous versions.

#### [Name everything](#name-everything)

This release no longer supports ordered numerical parameters.

In Express v4, you could get numerical parameters using regex capture groups (for example, `/user(s?)` => `req.params[0] === 's'`). Now all parameters must be named. Along with requiring a name, Express now supports all valid JavaScript identifiers or quoted (for example, `/:"this"`).

### [Promise support](#promise-support)

This one may be a bit contentious, but we “promise” we’re moving in the right direction. We added support for returned *rejected* promises from errors raised in middleware. This *does not include* calling `next` from returned *resolved* promises. There are a lot of edge cases in old Express apps that have expectations of `Promise` behavior, and before we can run we need to walk. For most folks, this means you can now write middleware like the following:

```
app.use(async (req, res, next) => {
  req.locals.user = await getUser(req);
  next();
});
```

Notice that this example uses `async/await` and the `getUser` call may throw an error (if, for example, the user doesn’t exist, the user database is down, and so on), but we still call `next` if it is successful. We don’t need to catch the error in line anymore if we want to rely on error-handling middleware instead because the router will now catch the rejected promise and treat that as calling `next(err)`.

NOTE: Best practice is to handle errors as close to the site as possible. So while this is now handled in the router, it’s best to catch the error in the middleware and handle it without relying on separate error-handling middleware.

### [Body parser changes](#body-parser-changes)

There are a number of `body-parser` changes:

* Add option to customize the urlencoded body depth with a default value of 32 as mitigation for [CVE-2024-45590](https://nvd.nist.gov/vuln/detail/CVE-2024-45590) ([technical details](https://github.com/expressjs/body-parser/commit/b2695c4450f06ba3b0ccf48d872a229bb41c9bce))
* Remove deprecated `bodyParser()` combination middleware
* `req.body` is no longer always initialized to `{}`
* `urlencoded` parser now defaults `extended` to false
* Added support for Brotli lossless data compression

### [Removing deprecated method signatures](#removing-deprecated-method-signatures)

Express v5 removes a number of deprecated method signatures, many of which were carried over from v3. Below are the changes you need to make:

* `res.redirect('back')` and `res.location('back')`: The magic string `'back'` is no longer supported. Use `req.get('Referrer') || '/'` explicitly instead.
* `res.send(status, body)` and `res.send(body, status)` signatures: Use `res.status(status).send(body)`.
* `res.send(status)` signature: Use `res.sendStatus(status)` for simple status responses, or `res.status(status).send()` for sending a status code with an optional body.
* `res.redirect(url, status)` signature: Use `res.redirect(status, url)`.
* `res.json(status, obj)` and `res.json(obj, status)` signatures: Use `res.status(status).json(obj)`.
* `res.jsonp(status, obj)` and `res.jsonp(obj, status)` signatures: Use `res.status(status).jsonp(obj)`.
* `app.param(fn)`: This method has been deprecated. Instead, access parameters directly via `req.params`, or use `req.body` or `req.query` as needed.
* `app.del('/', () => {})` method: Use `app.delete('/', () => {})` instead.
* `req.acceptsCharset`: Use `req.acceptsCharsets` (plural).
* `req.acceptsEncoding`: Use `req.acceptsEncodings` (plural).
* `req.acceptsLanguage`: Use `req.acceptsLanguages` (plural).
* `res.sendfile` method: Use `res.sendFile` instead.

As a framework, we aim to ensure that the API is as consistent as possible. We’ve removed these deprecated signatures to make the API more predictable and easier to use. By streamlining each method to use a single, consistent signature, we simplify the developer experience and reduce confusion.

## [Migration and security guidance](#migration-and-security-guidance)

For developers looking to migrate from v4 to v5, there’s a [detailed migration guide](/en/guide/migrating-5/) to help you navigate through the changes and ensure a smooth upgrade process.

Additionally, we’ve been working hard on a comprehensive [Threat Model](https://github.com/expressjs/security-wg/blob/main/docs/ThreatModel.md) that helps illustrate our philosophy of a “Fast, unopinionated, minimalist web framework for Node.js.” It provides critical insights into areas like user input validation and security practices that are essential for safe and secure usage of Express in your applications.

## [Our work is just starting](#our-work-is-just-starting)

We see the v5 release as a milestone toward an Express ecosystem that’s a stable and reliable tool for companies, governments, educators, and hobby projects. It is our commitment as the new stewards of the Express project to move the ecosystem forward with this goal in mind. If you want to support this work, which we do on a volunteer basis, please consider supporting the project and its maintainers via [our sponsorship opportunities](https://opencollective.com/express).

We have an [extensive working backlog](https://github.com/expressjs/discussions/issues/266) of tasks, PRs, and issues for Express and dependencies. Naturally, we expect developers will continue to report issues to add to this backlog and open PRs moving forward, and we’ll continue to collaborate with the community to triage and resolve them. We look forward to continuing to improve Express and making it useful for its users across the world.

----
url: https://expressjs.com/en/4x/starter/generator
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/4x/starter/generator.mdx)

# [Express application generator](#overview)

Use the application generator tool, `express-generator`, to quickly create an application skeleton.

You can run the application generator with the `npx` command (available in Node.js 8.2.0).

Terminal window

```
$ npx express-generator
```

For earlier Node versions, install the application generator as a global npm package and then launch it:

Terminal window

```
$ npm install -g express-generator
$ express
```

Display the command options with the `-h` option:

Terminal window

```
$ express -h


  Usage: express [options] [dir]


  Options:


    -h, --help          output usage information
        --version       output the version number
    -e, --ejs           add ejs engine support
        --hbs           add handlebars engine support
        --pug           add pug engine support
    -H, --hogan         add hogan.js engine support
        --no-view       generate without view engine
    -v, --view <engine> add view <engine> support (ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
    -c, --css <engine>  add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)
        --git           add .gitignore
    -f, --force         force on non-empty directory
```

For example, the following creates an Express app named *myapp*. The app will be created in a folder named *myapp* in the current working directory and the view engine will be set to [Pug](https://pugjs.org/ "Pug documentation"):

Terminal window

```
$ express --view=pug myapp


   create : myapp
   create : myapp/package.json
   create : myapp/app.js
   create : myapp/public
   create : myapp/public/javascripts
   create : myapp/public/images
   create : myapp/routes
   create : myapp/routes/index.js
   create : myapp/routes/users.js
   create : myapp/public/stylesheets
   create : myapp/public/stylesheets/style.css
   create : myapp/views
   create : myapp/views/index.pug
   create : myapp/views/layout.pug
   create : myapp/views/error.pug
   create : myapp/bin
   create : myapp/bin/www
```

Then install dependencies:

Terminal window

```
$ cd myapp
$ npm install
```

On MacOS or Linux, run the app with this command:

Terminal window

```
$ DEBUG=myapp:* npm start
```

On Windows Command Prompt, use this command:

Terminal window

```
> set DEBUG=myapp:* & npm start
```

On Windows PowerShell, use this command:

Terminal window

```
PS> $env:DEBUG='myapp:*'; npm start
```

Then, load `http://localhost:3000/` in your browser to access the app.

The generated app has the following directory structure:

Terminal window

```
.
├── app.js
├── bin
│   └── www
├── package.json
├── public
│   ├── images
│   ├── javascripts
│   └── stylesheets
│       └── style.css
├── routes
│   ├── index.js
│   └── users.js
└── views
    ├── error.pug
    ├── index.pug
    └── layout.pug


7 directories, 9 files
```

### Note

The app structure created by the generator is just one of many ways to structure Express apps. Feel free to use this structure or modify it to best suit your needs.

----
url: https://expressjs.com/en/5x/starter/faq
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/starter/faq.mdx)

# [FAQ](#overview)

## [How should I structure my application?](#how-should-i-structure-my-application)

There is no definitive answer to this question. The answer depends on the scale of your application and the team that is involved. To be as flexible as possible, Express makes no assumptions in terms of structure.

Routes and other application-specific logic can live in as many files as you wish, in any directory structure you prefer. View the following examples for inspiration:

* [Route listings](https://github.com/expressjs/express/blob/v5.2.1/examples/route-separation/index.js#L34-L49)
* [Route map](https://github.com/expressjs/express/blob/v5.2.1/examples/route-map/index.js#L55-L69)

```
app.use((req, res, next) => {
  res.status(404).send("Sorry can't find that!");
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use((req: Request, res: Response, next: NextFunction) => {
  res.status(404).send("Sorry can't find that!");
});
```

Add routes dynamically at runtime on an instance of `express.Router()` so the routes are not superseded by a middleware function.

## [How do I setup an error handler?](#how-do-i-setup-an-error-handler)

You define error-handling middleware in the same way as other middleware, except with four arguments instead of three; specifically with the signature `(err, req, res, next)`:

```
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

## [How do I render plain HTML?](#how-do-i-render-plain-html)

You don’t! There’s no need to “render” HTML with the `res.render()` function. If you have a specific file, use the `res.sendFile()` function. If you are serving many assets from a directory, use the `express.static()` middleware function.

## [What version of Node.js does Express require?](#what-version-of-nodejs-does-express-require)

* [Express 4.x](/en/4x/api/) requires Node.js 0.10 or higher.
* [Express 5.x](/en/5x/api/) requires Node.js 18 or higher.

----
url: https://expressjs.com/en/blog/2026-05-31-security-releases
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2026-05-31-security-releases)

security

# [May 2026 Security Releases](#overview)

Ulises GasconMay 31, 2026

[](https://x.com/intent/tweet?text=May%202026%20Security%20Releases\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-05-31-security-releases%2F)[](https://bsky.app/intent/compose?text=May%202026%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-05-31-security-releases%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-05-31-security-releases%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-05-31-security-releases%2F\&text=May%202026%20Security%20Releases)[](https://wa.me/?text=May%202026%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-05-31-security-releases%2F)[](/feed.xml)

The Express team has released [multiparty](https://www.npmjs.com/package/multiparty) 4.3.0, addressing three denial of service vulnerabilities in the multipart form parser.

### Warning

We recommend upgrading to the latest version of multiparty to secure your applications. If you have a `package-lock.json`, you can update the dependency by running:

Terminal window

```
npm update multiparty
```

The following vulnerabilities have been addressed:

* [CVE-2026-8159 in multiparty utility module (High)](#cve-2026-8159-in-multiparty-utility-module-high)
* [CVE-2026-8161 in multiparty utility module (High)](#cve-2026-8161-in-multiparty-utility-module-high)
* [CVE-2026-8162 in multiparty utility module (High)](#cve-2026-8162-in-multiparty-utility-module-high)

## [CVE-2026-8159 in multiparty utility module (High)](#cve-2026-8159-in-multiparty-utility-module-high)

**[multiparty](https://www.npmjs.com/package/multiparty) versions `<= 4.2.3` are vulnerable to regular expression denial of service via filename parsing**

A crafted multipart upload with a long header value can cause regex matching in the Content-Disposition filename parser to take seconds, blocking the Node.js event loop. Any service accepting multipart uploads via multiparty is affected. A small header of around 8 KB is sufficient to trigger the vulnerable backtracking.

**Affected versions**: `<= 4.2.3`\
**Patched version**: `>= 4.3.0`

For more details, see [GHSA-65x3-rw7q-gx94](https://github.com/pillarjs/multiparty/security/advisories/GHSA-65x3-rw7q-gx94).

## [CVE-2026-8161 in multiparty utility module (High)](#cve-2026-8161-in-multiparty-utility-module-high)

**[multiparty](https://www.npmjs.com/package/multiparty) versions `<= 4.2.3` are vulnerable to denial of service via prototype pollution leading to an uncaught exception**

A multipart upload with a field name that collides with an inherited Object.prototype property such as `__proto__`, `constructor`, or `toString` causes the parser to invoke `.push()` on the inherited prototype value rather than an array, throwing a TypeError that propagates as an uncaught exception and crashes the process. Any service accepting multipart uploads via multiparty is affected.

**Affected versions**: `<= 4.2.3`\
**Patched version**: `>= 4.3.0`

For more details, see [GHSA-qxch-whhj-8956](https://github.com/pillarjs/multiparty/security/advisories/GHSA-qxch-whhj-8956).

## [CVE-2026-8162 in multiparty utility module (High)](#cve-2026-8162-in-multiparty-utility-module-high)

**[multiparty](https://www.npmjs.com/package/multiparty) versions `<= 4.2.3` are vulnerable to denial of service via an uncaught exception in filename\* parameter parsing**

A multipart upload with a Content-Disposition header whose `filename*` parameter contains a malformed percent-encoding causes the parser to invoke `decodeURI` on the value without try/catch. The resulting URIError propagates as an uncaught exception and crashes the process. Any service accepting multipart uploads via multiparty is affected.

**Affected versions**: `<= 4.2.3`\
**Patched version**: `>= 4.3.0`

For more details, see [GHSA-xh3c-6gcq-g4rv](https://github.com/pillarjs/multiparty/security/advisories/GHSA-xh3c-6gcq-g4rv).

***

We recommend upgrading to the latest version of multiparty to secure your applications.

----
url: https://expressjs.com/en/advanced/security-updates
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/advanced/security-updates.mdx)

# [Security updates](#overview)

### Caution

Node.js vulnerabilities directly affect Express. Therefore, [keep a watch on Node.js vulnerabilities](https://nodejs.org/en/blog/vulnerability/) and make sure you are using the latest stable version of Node.js.

The list below enumerates the Express vulnerabilities that were fixed in the specified version update.

### Note

If you believe you have discovered a security vulnerability in Express, please see [Security Policies and Procedures](/en/resources/contributing/#security-policies-and-procedures).

## [4.x](#4x)

* 4.21.2
  * The dependency `path-to-regexp` has been updated to address a [vulnerability](https://github.com/pillarjs/path-to-regexp/security/advisories/GHSA-rhx6-c78j-4q9w).

* 4.21.1
  * The dependency `cookie` has been updated to address a [vulnerability](https://github.com/jshttp/cookie/security/advisories/GHSA-pxg6-pf52-xh8x), This may affect your application if you use `res.cookie`.

* 4.20.0

  * Fixed XSS vulnerability in `res.redirect` ([advisory](https://github.com/expressjs/express/security/advisories/GHSA-qw6h-vgh9-j6wx), [CVE-2024-43796](https://www.cve.org/CVERecord?id=CVE-2024-43796)).
  * The dependency `serve-static` has been updated to address a [vulnerability](https://github.com/advisories/GHSA-cm22-4g7w-348p).
  * The dependency `send` has been updated to address a [vulnerability](https://github.com/advisories/GHSA-m6fv-jmcg-4jfg).
  * The dependency `path-to-regexp` has been updated to address a [vulnerability](https://github.com/pillarjs/path-to-regexp/security/advisories/GHSA-9wv6-86v2-598j).
  * The dependency `body-parser` has been updated to address a [vulnerability](https://github.com/advisories/GHSA-qwcr-r2fm-qrc7), This may affect your application if you had url encoding activated.

* 4.19.0, 4.19.1
  * Fixed open redirect vulnerability in `res.location` and `res.redirect` ([advisory](https://github.com/expressjs/express/security/advisories/GHSA-rv95-896h-c2vc), [CVE-2024-29041](https://www.cve.org/CVERecord?id=CVE-2024-29041)).

* 4.17.3
  * The dependency `qs` has been updated to address a [vulnerability](https://github.com/advisories/GHSA-hrpp-h998-j3pp). This may affect your application if the following APIs are used: `req.query`, `req.body`, `req.param`.

* 4.16.0

  * The dependency `forwarded` has been updated to address a [vulnerability](https://github.com/advisories/GHSA-mpcf-4gmh-23w8). This may affect your application if the following APIs are used: `req.host`, `req.hostname`, `req.ip`, `req.ips`, `req.protocol`.
  * The dependency `mime` has been updated to address a [vulnerability](https://github.com/advisories/GHSA-wrvr-8mpx-r7pp), but this issue does not impact Express.
  * The dependency `send` has been updated to provide a protection against a [Node.js 8.5.0 vulnerability](https://nodejs.org/en/blog/vulnerability/september-2017-path-validation/). This only impacts running Express on the specific Node.js version 8.5.0.

* 4.15.5

  * The dependency `debug` has been updated to address a [vulnerability](https://security.snyk.io/vuln/npm:debug:20170905), but this issue does not impact Express.
  * The dependency `fresh` has been updated to address a [vulnerability](https://github.com/advisories/GHSA-9qj9-36jm-prpv). This will affect your application if the following APIs are used: `express.static`, `req.fresh`, `res.json`, `res.jsonp`, `res.send`, `res.sendfile` `res.sendFile`, `res.sendStatus`.

* 4.15.3
  * The dependency `ms` has been updated to address a [vulnerability](https://security.snyk.io/vuln/npm:ms:20170412). This may affect your application if untrusted string input is passed to the `maxAge` option in the following APIs: `express.static`, `res.sendfile`, and `res.sendFile`.

* 4.15.2
  * The dependency `qs` has been updated to address a [vulnerability](https://security.snyk.io/vuln/npm:qs:20170213), but this issue does not impact Express. Updating to 4.15.2 is a good practice, but not required to address the vulnerability.

* 4.11.1
  * Fixed root path disclosure vulnerability in `express.static`, `res.sendfile`, and `res.sendFile`

* 4.10.7
  * Fixed open redirect vulnerability in `express.static` ([advisory](https://github.com/advisories/GHSA-c3x7-gjmx-r2ff), [CVE-2015-1164](https://www.cve.org/CVERecord?id=CVE-2015-1164)).

* 4.8.8
  * Fixed directory traversal vulnerabilities in `express.static` ([advisory](https://github.com/advisories/GHSA-xwg4-93c6-3h42) , [CVE-2014-6394](https://www.cve.org/CVERecord?id=CVE-2014-6394)).

* 4.8.4
  * Node.js 0.10 can leak `fd`s in certain situations that affect `express.static` and `res.sendfile`. Malicious requests could cause `fd`s to leak and eventually lead to `EMFILE` errors and server unresponsiveness.

* 4.8.0

  * Sparse arrays that have extremely high indexes in the query string could cause the process to run out of memory and crash the server.
  * Extremely nested query string objects could cause the process to block and make the server unresponsive temporarily.

## [3.x](#3x)

### Warning

**Express 3.x IS END-OF-LIFE AND NO LONGER MAINTAINED**

Known and unknown security and performance issues in 3.x have not been addressed since the last update (1 August, 2015). It is highly recommended to use the latest version of Express.

If you are unable to upgrade past 3.x, please consider [Commercial Support Options](/en/support/#commercial-support-options).

* 3.19.1
  * Fixed root path disclosure vulnerability in `express.static`, `res.sendfile`, and `res.sendFile`

* 3.19.0
  * Fixed open redirect vulnerability in `express.static` ([advisory](https://github.com/advisories/GHSA-c3x7-gjmx-r2ff), [CVE-2015-1164](https://www.cve.org/CVERecord?id=CVE-2015-1164)).

* 3.16.10
  * Fixed directory traversal vulnerabilities in `express.static`.

* 3.16.6
  * Node.js 0.10 can leak `fd`s in certain situations that affect `express.static` and `res.sendfile`. Malicious requests could cause `fd`s to leak and eventually lead to `EMFILE` errors and server unresponsiveness.

* 3.16.0

  * Sparse arrays that have extremely high indexes in query string could cause the process to run out of memory and crash the server.
  * Extremely nested query string objects could cause the process to block and make the server unresponsive temporarily.

* 3.3.0
  * The 404 response of an unsupported method override attempt was susceptible to cross-site scripting attacks.

----
url: https://expressjs.com/en/advanced/best-practice-security
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/advanced/best-practice-security.mdx)

# [Production Best Practices: Security](#overview)

The term *“production”* refers to the stage in the software lifecycle when an application or API is generally available to its end-users or consumers. In contrast, in the *“development”* stage, you’re still actively writing and testing code, and the application is not open to external access. The corresponding system environments are known as *production* and *development* environments, respectively.

Development and production environments are usually set up differently and have vastly different requirements. What’s fine in development may not be acceptable in production. For example, in a development environment you may want verbose logging of errors for debugging, while the same behavior can become a security concern in a production environment. And in development, you don’t need to worry about scalability, reliability, and performance, while those concerns become critical in production.

### Note

If you believe you have discovered a security vulnerability in Express, please see [Security Policies and Procedures](/en/resources/contributing/#security-policies-and-procedures).

## [Don’t use deprecated or vulnerable versions of Express](#dont-use-deprecated-or-vulnerable-versions-of-express)

Express 2.x and 3.x are no longer maintained. Security and performance issues in these versions won’t be fixed. Do not use them! If you haven’t moved to version 4, follow the [migration guide](/en/guide/migrating-4/) or consider [Commercial Support Options](/en/support/#commercial-support-options).

Also ensure you are not using any of the vulnerable Express versions listed on the [Security updates page](/en/advanced/security-updates/). If you are, update to one of the stable releases, preferably the latest.

## [Use TLS](#use-tls)

If your app deals with or transmits sensitive data, use [Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security) (TLS) to secure the connection and the data. This technology encrypts data before it is sent from the client to the server, thus preventing some common (and easy) hacks. Although Ajax and POST requests might not be visibly obvious and seem “hidden” in browsers, their network traffic is vulnerable to [packet sniffing](https://en.wikipedia.org/wiki/Packet_analyzer) and [man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).

You may be familiar with Secure Socket Layer (SSL) encryption. [TLS is simply the next progression of SSL](https://learn.microsoft.com/en-us/windows/win32/secauthn/tls-versus-ssl). In other words, if you were using SSL before, consider upgrading to TLS. In general, we recommend Nginx to handle TLS. For a good reference to configure TLS on Nginx (and other servers), see [Recommended Server Configurations (TLSRef)](https://docs.tlsref.org/server-side-tls.html#recommended-configurations).

Also, a handy tool to get a free TLS certificate is [Let’s Encrypt](https://letsencrypt.org/about/), a free, automated, and open certificate authority (CA) provided by the [Internet Security Research Group (ISRG)](https://www.abetterinternet.org/).

## [Do not trust user input](#do-not-trust-user-input)

For web applications, one of the most critical security requirements is proper user input validation and handling. This comes in many forms and we will not cover all of them here. Ultimately, the responsibility for validating and correctly handling the types of user input your application accepts is yours.

### [Prevent open redirects](#prevent-open-redirects)

An example of potentially dangerous user input is an *open redirect*, where an application accepts a URL as user input (often in the URL query, for example `?url=https://example.com`) and uses `res.redirect` to set the `location` header and return a 3xx status.

An application must validate that it supports redirecting to the incoming URL to avoid sending users to malicious links such as phishing websites, among other risks.

Here is an example of checking URLs before using `res.redirect` or `res.location`:

```
app.use((req, res) => {
  try {
    if (new URL(req.query.url).host !== 'example.com') {
      return res.status(400).end(`Unsupported redirect to host: ${req.query.url}`);
    }
  } catch (e) {
    return res.status(400).end(`Invalid url: ${req.query.url}`);
  }
  res.redirect(req.query.url);
});
```

## [Use Helmet](#use-helmet)

[Helmet](https://helmet.js.org/) can help protect your app from some well-known web vulnerabilities by setting HTTP headers appropriately.

Helmet is a middleware function that sets security-related HTTP response headers. Helmet sets the following headers by default:

* `Content-Security-Policy`: A powerful allow-list of what can happen on your page which mitigates many attacks
* `Cross-Origin-Opener-Policy`: Helps process-isolate your page
* `Cross-Origin-Resource-Policy`: Blocks others from loading your resources cross-origin
* `Origin-Agent-Cluster`: Changes process isolation to be origin-based
* `Referrer-Policy`: Controls the [`Referer`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Referer) header
* `Strict-Transport-Security`: Tells browsers to prefer HTTPS
* `X-Content-Type-Options`: Avoids [MIME sniffing](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types#mime_sniffing)
* `X-DNS-Prefetch-Control`: Controls DNS prefetching
* `X-Download-Options`: Forces downloads to be saved (Internet Explorer only)
* `X-Frame-Options`: Legacy header that mitigates [Clickjacking](https://en.wikipedia.org/wiki/Clickjacking) attacks
* `X-Permitted-Cross-Domain-Policies`: Controls cross-domain behavior for Adobe products, like Acrobat
* `X-Powered-By`: Info about the web server. Removed because it could be used in simple attacks
* `X-XSS-Protection`: Legacy header that tries to mitigate [XSS attacks](https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting), but makes things worse, so Helmet disables it

Each header can be configured or disabled. To read more about it please go to [its documentation website](https://helmet.js.org/).

Install Helmet like any other module:

Terminal window

```
npm install helmet
```

Terminal window

```
yarn add helmet
```

Terminal window

```
pnpm add helmet
```

Terminal window

```
bun add helmet
```

Then to use it in your code:

index.cjs

```
// ...


const helmet = require('helmet');
app.use(helmet());


// ...
```

index.mjs

```
import helmet from 'helmet';


// ...


app.use(helmet());


// ...
```

## [Reduce fingerprinting](#reduce-fingerprinting)

It can help to provide an extra layer of security to reduce the ability of attackers to determine the software that a server uses, known as “fingerprinting.” Though not a security issue itself, reducing the ability to fingerprint an application improves its overall security posture. Server software can be fingerprinted by quirks in how it responds to specific requests, for example in the HTTP response headers.

By default, Express sends the `X-Powered-By` response header that you can disable using the `app.disable()` method:

```
app.disable('x-powered-by');
```

### Note

Disabling the `X-Powered-By header` does not prevent a sophisticated attacker from determining that an app is running Express. It may discourage a casual exploit, but there are other ways to determine an app is running Express.

Express also sends its own formatted “404 Not Found” messages and formatter error response messages. These can be changed by [adding your own not found handler](/en/5x/starter/faq/#how-do-i-handle-404-responses) and [writing your own error handler](/en/5x/guide/error-handling/#writing-error-handlers):

```
// last app.use calls right before app.listen():


// custom 404
app.use((req, res, next) => {
  res.status(404).send("Sorry can't find that!");
});


// custom error handler
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

## [Use cookies securely](#use-cookies-securely)

To ensure cookies don’t open your app to exploits, don’t use the default session cookie name and set cookie security options appropriately.

There are two main middleware cookie session modules:

* [express-session](https://www.npmjs.com/package/express-session) that replaces `express.session` middleware built-in to Express 3.x.
* [cookie-session](https://www.npmjs.com/package/cookie-session) that replaces `express.cookieSession` middleware built-in to Express 3.x.

The main difference between these two modules is how they save cookie session data. The [express-session](https://www.npmjs.com/package/express-session) middleware stores session data on the server; it only saves the session ID in the cookie itself, not session data. By default, it uses in-memory storage and is not designed for a production environment. In production, you’ll need to set up a scalable session-store; see the list of [compatible session stores](https://github.com/expressjs/session#compatible-session-stores).

In contrast, [cookie-session](https://www.npmjs.com/package/cookie-session) middleware implements cookie-backed storage: it serializes the entire session to the cookie, rather than just a session key. Only use it when session data is relatively small and easily encoded as primitive values (rather than objects). Although browsers are supposed to support at least 4096 bytes per cookie, to ensure you don’t exceed the limit, don’t exceed a size of 4093 bytes per domain. Also, be aware that the cookie data will be visible to the client, so if there is any reason to keep it secure or obscure, then `express-session` may be a better choice.

### [Don’t use the default session cookie name](#dont-use-the-default-session-cookie-name)

Using the default session cookie name can open your app to attacks. The security issue posed is similar to `X-Powered-By`: a potential attacker can use it to fingerprint the server and target attacks accordingly.

To avoid this problem, use generic cookie names; for example using [express-session](https://www.npmjs.com/package/express-session) middleware:

index.cjs

```
const session = require('express-session');
app.set('trust proxy', 1); // trust first proxy
app.use(
  session({
    secret: 's3Cur3',
    name: 'sessionId',
  })
);
```

index.mjs

```
import session from 'express-session';


app.set('trust proxy', 1); // trust first proxy
app.use(
  session({
    secret: 's3Cur3',
    name: 'sessionId',
  })
);
```

### [Set cookie security options](#set-cookie-security-options)

Set the following cookie options to enhance security:

* `secure` - Ensures the browser only sends the cookie over HTTPS.
* `httpOnly` - Ensures the cookie is sent only over HTTP(S), not client JavaScript, helping to protect against cross-site scripting attacks.
* `domain` - indicates the domain of the cookie; use it to compare against the domain of the server in which the URL is being requested. If they match, then check the path attribute next.
* `path` - indicates the path of the cookie; use it to compare against the request path. If this and domain match, then send the cookie in the request.
* `expires` - use to set expiration date for persistent cookies.

Here is an example using [cookie-session](https://www.npmjs.com/package/cookie-session) middleware:

index.cjs

```
const session = require('cookie-session');
const express = require('express');
const app = express();


const expiryDate = new Date(Date.now() + 60 * 60 * 1000); // 1 hour
app.use(
  session({
    name: 'session',
    keys: ['key1', 'key2'],
    cookie: {
      secure: true,
      httpOnly: true,
      domain: 'example.com',
      path: 'foo/bar',
      expires: expiryDate,
    },
  })
);
```

index.mjs

```
import session from 'cookie-session';
import express from 'express';


const app = express();


const expiryDate = new Date(Date.now() + 60 * 60 * 1000); // 1 hour
app.use(
  session({
    name: 'session',
    keys: ['key1', 'key2'],
    cookie: {
      secure: true,
      httpOnly: true,
      domain: 'example.com',
      path: 'foo/bar',
      expires: expiryDate,
    },
  })
);
```

## [Prevent brute-force attacks against authorization](#prevent-brute-force-attacks-against-authorization)

Make sure login endpoints are protected to make private data more secure.

A simple and powerful technique is to block authorization attempts using two metrics:

1. The number of consecutive failed attempts by the same user name and IP address.
2. The number of failed attempts from an IP address over some long period of time. For example, block an IP address if it makes 100 failed attempts in one day.

[rate-limiter-flexible](https://github.com/animir/node-rate-limiter-flexible) package provides tools to make this technique easy and fast. You can find [an example of brute-force protection in the documentation](https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#login-endpoint-protection)

## [Ensure your dependencies are secure](#ensure-your-dependencies-are-secure)

Using npm to manage your application’s dependencies is powerful and convenient. But the packages that you use may contain critical security vulnerabilities that could also affect your application. The security of your app is only as strong as the “weakest link” in your dependencies.

Since npm\@6, npm automatically reviews every install request. Also, you can use `npm audit` to analyze your dependency tree.

Terminal window

```
$ npm audit
```

If you want to stay more secure, consider [Snyk](https://snyk.io/).

Snyk offers both a [command-line tool](https://www.npmjs.com/package/snyk) and a [GitHub integration](https://docs.snyk.io/discover-snyk/getting-started) that checks your application against [Snyk’s open source vulnerability database](https://security.snyk.io/) for any known vulnerabilities in your dependencies. Install the CLI as follows:

Terminal window

```
$ npm install -g snyk
$ cd your-app
```

Use this command to test your application for vulnerabilities:

Terminal window

```
$ snyk test
```

### [Avoid other known vulnerabilities](#avoid-other-known-vulnerabilities)

Keep an eye out for [GitHub Advisory Database](https://github.com/advisories?query=ecosystem%3Anpm) or [Snyk](https://security.snyk.io/vuln/npm) advisories that may affect Express or other modules that your app uses. In general, these databases are excellent resources for knowledge and tools about Node security.

Finally, Express apps—like any other web apps—can be vulnerable to a variety of web-based attacks. Familiarize yourself with known [web vulnerabilities](https://owasp.org/www-project-top-ten/) and take precautions to avoid them.

## [Additional considerations](#additional-considerations)

Here are some further recommendations from the excellent [Node.js Security Checklist](https://blog.risingstack.com/node-js-security-checklist/). Refer to that blog post for all the details on these recommendations:

* Always filter and sanitize user input to protect against cross-site scripting (XSS) and command injection attacks.
* Defend against SQL injection attacks by using parameterized queries or prepared statements.
* Use the open-source [sqlmap](https://sqlmap.org/) tool to detect SQL injection vulnerabilities in your app.
* Use the [nmap](https://nmap.org/) and [sslyze](https://github.com/nabla-c0d3/sslyze) tools to test the configuration of your SSL ciphers, keys, and renegotiation as well as the validity of your certificate.
* Use [safe-regex](https://www.npmjs.com/package/safe-regex) to ensure your regular expressions are not susceptible to [regular expression denial of service](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS) attacks.

----
url: https://expressjs.com/en/5x/starter/installing
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/docs/en/5x/starter/installing.mdx)

# [Installing](#overview)

Before you begin, make sure you have [Node.js](https://nodejs.org/) 18 or higher installed. Then, create a directory for your application and navigate into it.

Terminal window

```
mkdir myapp
cd myapp
```

Use the `npm init` command to create a `package.json` file for your application. For more information on how `package.json` works, see [Specifics of npm’s package.json handling](https://docs.npmjs.com/files/package.json).

Terminal window

```
npm init
```

Terminal window

```
yarn init
```

Terminal window

```
pnpm init
```

Terminal window

```
bun init
```

This command prompts you for a number of things, such as the name and version of your application. For now, you can simply hit RETURN to accept the defaults for most of them, with the following exception:

```
entry point: (index.js)
```

Enter `app.js`, or whatever you want the name of the main file to be. If you want it to be `index.js`, hit RETURN to accept the suggested default file name.

Now, install Express in the `myapp` directory and save it in the dependencies list. For example:

Terminal window

```
npm install express
```

Terminal window

```
yarn add express
```

Terminal window

```
pnpm add express
```

Terminal window

```
bun add express
```

To install Express temporarily and not add it to the dependencies list:

Terminal window

```
npm install express --no-save
```

Terminal window

```
bun add express --no-save
```

## [TypeScript](#typescript)

Express is written in JavaScript and does not bundle its own type definitions. To use it with TypeScript, install TypeScript together with the community-maintained types for Express and Node.js (from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped)) as development dependencies:

Terminal window

```
npm install --save-dev typescript @types/express @types/node
```

Terminal window

```
yarn add --dev typescript @types/express @types/node
```

Terminal window

```
pnpm add --save-dev typescript @types/express @types/node
```

Terminal window

```
bun add --dev typescript @types/express @types/node
```

### Warning

Some middleware does not bundle its own type definitions. If you add an official middleware package that TypeScript reports as untyped, also install its types from DefinitelyTyped as a dev dependency, for example `@types/cors` alongside `cors`.

Add a `tsconfig.json`. These options mirror how Node.js runs TypeScript and make the compiler reject non-erasable syntax (such as `enum`s, namespaces, and parameter properties) that Node cannot strip:

tsconfig.json

```
{
  "compilerOptions": {
    "target": "esnext",
    "module": "nodenext",
    "rewriteRelativeImportExtensions": true,
    "erasableSyntaxOnly": true,
    "verbatimModuleSyntax": true,
    "noEmit": true,
    "strict": true,
    "skipLibCheck": true
  }
}
```

Write your application in TypeScript, annotating the [request](/en/5x/api/request/) and [response](/en/5x/api/response/) objects:

src/app.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


app.get('/', (req: Request, res: Response) => {
  res.send('Hello World!');
});


app.listen(3000);
```

You do not need to annotate everything. When you pass a handler directly to a route method or to `app.use()`, Express infers the types of `req`, `res`, and `next`, and it infers route parameters from the path, so `req.params.id` is a `string` in `app.get('/users/:id', ...)`. Add explicit types only where TypeScript has no context to infer from: error-handling middleware, whose `(err, req, res, next)` signature is not inferred, and handlers you define separately from the route. In those cases, annotate the parameters or type the whole function as `RequestHandler` or `ErrorRequestHandler`.

Run the file directly with Node.js, which strips the TypeScript types and runs the result without a build step:

Terminal window

```
node src/app.ts
```

### Note

Running `.ts` files directly requires Node.js >= 22.18.0 (or >= 23.6.0 on the v23 line) and TypeScript >= 5.8. Node strips the types but does not type-check them, so run `npx tsc` to type-check your project. For more details, see the Node.js guide on [running TypeScript natively](https://nodejs.org/learn/typescript/run-natively).

----
url: https://expressjs.com/en/blog/2025-05-16-express-cleanup-legacy-packages
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2025-05-16-express-cleanup-legacy-packages)

announcements

# [Spring Cleaning in Express.js: Deprecations and the Path Ahead](#overview)

Express Technical CommitteeMay 16, 2025

[](https://x.com/intent/tweet?text=Spring%20Cleaning%20in%20Express.js%3A%20Deprecations%20and%20the%20Path%20Ahead\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-05-16-express-cleanup-legacy-packages%2F)[](https://bsky.app/intent/compose?text=Spring%20Cleaning%20in%20Express.js%3A%20Deprecations%20and%20the%20Path%20Ahead%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-05-16-express-cleanup-legacy-packages%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-05-16-express-cleanup-legacy-packages%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-05-16-express-cleanup-legacy-packages%2F\&text=Spring%20Cleaning%20in%20Express.js%3A%20Deprecations%20and%20the%20Path%20Ahead)[](https://wa.me/?text=Spring%20Cleaning%20in%20Express.js%3A%20Deprecations%20and%20the%20Path%20Ahead%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-05-16-express-cleanup-legacy-packages%2F)[](/feed.xml)

As Express.js continues to power web applications across the world, it’s important that we maintain a clean, reliable, and modern codebase. In that spirit, we’ve done a bit of spring cleaning.

Over the past few weeks, we’ve evaluated legacy packages within the Express.js ecosystem — some of which have become outdated, unmaintained, or misaligned with modern best practices. As a result, we’ve officially deprecated several of them.

## [🚨 Packages Deprecated](#-packages-deprecated)

Here are the key packages we’ve deprecated:

* [`csurf`](https://www.npmjs.com/package/csurf): A CSRF middleware that’s long been difficult to maintain and is better handled today through frameworks or custom implementations that align with your architecture.
* [`connect-multiparty`](https://www.npmjs.com/package/connect-multiparty): A multipart form-data parser that relies on deprecated libraries and hasn’t aged well.
* [`path-match`](https://www.npmjs.com/package/path-match): A route-matching utility that has been superseded by more modern and maintained alternatives.

Each of these packages was originally created to solve real problems—but time has moved on, and the ecosystem has evolved.

## [🤔 Why This Matters](#-why-this-matters)

Maintaining deprecated or inactive dependencies introduces technical debt and security risk. By formally deprecating these packages, we:

* Encourage developers to adopt better-maintained and more secure solutions.
* Reduce confusion around which tools are actively supported by Express.
* Focus our efforts on modernizing the core and surrounding ecosystem.

## [🗂️ What You Should Do](#️-what-you-should-do)

If your application depends on any of these packages, now is a great time to look for alternatives. For instance:

* Consider finding a modern CSRF protection strategy on [npm](https://www.npmjs.com/search?q=csurf) that aligns with your specific needs.
* Use up-to-date multipart parsers like [`multer`](https://www.npmjs.com/package/multer).
* Replace path-match logic with standard [`path-to-regexp`](https://www.npmjs.com/package/path-to-regexp).

## [📘 What’s Next](#-whats-next)

We’re not stopping here. This cleanup is part of a broader effort to streamline Express.js, prepare for the future, and clarify what is and isn’t officially supported.

👉 A full discussion of these changes can be found [expressjs/discussions#134](https://github.com/expressjs/discussions/issues/134).

📢 Stay tuned—we’ll continue to post updates and insights as we modernize the Express ecosystem.

💚Thanks to the community for your continued trust and support.

## More from Express

[announcements](/en/blog/2026-05-18-a-new-look-for-express)

## [A New Look for Express](/en/blog/2026-05-18-a-new-look-for-express)

[Sebastian BeltranMay 18, 2026](/en/blog/2026-05-18-a-new-look-for-express)

----
url: https://expressjs.com/en/4x/api/router/
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/4x/api/router/index.mdx)

# [Router](#overview)

A `router` object is an instance of middleware and routes. You can think of it as a “mini-application,” capable only of performing middleware and routing functions. Every Express application has a built-in app router.

A router behaves like middleware itself, so you can use it as an argument to [app.use()](/en/4x/api/application/#appuse) or as the argument to another router’s [use()](#routeruse) method.

The top-level `express` object has a [Router()](/en/4x/api/express/#expressrouter) method that creates a new `router` object.

Once you’ve created a router object, you can add middleware and HTTP method routes (such as `get`, `put`, `post`, and so on) to it just like an application. For example:

```
// invoked for any requests passed to this router
router.use(function (req, res, next) {
  // .. some logic here .. like any other middleware
  next();
});


// will handle any request that ends in /events
// depends on where the router is "use()'d"
router.get('/events', function (req, res, next) {
  // ..
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


// invoked for any requests passed to this router
router.use(function (req: Request, res: Response, next: NextFunction) {
  // .. some logic here .. like any other middleware
  next();
});


// will handle any request that ends in /events
// depends on where the router is "use()'d"
router.get('/events', function (req: Request, res: Response, next: NextFunction) {
  // ..
});
```

You can then use a router for a particular root URL in this way separating your routes into files or even mini-apps.

```
// only requests to /calendar/* will be sent to our "router"
app.use('/calendar', router);
```

```
var express = require('express');
var router = express.Router({ caseSensitive: true, strict: true });


router.get('/events', function (req, res) {
  res.send('events');
});


// mount the router on an app
app.use('/calendar', router);
```

index.mjs

```
import express from 'express';


const router = express.Router({ caseSensitive: true, strict: true });


router.get('/events', (req, res) => {
  res.send('events');
});


// mount the router on an app
app.use('/calendar', router);
```

index.ts

```
import express, { type Request, type Response } from 'express';


const router = express.Router({ caseSensitive: true, strict: true });


router.get('/events', (req: Request, res: Response) => {
  res.send('events');
});


// mount the router on an app
app.use('/calendar', router);
```

```
router.all('*', requireAuthentication, loadUser);
```

Or the equivalent:

```
router.all('*', requireAuthentication);
router.all('*', loadUser);
```

Another example of this is white-listed “global” functionality. Here the example is much like before, but it only restricts paths prefixed with “/api”:

```
router.all('/api/*', requireAuthentication);
```

`router.query()` routes HTTP `QUERY` requests, mirroring [`app.query()`](/en/4x/api/application/#appquery). The `QUERY` method is gated by the runtime and requires Node.js `>=20.19.3 <21 || >=22.2.0`.

You can provide multiple callbacks, and all are treated equally, and behave just like middleware, except that these callbacks may invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to perform pre-conditions on a route then pass control to subsequent routes when there is no reason to proceed with the route matched.

The following snippet illustrates the most simple route definition possible. Express translates the path strings to regular expressions, used internally to match incoming requests. Query strings are *not* considered when performing these matches, for example “GET /” would match the following route, as would “GET /?name=tobi”.

```
router.get('/', function (req, res) {
  res.send('hello world');
});
```

```
import { type Request, type Response } from 'express';


router.get('/', function (req: Request, res: Response) {
  res.send('hello world');
});
```

You can also use regular expressions—useful if you have very specific constraints, for example the following would match “GET /commits/71dbb9c” as well as “GET /commits/71dbb9c..4c084f9”.

```
router.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/, function (req, res) {
  var from = req.params[0];
  var to = req.params[1] || 'HEAD';
  res.send('commit range ' + from + '..' + to);
});
```

```
import { type Request, type Response } from 'express';


router.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/, function (req: Request, res: Response) {
  const from = req.params[0];
  const to = req.params[1] || 'HEAD';
  res.send('commit range ' + from + '..' + to);
});
```

Adds callback triggers to route parameters, where `name` is the name of the parameter and `callback` is the callback function. Although `name` is technically optional, using this method without it is deprecated starting with Express v4.11.0 (see below).

```
router.param('user', function (req, res, next, id) {
  // try to get the user details from the User model and attach it to the request object
  User.find(id, function (err, user) {
    if (err) {
      next(err);
    } else if (user) {
      req.user = user;
      next();
    } else {
      next(new Error('failed to load user'));
    }
  });
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


router.param('user', function (req: Request, res: Response, next: NextFunction, id) {
  // try to get the user details from the User model and attach it to the request object
  User.find(id, function (err, user) {
    if (err) {
      next(err);
    } else if (user) {
      req.user = user;
      next();
    } else {
      next(new Error('failed to load user'));
    }
  });
});
```

Param callback functions are local to the router on which they are defined. They are not inherited by mounted apps or routers, nor are they triggered for route parameters inherited from parent routers. Hence, param callbacks defined on `router` will be triggered only by route parameters defined on `router` routes.

A param callback will be called only once in a request-response cycle, even if the parameter is matched in multiple routes, as shown in the following examples.

```
router.param('id', function (req, res, next, id) {
  console.log('CALLED ONLY ONCE');
  next();
});


router.get('/user/:id', function (req, res, next) {
  console.log('although this matches');
  next();
});


router.get('/user/:id', function (req, res) {
  console.log('and this matches too');
  res.end();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


router.param('id', function (req: Request, res: Response, next: NextFunction, id) {
  console.log('CALLED ONLY ONCE');
  next();
});


router.get('/user/:id', function (req: Request, res: Response, next: NextFunction) {
  console.log('although this matches');
  next();
});


router.get('/user/:id', function (req: Request, res: Response) {
  console.log('and this matches too');
  res.end();
});
```

On `GET /user/42`, the following is printed:

```
CALLED ONLY ONCE
although this matches
and this matches too
```

### Caution

The following section describes `router.param(callback)`, which is deprecated as of v4.11.0.

The behavior of the `router.param(name, callback)` method can be altered entirely by passing only a function to `router.param()`. This function is a custom implementation of how `router.param(name, callback)` should behave - it accepts two parameters and must return a middleware.

The first parameter of this function is the name of the URL parameter that should be captured, the second parameter can be any JavaScript object which might be used for returning the middleware implementation.

The middleware returned by the function decides the behavior of what happens when a URL parameter is captured.

In this example, the `router.param(name, callback)` signature is modified to `router.param(name, accessId)`. Instead of accepting a name and a callback, `router.param()` will now accept a name and a number.

index.cjs

```
var express = require('express');
var app = express();
var router = express.Router();


// customizing the behavior of router.param()
router.param(function (param, option) {
  return function (req, res, next, val) {
    if (val === option) {
      next();
    } else {
      res.sendStatus(403);
    }
  };
});


// using the customized router.param()
router.param('id', '1337');


// route to trigger the capture
router.get('/user/:id', function (req, res) {
  res.send('OK');
});


app.use(router);


app.listen(3000, function () {
  console.log('Ready');
});
```

index.mjs

```
import express from 'express';


const app = express();
const router = express.Router();


// customizing the behavior of router.param()
router.param(function (param, option) {
  return function (req, res, next, val) {
    if (val === option) {
      next();
    } else {
      res.sendStatus(403);
    }
  };
});


// using the customized router.param()
router.param('id', '1337');


// route to trigger the capture
router.get('/user/:id', function (req, res) {
  res.send('OK');
});


app.use(router);


app.listen(3000, function () {
  console.log('Ready');
});
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();
const router = express.Router();


// customizing the behavior of router.param()
router.param(function (param, option) {
  return function (req: Request, res: Response, next: NextFunction, val) {
    if (val === option) {
      next();
    } else {
      res.sendStatus(403);
    }
  };
});


// using the customized router.param()
router.param('id', '1337');


// route to trigger the capture
router.get('/user/:id', function (req: Request, res: Response) {
  res.send('OK');
});


app.use(router);


app.listen(3000, function () {
  console.log('Ready');
});
```

In this example, the `router.param(name, callback)` signature remains the same, but instead of a middleware callback, a custom data type checking function has been defined to validate the data type of the user id.

```
router.param(function (param, validator) {
  return function (req, res, next, val) {
    if (validator(val)) {
      next();
    } else {
      res.sendStatus(403);
    }
  };
});


router.param('id', function (candidate) {
  return !isNaN(parseFloat(candidate)) && isFinite(candidate);
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


router.param(function (param, validator) {
  return function (req: Request, res: Response, next: NextFunction, val) {
    if (validator(val)) {
      next();
    } else {
      res.sendStatus(403);
    }
  };
});


router.param('id', function (candidate) {
  return !isNaN(parseFloat(candidate)) && isFinite(candidate);
});
```

```
var router = express.Router();


router.param('user_id', function (req, res, next, id) {
  // sample user, would actually fetch from DB, etc...
  req.user = {
    id: id,
    name: 'TJ',
  };
  next();
});


router
  .route('/users/:user_id')
  .all(function (req, res, next) {
    // runs for all HTTP verbs first
    // think of it as route specific middleware!
    next();
  })
  .get(function (req, res, next) {
    res.json(req.user);
  })
  .put(function (req, res, next) {
    // just an example of maybe updating the user
    req.user.name = req.params.name;
    // save user ... etc
    res.json(req.user);
  })
  .post(function (req, res, next) {
    next(new Error('not implemented'));
  })
  .delete(function (req, res, next) {
    next(new Error('not implemented'));
  });
```

```
import { type Request, type Response, type NextFunction } from 'express';


const router = express.Router();


router.param('user_id', function (req: Request, res: Response, next: NextFunction, id) {
  // sample user, would actually fetch from DB, etc...
  req.user = {
    id: id,
    name: 'TJ',
  };
  next();
});


router
  .route('/users/:user_id')
  .all(function (req: Request, res: Response, next: NextFunction) {
    // runs for all HTTP verbs first
    // think of it as route specific middleware!
    next();
  })
  .get(function (req: Request, res: Response, next: NextFunction) {
    res.json(req.user);
  })
  .put(function (req: Request, res: Response, next: NextFunction) {
    // just an example of maybe updating the user
    req.user.name = req.params.name;
    // save user ... etc
    res.json(req.user);
  })
  .post(function (req: Request, res: Response, next: NextFunction) {
    next(new Error('not implemented'));
  })
  .delete(function (req: Request, res: Response, next: NextFunction) {
    next(new Error('not implemented'));
  });
```

This method is similar to [app.use()](/en/4x/api/application/#appuse). A simple example and use case is described below. See [app.use()](/en/4x/api/application/#appuse) for more information.

Middleware is like a plumbing pipe: requests start at the first middleware function defined and work their way “down” the middleware stack processing for each path they match.

index.cjs

```
var express = require('express');
var app = express();
var router = express.Router();


// simple logger for this router's requests
// all requests to this router will first hit this middleware
router.use(function (req, res, next) {
  console.log('%s %s %s', req.method, req.url, req.path);
  next();
});


// this will only be invoked if the path starts with /bar from the mount point
router.use('/bar', function (req, res, next) {
  // ... maybe some additional /bar logging ...
  next();
});


// always invoked
router.use(function (req, res, next) {
  res.send('Hello World');
});


app.use('/foo', router);


app.listen(3000);
```

index.mjs

```
import express from 'express';


const app = express();
const router = express.Router();


// simple logger for this router's requests
// all requests to this router will first hit this middleware
router.use(function (req, res, next) {
  console.log('%s %s %s', req.method, req.url, req.path);
  next();
});


// this will only be invoked if the path starts with /bar from the mount point
router.use('/bar', function (req, res, next) {
  // ... maybe some additional /bar logging ...
  next();
});


// always invoked
router.use(function (req, res, next) {
  res.send('Hello World');
});


app.use('/foo', router);


app.listen(3000);
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();
const router = express.Router();


// simple logger for this router's requests
// all requests to this router will first hit this middleware
router.use(function (req: Request, res: Response, next: NextFunction) {
  console.log('%s %s %s', req.method, req.url, req.path);
  next();
});


// this will only be invoked if the path starts with /bar from the mount point
router.use('/bar', function (req: Request, res: Response, next: NextFunction) {
  // ... maybe some additional /bar logging ...
  next();
});


// always invoked
router.use(function (req: Request, res: Response, next: NextFunction) {
  res.send('Hello World');
});


app.use('/foo', router);


app.listen(3000);
```

The “mount” path is stripped and is *not* visible to the middleware function. The main effect of this feature is that a mounted middleware function may operate without code changes regardless of its “prefix” pathname.

The order in which you define middleware with `router.use()` is very important. They are invoked sequentially, thus the order defines middleware precedence. For example, usually a logger is the very first middleware you would use, so that every request gets logged.

index.cjs

```
var logger = require('morgan');
var path = require('path');


router.use(logger());
router.use(express.static(path.join(__dirname, 'public')));
router.use(function (req, res) {
  res.send('Hello');
});
```

index.mjs

```
import logger from 'morgan';
import path from 'path';


router.use(logger());
router.use(express.static(path.join(__dirname, 'public')));
router.use(function (req, res) {
  res.send('Hello');
});
```

index.ts

```
import logger from 'morgan';
import path from 'path';
import { type Request, type Response } from 'express';


router.use(logger());
router.use(express.static(path.join(__dirname, 'public')));
router.use(function (req: Request, res: Response) {
  res.send('Hello');
});
```

Now suppose you wanted to ignore logging requests for static files, but to continue logging routes and middleware defined after `logger()`. You would simply move the call to `express.static()` to the top, before adding the logger middleware:

```
router.use(express.static(path.join(__dirname, 'public')));
router.use(logger());
router.use(function (req, res) {
  res.send('Hello');
});
```

```
import { type Request, type Response } from 'express';


router.use(express.static(path.join(__dirname, 'public')));
router.use(logger());
router.use(function (req: Request, res: Response) {
  res.send('Hello');
});
```

Another example is serving files from multiple directories, giving precedence to ”./public” over the others:

```
router.use(express.static(path.join(__dirname, 'public')));
router.use(express.static(path.join(__dirname, 'files')));
router.use(express.static(path.join(__dirname, 'uploads')));
```

The `router.use()` method also supports named parameters so that your mount points for other routers can benefit from preloading using named parameters.

### Note

Although these middleware functions are added via a particular router, *when* they run is defined by the path they are attached to (not the router). Therefore, middleware added via one router may run for other routers if its routes match.

For example, this code shows two different routers mounted on the same path:

```
var authRouter = express.Router();
var openRouter = express.Router();


authRouter.use(require('./authenticate').basic(usersdb));


authRouter.get('/:user_id/edit', function (req, res, next) {
  // ... Edit user UI ...
});
openRouter.get('/', function (req, res, next) {
  // ... List users ...
});
openRouter.get('/:user_id', function (req, res, next) {
  // ... View user ...
});


app.use('/users', authRouter);
app.use('/users', openRouter);
```

```
import { type Request, type Response, type NextFunction } from 'express';
import { basic } from './authenticate';


const authRouter = express.Router();
const openRouter = express.Router();


authRouter.use(basic(usersdb));


authRouter.get('/:user_id/edit', function (req: Request, res: Response, next: NextFunction) {
  // ... Edit user UI ...
});
openRouter.get('/', function (req: Request, res: Response, next: NextFunction) {
  // ... List users ...
});
openRouter.get('/:user_id', function (req: Request, res: Response, next: NextFunction) {
  // ... View user ...
});


app.use('/users', authRouter);
app.use('/users', openRouter);
```

Even though the authentication middleware was added via the `authRouter` it will run on the routes defined by the `openRouter` as well since both routers were mounted on `/users`. To avoid this behavior, use different paths for each router.

----
url: https://expressjs.com/en/3x/api/request
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/3x/api/request/index.mdx)

# [Request](#overview)

The `req` object is an enhanced version of Node’s own request object and supports all [built-in fields and methods](https://nodejs.org/api/http.html#class-httpincomingmessage).

## [Properties](#properties)

The `req` object contains a number of properties that provide information about the HTTP request, such as headers, query parameters, and more.

### [req.accepted](#reqaccepted)

Return an array of Accepted media types ordered from highest quality to lowest.

```
[
  { "value": "application/json", "quality": 1, "type": "application", "subtype": "json" },
  { "value": "text/html", "quality": 0.5, "type": "text", "subtype": "html" }
]
```

### [req.acceptedCharsets](#reqacceptedcharsets)

Return an array of Accepted charsets ordered from highest quality to lowest.

```
Accept-Charset: iso-8859-5;q=.2, unicode-1-1;q=0.8
// => ['unicode-1-1', 'iso-8859-5']
```

### [req.acceptedLanguages](#reqacceptedlanguages)

Return an array of Accepted languages ordered from highest quality to lowest.

```
Accept-Language: en;q=.5, en-us
// => ['en-us', 'en']
```

### [req.body](#reqbody)

This property is an object containing the parsed request body. This feature is provided by the `bodyParser()` middleware, though other body parsing middleware may follow this convention as well. This property defaults to `{}` when `bodyParser()` is used.

index.js

```
// POST user[name]=tobi&user[email]=tobi@learnboost.com
console.log(req.body.user.name);
// => "tobi"


console.log(req.body.user.email);
// => "tobi@learnboost.com"


// POST { "name": "tobi" }
console.log(req.body.name);
// => "tobi"
```

### [req.cookies](#reqcookies)

This object requires the `cookieParser()` middleware for use. It contains cookies sent by the user-agent. If no cookies are sent, it defaults to `{}`.

index.js

```
// Cookie: name=tj
console.log(req.cookies.name);
// => "tj"
```

### [req.files](#reqfiles)

This property is an object of the files uploaded. This feature is provided by the `bodyParser()` middleware, though other body parsing middleware may follow this convention as well. This property defaults to `{}` when `bodyParser()` is used.

For example if a **file** field was named “image”, and a file was uploaded, `req.files.image` would contain the following `File` object:

```
{ size: 74643,
  path: '/tmp/8ef9c52abe857867fd0a4e9a819d1876',
  name: 'edge.png',
  type: 'image/png',
  hash: false,
  lastModifiedDate: Thu Aug 09 2012 20:07:51 GMT-0700 (PDT),
  _writeStream:
   { path: '/tmp/8ef9c52abe857867fd0a4e9a819d1876',
     fd: 13,
     writable: false,
     flags: 'w',
     encoding: 'binary',
     mode: 438,
     bytesWritten: 74643,
     busy: false,
     _queue: [],
     _open: [Function],
     drainable: true },
  length: [Getter],
  filename: [Getter],
  mime: [Getter] }
```

The `bodyParser()` middleware utilizes the

[node-formidable](https://github.com/felixge/node-formidable) module internally, and accepts the same options. An example of this is the `keepExtensions` formidable option, defaulting to **false** which in this case gives you the filename “/tmp/8ef9c52abe857867fd0a4e9a819d1876” void of the “.png” extension. To enable this, and others you may pass them to `bodyParser()`:

```
app.use(express.bodyParser({ keepExtensions: true, uploadDir: '/my/files' }));
```

### [req.fresh](#reqfresh)

Check if the request is fresh - aka Last-Modified and/or the ETag still match, indicating that the resource is “fresh”.

```
console.dir(req.fresh);
// => true
```

### [req.host](#reqhost)

Returns the hostname from the “Host” header field (void of port number).

```
// Host: "example.com:3000"
console.dir(req.host);
// => 'example.com'
```

### [req.ip](#reqip)

Return the remote address, or when “trust proxy” is enabled - the upstream address.

```
console.dir(req.ip);
// => '127.0.0.1'
```

### [req.ips](#reqips)

When “trust proxy” is `true`, parse the “X-Forwarded-For” ip address list and return an array, otherwise an empty array is returned.

For example if the value were “client, proxy1, proxy2” you would receive the array `["client", "proxy1", "proxy2"]` where “proxy2” is the furthest down-stream.

### [req.originalUrl](#reqoriginalurl)

This property is much like `req.url`, however it retains the original request url, allowing you to rewrite `req.url` freely for internal routing purposes. For example the “mounting” feature of [app.use()](/en/3x/api/application/#appusepath-function) will rewrite `req.url` to strip the mount point.

```
// GET /search?q=something
console.log(req.originalUrl);
// => "/search?q=something"
```

### [req.params](#reqparams)

This property is an array containing properties mapped to the named route “parameters”. For example if you have the route `/user/:name`, then the “name” property is available to you as `req.params.name`. This object defaults to `{}`.

```
// GET /user/tj
console.dir(req.params.name);
// => 'tj'
```

When a regular expression is used for the route definition, capture groups are provided in the array using `req.params[N]`, where `N` is the nth capture group. This rule is applied to unnamed wild-card matches with string routes such as `/file/*`:

```
// GET /file/javascripts/jquery.js
console.dir(req.params[0]);
// => 'javascripts/jquery.js'
```

### [req.path](#reqpath)

Returns the request URL pathname.

```
// example.com/users?sort=desc
console.dir(req.path);
// => '/users'
```

### [req.protocol](#reqprotocol)

Return the protocol string “http” or “https” when requested with TLS. When the “trust proxy” setting is enabled the “X-Forwarded-Proto” header field will be trusted. If you’re running behind a reverse proxy that supplies https for you this may be enabled.

```
console.dir(req.protocol);
// => 'http'
```

### [req.query](#reqquery)

This property is an object containing the parsed query-string, defaulting to `{}`.

```
// GET /search?q=tobi+ferret
console.dir(req.query.q);
// => 'tobi ferret'


// GET /shoes?order=desc&shoe[color]=blue&shoe[type]=converse
console.dir(req.query.order);
// => 'desc'


console.dir(req.query.shoe.color);
// => 'blue'


console.dir(req.query.shoe.type);
// => 'converse'
```

### [req.res](#reqres)

This property holds a reference to the [response object](/en/3x/api/response/) that relates to this request object.

### [req.route](#reqroute)

The currently matched `Route` containing several properties such as the route’s original path string, the regexp generated, and so on.

```
app.get('/user/:id?', function (req, res) {
  console.dir(req.route);
});
```

Example output from the previous snippet:

```
{ path: '/user/:id?',
  method: 'get',
  callbacks: [ [Function] ],
  keys: [ { name: 'id', optional: true } ],
  regexp: /^\/user(?:\/([^\/]+?))?\/?$/i,
  params: [ id: '12' ] }
```

### [req.secure](#reqsecure)

Check if a TLS connection is established. This is a short-hand for:

```
console.dir(req.protocol === 'https');
// => true
```

### [req.signedCookies](#reqsignedcookies)

This object requires the `cookieParser(secret)` middleware for use. It contains signed cookies sent by the user-agent, unsigned and ready for use. Signed cookies reside in a different object to show developer intent; otherwise, a malicious attack could be placed on `req.cookie` values (which are easy to spoof). Note that signing a cookie does not make it “hidden” or encrypted; this simply prevents tampering (because the secret used to sign is private). If no signed cookies are sent, it defaults to `{}`.

```
// Cookie: user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
console.dir(req.signedCookies.user);
// => 'tobi'
```

### [req.stale](#reqstale)

Check if the request is stale - aka Last-Modified and/or the ETag do not match, indicating that the resource is “stale”.

```
console.dir(req.stale);
// => true
```

### [req.subdomains](#reqsubdomains)

Return subdomains as an array.

```
// Host: "tobi.ferrets.example.com"
console.dir(req.subdomains);
// => ['ferrets', 'tobi']
```

### [req.xhr](#reqxhr)

Check if the request was issued with the “X-Requested-With” header field set to “XMLHttpRequest” (jQuery etc).

```
console.dir(req.xhr);
// => true
```

## [Methods](#methods)

The `req` object also contains a number of methods that can be used to perform various tasks related to the HTTP request, such as checking the content type, retrieving header values, and more.

### [req.accepts(types)](#reqacceptstypes)

Check if the given `types` are acceptable, returning the best match when true, otherwise `undefined` - in which case you should respond with 406 “Not Acceptable”.

The `type` value may be a single mime type string such as “application/json”, the extension name such as “json”, a comma-delimited list or an array. When a list or array is given the best match, if any is returned.

index.js

```
// Accept: text/html
req.accepts('html');
// => "html"


// Accept: text/*, application/json
req.accepts('html');
// => "html"
req.accepts('text/html');
// => "text/html"
req.accepts('json, text');
// => "json"
req.accepts('application/json');
// => "application/json"


// Accept: text/*, application/json
req.accepts('image/png');
req.accepts('png');
// => undefined


// Accept: text/*;q=.5, application/json
req.accepts(['html', 'json']);
req.accepts('html, json');
// => "json"
```

### [req.acceptsCharset(charset)](#reqacceptscharsetcharset)

Check if the given `charset` are acceptable.

### [req.acceptsLanguage(lang)](#reqacceptslanguagelang)

Check if the given `lang` are acceptable.

### [req.get(field)](#reqgetfield)

Get the case-insensitive request header `field`. The “Referrer” and “Referer” fields are interchangeable.

```
req.get('Content-Type');
// => "text/plain"


req.get('content-type');
// => "text/plain"


req.get('Something');
// => undefined
```

Aliased as `req.header(field)`.

### [req.is(type)](#reqistype)

Check if the incoming request contains the “Content-Type” header field, and it matches the give mime `type`.

```
// With Content-Type: text/html; charset=utf-8
req.is('html');
req.is('text/html');
req.is('text/*');
// => true


// When Content-Type is application/json
req.is('json');
req.is('application/json');
req.is('application/*');
// => true


req.is('html');
// => false
```

### [req.param(name)](#reqparamname)

Return the value of param `name` when present.

```
// ?name=tobi
req.param('name');
// => "tobi"


// POST name=tobi
req.param('name');
// => "tobi"


// /user/tobi for /user/:name
req.param('name');
// => "tobi"
```

Lookup is performed in the following order:

* `req.params`
* `req.body`
* `req.query`

Direct access to `req.body`, `req.params`, and `req.query` should be favoured for clarity - unless you truly accept input from each object.

----
url: https://expressjs.com/en/blog/2026-09-30-security-releases
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2026-09-30-security-releases)

security

# [September 2026 Security Releases](#overview)

Ulises GasconSeptember 30, 2026

[](https://x.com/intent/tweet?text=September%202026%20Security%20Releases\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-09-30-security-releases%2F)[](https://bsky.app/intent/compose?text=September%202026%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-09-30-security-releases%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-09-30-security-releases%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-09-30-security-releases%2F\&text=September%202026%20Security%20Releases)[](https://wa.me/?text=September%202026%20Security%20Releases%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-09-30-security-releases%2F)[](/feed.xml)

The Express team has released [compression](https://www.npmjs.com/package/compression) 1.8.2, [cookies](https://www.npmjs.com/package/cookies) 0.9.2, [hbs](https://www.npmjs.com/package/hbs) 4.3.1, [morgan](https://www.npmjs.com/package/morgan) 1.12.1, [multer](https://www.npmjs.com/package/multer) 2.4.0, [multiparty](https://www.npmjs.com/package/multiparty) 4.3.1, and [proxy-addr](https://www.npmjs.com/package/proxy-addr) 2.0.8, addressing seven vulnerabilities across proxy trust, response compression, multipart parsing, template rendering, access logging, and cookie handling.

The Express security team took a [scheduled break](/en/blog/2026-09-09-joining-the-openjs-cna-security-break/) over the recent holiday period, alongside the [OpenJS Foundation CNA coordinated break](https://openjsf.org/blog/the-openjs-foundation-cna-is-taking-a-coordinated-break). There were no security incidents or escalations while we were away. We are now back at full capacity: the reports that arrived during the break have been triaged, and further fixes are already in progress for the coming weeks. We are grateful to the reporters and to the wider team for their patience and support, which made the break possible, and we encourage other maintainers to take time away with the same confidence.

### Warning

We recommend upgrading to the latest versions of compression, cookies, hbs, morgan, multer, multiparty, and proxy-addr to secure your applications. If you have a `package-lock.json`, you can update the dependencies by running:

Terminal window

```
npm update compression cookies hbs morgan multer multiparty proxy-addr
```

The following vulnerabilities have been addressed:

* [CVE-2026-90711 in proxy-addr utility module (Critical)](#cve-2026-90711-in-proxy-addr-utility-module-critical)
* [CVE-2026-87776 in compression middleware (High)](#cve-2026-87776-in-compression-middleware-high)
* [CVE-2026-87908 in multiparty utility module (High)](#cve-2026-87908-in-multiparty-utility-module-high)
* [CVE-2026-87123 in hbs template engine (Medium)](#cve-2026-87123-in-hbs-template-engine-medium)
* [CVE-2026-87859 in morgan middleware (Medium)](#cve-2026-87859-in-morgan-middleware-medium)
* [CVE-2026-88932 in multer middleware (Medium)](#cve-2026-88932-in-multer-middleware-medium)
* [CVE-2026-88038 in cookies utility module (Medium)](#cve-2026-88038-in-cookies-utility-module-medium)

## [CVE-2026-90711 in proxy-addr utility module (Critical)](#cve-2026-90711-in-proxy-addr-utility-module-critical)

**[proxy-addr](https://www.npmjs.com/package/proxy-addr) versions `>= 1.1.0, < 2.0.8` are vulnerable to IP spoofing when a trusted proxy subnet is configured in IPv4-mapped IPv6 notation**

proxy-addr decides which network hops to trust so that Express can believe the `X-Forwarded-For` header when setting `req.ip` and `req.ips`. When a trusted proxy subnet was written as an IPv4-mapped IPv6 address with a short prefix, such as `::ffff:10.0.0.0/8`, the subnet compiled with all-zero leading bits and matched every address instead of the block it named. Every unauthenticated client was then trusted as a proxy, so an attacker could set `req.ip` to any value and defeat IP-based access control, rate limiting, geolocation, and audit logging. The fix in 2.0.8 treats an IPv4 address as matching an IPv6 trust subnet only when that subnet genuinely covers the IPv4-mapped range.

**Affected versions**: `>= 1.1.0, < 2.0.8`\
**Patched version**: `>= 2.0.8`

For more details, see [GHSA-jqcg-44mw-7w3h](https://github.com/jshttp/proxy-addr/security/advisories/GHSA-jqcg-44mw-7w3h).

***

## [CVE-2026-87776 in compression middleware (High)](#cve-2026-87776-in-compression-middleware-high)

**[compression](https://www.npmjs.com/package/compression) versions `< 1.8.2` are vulnerable to denial of service through a memory leak on prematurely closed responses**

When a client disconnected before a compressed response finished sending, the zlib stream created to compress that response was never destroyed, so each aborted response leaked its native zlib memory. A remote client could repeatedly open requests and abort them mid-response, growing server memory with every aborted request until the process runs out of memory. All applications using compression are affected. The fix in 1.8.2 destroys the compression stream when the response closes early.

**Affected versions**: `< 1.8.2`\
**Patched version**: `>= 1.8.2`

For more details, see [GHSA-vc2v-76pw-4v95](https://github.com/expressjs/compression/security/advisories/GHSA-vc2v-76pw-4v95).

***

## [CVE-2026-87908 in multiparty utility module (High)](#cve-2026-87908-in-multiparty-utility-module-high)

**[multiparty](https://www.npmjs.com/package/multiparty) versions `>= 2.1.0, < 4.3.1` are vulnerable to denial of service through unbounded part-header accumulation**

multiparty bounds the total size of accumulated field values and uploaded file bytes, but did not bound the size of an individual part header. By sending a `multipart/form-data` request with a part header that never terminates, an unauthenticated attacker could grow server memory in proportion to the bytes sent until the process runs out of memory and crashes, even with every documented limit configured. Any service accepting multipart uploads through multiparty is affected. The fix in 4.3.1 adds a `maxHeadersSize` option, defaulting to 16 KB, that bounds per-part header size.

**Affected versions**: `>= 2.1.0, < 4.3.1`\
**Patched version**: `>= 4.3.1`

For more details, see [GHSA-5h46-2939-q3wh](https://github.com/pillarjs/multiparty/security/advisories/GHSA-5h46-2939-q3wh).

***

## [CVE-2026-87123 in hbs template engine (Medium)](#cve-2026-87123-in-hbs-template-engine-medium)

**[hbs](https://www.npmjs.com/package/hbs) version `4.3.0` is vulnerable to denial of service through an unhandled exception in async helper output escaping**

hbs 4.3.0 could crash the Node.js process when an async helper registered with `registerAsyncHelper` resolved to an object with a truthy but non-callable `toHTML` property. During output escaping handlebars calls `value.toHTML()`, which throws, and because the async substitution runs on a later tick outside the render function’s `try/catch`, the throw became an uncaught exception that terminated the process with no response sent and no chance for the Express error handler to intercept it. An object parsed from untrusted JSON such as `{"toHTML":"x"}` produces exactly this shape, so applications whose async helpers can resolve to externally-influenced objects could be crashed remotely. Only 4.3.0 is affected, and the fix in 4.3.1 handles the throw as a normal render error.

**Affected versions**: `= 4.3.0`\
**Patched version**: `>= 4.3.1`

For more details, see [GHSA-3c55-w9jx-p5jr](https://github.com/pillarjs/hbs/security/advisories/GHSA-3c55-w9jx-p5jr).

***

## [CVE-2026-87859 in morgan middleware (Medium)](#cve-2026-87859-in-morgan-middleware-medium)

**[morgan](https://www.npmjs.com/package/morgan) versions `< 1.12.1` are vulnerable to log injection through an unescaped double quote in quoted log fields**

morgan writes attacker-controlled request data into the access log. Its field escaping neutralized control characters and Unicode line separators but not the double quote, which delimits the quoted fields of the Apache combined log format morgan emits. An attacker who controlled a value written to a quoted field, such as the user-agent, the referrer, or a request header, could include a double quote to close that field early so that text they supplied was read as the following field by any log consumer that parses by field position. In custom formats that quote an attacker-controlled token before a server-controlled one, this lets the attacker forge values they otherwise do not control. The fix in 1.12.1 escapes the double quote as well.

**Affected versions**: `< 1.12.1`\
**Patched version**: `>= 1.12.1`

For more details, see [GHSA-9f6g-j8ch-79g4](https://github.com/expressjs/morgan/security/advisories/GHSA-9f6g-j8ch-79g4).

***

## [CVE-2026-88932 in multer middleware (Medium)](#cve-2026-88932-in-multer-middleware-medium)

**[multer](https://www.npmjs.com/package/multer) versions `>= 2.2.0, < 2.4.0` are vulnerable to denial of service through orphaned disk writes on aborted uploads**

multer’s `diskStorage` could leave complete, orphaned files on disk when a multipart upload was aborted in the brief window before the storage engine assigned the file path. An earlier cleanup fix removed only in-flight uploads that already had a path, so an upload aborted inside that window was written to disk with nothing left to remove it and no handle given to the application to clean it up. An unauthenticated attacker sending aborted requests to any route backed by disk storage could accumulate orphaned files until the upload directory or the shared system temporary directory was exhausted. The fix in 2.4.0 cleans up files aborted within this window.

**Affected versions**: `>= 2.2.0, < 2.4.0`\
**Patched version**: `>= 2.4.0`

For more details, see [GHSA-3pph-fpjx-jg34](https://github.com/expressjs/multer/security/advisories/GHSA-3pph-fpjx-jg34).

***

## [CVE-2026-88038 in cookies utility module (Medium)](#cve-2026-88038-in-cookies-utility-module-medium)

**[cookies](https://www.npmjs.com/package/cookies) versions `< 0.9.2` are vulnerable to Set-Cookie attribute injection through unvalidated domain and path options**

cookies validates cookie names and values against character sets that reject `;`, but the `domain` and `path` options were checked only against a permissive matcher that allows `;`, and both were written into the `Set-Cookie` header unescaped. An application that passed untrusted or request-derived data into `domain` or `path`, for example `domain: '.' + req.headers.host`, let that value inject additional cookie attributes and override `SameSite`, `Secure`, `HttpOnly`, or `Domain` on the cookies the application issued. The fix in 0.9.2 validates `domain` and `path` against the stricter RFC 6265 character sets.

**Affected versions**: `< 0.9.2`\
**Patched version**: `>= 0.9.2`

For more details, see [GHSA-x44v-5gxf-r6hf](https://github.com/pillarjs/cookies/security/advisories/GHSA-x44v-5gxf-r6hf).

***

We recommend upgrading to the latest versions of compression, cookies, hbs, morgan, multer, multiparty, and proxy-addr to secure your applications.

## More from Express

[security](/en/blog/2026-09-09-joining-the-openjs-cna-security-break)

## [Express is joining the OpenJS CNA coordinated break](/en/blog/2026-09-09-joining-the-openjs-cna-security-break)

[Express Security TeamSeptember 9, 2026](/en/blog/2026-09-09-joining-the-openjs-cna-security-break)

----
url: https://expressjs.com/en/advanced/best-practice-performance
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/advanced/best-practice-performance.mdx)

# [Production best practices: performance and reliability](#overview)

This article discusses performance and reliability best practices for Express applications deployed to production.

This topic clearly falls into the “devops” world, spanning both traditional development and operations. Accordingly, the information is divided into two parts: [things to do in your code](#things-to-do-in-your-code) (the dev part), and [things to do in your environment / setup](#things-to-do-in-your-environment--setup) (the ops part).

## [Things to do in your code](#things-to-do-in-your-code)

Here are some things you can do in your code to improve your application’s performance.

### [Use gzip compression](#use-gzip-compression)

Gzip compressing can greatly decrease the size of the response body and hence increase the speed of a web app. Use the [compression](https://www.npmjs.com/package/compression) middleware for gzip compression in your Express app. For example:

index.cjs

```
const compression = require('compression');
const express = require('express');
const app = express();


app.use(compression());
```

index.mjs

```
import compression from 'compression';
import express from 'express';


const app = express();


app.use(compression());
```

For a high-traffic website in production, the best way to put compression in place is to implement it at a reverse proxy level (see [Use a reverse proxy](#use-a-reverse-proxy)). In that case, you do not need to use compression middleware. For details on enabling gzip compression in Nginx, see [Module ngx\_http\_gzip\_module](https://nginx.org/en/docs/http/ngx_http_gzip_module.html) in the Nginx documentation.

### [Don’t use synchronous functions](#dont-use-synchronous-functions)

Synchronous functions and methods tie up the executing process until they return. A single call to a synchronous function might return in a few microseconds or milliseconds, however in high-traffic websites, these calls add up and reduce the performance of the app. Avoid their use in production.

Although Node and many modules provide synchronous and asynchronous versions of their functions, always use the asynchronous version in production. The only time when a synchronous function can be justified is upon initial startup.

You can use the `--trace-sync-io` command-line flag to print a warning and a stack trace whenever your application uses a synchronous API. Of course, you wouldn’t want to use this in production, but rather to ensure that your code is ready for production. See the [node command-line options documentation](https://nodejs.org/api/cli.html#--trace-sync-io) for more information.

### [Do logging correctly](#do-logging-correctly)

In general, there are two reasons for logging from your app: For debugging and for logging app activity (essentially, everything else). Using `console.log()` or `console.error()` to print log messages to the terminal is common practice in development. But [these functions are synchronous](https://nodejs.org/api/console.html#console) when the destination is a terminal or a file, so they are not suitable for production, unless you pipe the output to another program.

#### [For debugging](#for-debugging)

If you’re logging for purposes of debugging, then instead of using `console.log()`, use a special debugging module like [debug](https://www.npmjs.com/package/debug). This module enables you to use the DEBUG environment variable to control what debug messages are sent to `console.error()`, if any. To keep your app purely asynchronous, you’d still want to pipe `console.error()` to another program. But then, you’re not really going to debug in production, are you?

#### [For app activity](#for-app-activity)

If you’re logging app activity (for example, tracking traffic or API calls), instead of using `console.log()`, use a logging library like [Pino](https://www.npmjs.com/package/pino), which is the fastest and most efficient option available.

### [Handle exceptions properly](#handle-exceptions-properly)

Node apps crash when they encounter an uncaught exception. Not handling exceptions and taking appropriate actions will make your Express app crash and go offline. If you follow the advice in [Ensure your app automatically restarts](#ensure-your-app-automatically-restarts) below, then your app will recover from a crash. Fortunately, Express apps typically have a short startup time. Nevertheless, you want to avoid crashing in the first place, and to do that, you need to handle exceptions properly.

To ensure you handle all exceptions, use the following techniques:

* [Use try-catch](#use-try-catch)
* [Use promises](#use-promises)

Before diving into these topics, you should have a basic understanding of Node/Express error handling: using error-first callbacks, and propagating errors in middleware. Node uses an “error-first callback” convention for returning errors from asynchronous functions, where the first parameter to the callback function is the error object, followed by result data in succeeding parameters. To indicate no error, pass null as the first parameter. The callback function must correspondingly follow the error-first callback convention to meaningfully handle the error. And in Express, the best practice is to use the next() function to propagate errors through the middleware chain.

For more on the fundamentals of error handling, see:

* [Error Handling in Node.js](https://web.archive.org/web/20210619211351/https://www.joyent.com/node-js/production/design/errors)

#### [Use try-catch](#use-try-catch)

Try-catch is a JavaScript language construct that you can use to catch exceptions in synchronous code. Use try-catch, for example, to handle JSON parsing errors as shown below.

Here is an example of using try-catch to handle a potential process-crashing exception. This middleware function accepts a query field parameter named “params” that is a JSON object.

```
app.get('/search', (req, res) => {
  // Simulating async operation
  setImmediate(() => {
    const jsonStr = req.query.params;
    try {
      const jsonObj = JSON.parse(jsonStr);
      res.send('Success');
    } catch (e) {
      res.status(400).send('Invalid JSON string');
    }
  });
});
```

However, try-catch works only for synchronous code. Because the Node platform is primarily asynchronous (particularly in a production environment), try-catch won’t catch a lot of exceptions.

#### [Use promises](#use-promises)

When an error is thrown in an `async` function or a rejected promise is awaited inside an `async` function, those errors will be passed to the error handler as if calling `next(err)`

```
app.get('/', async (req, res, next) => {
  const data = await userData(); // If this promise fails, it will automatically call `next(err)` to handle the error.


  res.send(data);
});


app.use((err, req, res, next) => {
  res.status(err.status ?? 500).send({ error: err.message });
});
```

Also, you can use asynchronous functions for your middleware, and the router will handle errors if the promise fails, for example:

```
app.use(async (req, res, next) => {
  req.locals.user = await getUser(req);


  next(); // This will be called if the promise does not throw an error.
});
```

Best practice is to handle errors as close to the site as possible. So while this is now handled in the router, it’s best to catch the error in the middleware and handle it without relying on separate error-handling middleware.

#### [What not to do](#what-not-to-do)

One thing you should *not* do is to listen for the `uncaughtException` event, emitted when an exception bubbles all the way back to the event loop. Adding an event listener for `uncaughtException` will change the default behavior of the process that is encountering an exception; the process will continue to run despite the exception. This might sound like a good way of preventing your app from crashing, but continuing to run the app after an uncaught exception is a dangerous practice and is not recommended, because the state of the process becomes unreliable and unpredictable.

Additionally, using `uncaughtException` is officially recognized as [crude](https://nodejs.org/api/process.html#event-uncaughtexception). So listening for `uncaughtException` is just a bad idea. This is why we recommend things like multiple processes and supervisors: crashing and restarting is often the most reliable way to recover from an error.

We also don’t recommend using [domains](https://nodejs.org/api/domain.html). It generally doesn’t solve the problem and is a deprecated module.

### [Use worker threads for CPU-intensive tasks](#use-worker-threads-for-cpu-intensive-tasks)

Node.js runs your JavaScript on a single thread, so a CPU-intensive operation (such as image processing, parsing or transforming large payloads, or cryptographic operations) can block the event loop and slow down every request your Express app is handling. If your app does CPU-bound work, you can run it in [worker threads](https://nodejs.org/api/worker_threads.html), which execute JavaScript in parallel within the same process, keeping the main thread free to serve requests.

Each worker thread runs in its own JavaScript engine instance, so the data you pass to it through `workerData` or `postMessage` is copied, not shared. Copying large payloads has a cost of its own, which you can avoid by transferring objects such as `ArrayBuffer`s or by sharing memory explicitly with `SharedArrayBuffer`. Worker threads are not a replacement for [running your app in a cluster](#run-your-app-in-a-cluster), which scales your app across CPU cores by running multiple instances of it in separate processes.

This example offloads an image-resizing task to a worker, where `resize-worker.js` receives the image via `workerData` and posts the result back when it’s done:

```
const { Worker } = require('node:worker_threads');


app.post('/resize', (req, res, next) => {
  const worker = new Worker('./resize-worker.js', { workerData: req.body.image });


  worker.once('message', (result) => res.send(result));
  worker.once('error', next);
});
```

Note that this example is kept simple for illustration: creating a worker thread is relatively expensive, so [the Node.js documentation recommends using a pool of workers](https://nodejs.org/api/worker_threads.html#worker-threads) instead of spawning a new one for every request. Create a fixed pool of workers at startup and dispatch tasks to them as requests come in, for example with a library like [piscina](https://www.npmjs.com/package/piscina):

```
const path = require('node:path');
const Piscina = require('piscina');


const pool = new Piscina({ filename: path.resolve(__dirname, 'resize-worker.js') });


app.post('/resize', async (req, res, next) => {
  try {
    res.send(await pool.run(req.body.image));
  } catch (err) {
    next(err);
  }
});
```

Here `resize-worker.js` simply exports the function to run in the pool, and piscina takes care of creating the workers, queueing tasks, and reusing threads across requests.

For more guidance on keeping the event loop responsive, including when offloading work is worth its communication costs, see [Don’t Block the Event Loop](https://nodejs.org/learn/asynchronous-work/dont-block-the-event-loop) in the Node.js documentation.

## [Things to do in your environment / setup](#things-to-do-in-your-environment--setup)

Here are some things you can do in your system environment to improve your app’s performance.

### [Set NODE\_ENV to “production”](#set-node_env-to-production)

The NODE\_ENV environment variable specifies the environment in which an application is running (usually, development or production). One of the simplest things you can do to improve performance is to set NODE\_ENV to `production`.

Setting NODE\_ENV to “production” makes Express:

* Cache view templates.
* Cache CSS files generated from CSS extensions.
* Generate less verbose error messages.

[Tests indicate](https://web.archive.org/web/20250814011110/https://www.dynatrace.com/news/blog/the-drastic-effects-of-omitting-node-env-in-your-express-js-applications/) that just doing this can improve app performance by a factor of three!

If you need to write environment-specific code, you can check the value of NODE\_ENV with `process.env.NODE_ENV`. Be aware that checking the value of any environment variable incurs a performance penalty, and so should be done sparingly.

In development, you typically set environment variables in your interactive shell, for example by using `export` or your `.bash_profile` file. But in general, you shouldn’t do that on a production server; instead, use your OS’s init system (systemd). The next section provides more details about using your init system in general, but setting `NODE_ENV` is so important for performance (and easy to do), that it’s highlighted here.

With systemd, use the `Environment` directive in your unit file. For example:

Terminal window

```
Environment=NODE_ENV=production
```

For more information, see [Using Environment Variables In systemd Units](https://www.flatcar.org/docs/latest/setup/systemd/environment-variables/).

### [Use the latest LTS version of Node.js](#use-the-latest-lts-version-of-nodejs)

Running your app on a recent Node.js release is one of the easiest ways to improve performance. Each new version of Node.js ships with cumulative improvements to the V8 JavaScript engine and the runtime itself, so the same Express app can handle significantly more requests simply by upgrading. Benchmarks such as NodeSource’s [Node.js Performance Report](https://nodesource.com/pages/content-node-performance-report-wb.html) show how much throughput can improve from one Node.js version to the next. For production, use the latest [LTS release](https://nodejs.org/en/about/previous-releases) of Node.js, and keep it up to date as new versions come out.

### [Ensure your app automatically restarts](#ensure-your-app-automatically-restarts)

In production, you don’t want your application to be offline, ever. This means you need to make sure it restarts both if the app crashes and if the server itself crashes. Although you hope that neither of those events occurs, realistically you must account for both eventualities by:

* Using a process manager to restart the app (and Node) when it crashes.
* Using the init system provided by your OS to restart the process manager when the OS crashes. It’s also possible to use the init system without a process manager.

Node applications crash if they encounter an uncaught exception. The foremost thing you need to do is to ensure your app is well-tested and handles all exceptions (see [handle exceptions properly](#handle-exceptions-properly) for details). But as a fail-safe, put a mechanism in place to ensure that if and when your app crashes, it will automatically restart.

#### [Use a process manager](#use-a-process-manager)

In development, you started your app simply from the command line with `node server.js` or something similar. But doing this in production is a recipe for disaster. If the app crashes, it will be offline until you restart it. To ensure your app restarts if it crashes, use a process manager. A process manager is a “container” for applications that facilitates deployment, provides high availability, and enables you to manage the application at runtime.

In addition to restarting your app when it crashes, a process manager can enable you to:

* Gain insights into runtime performance and resource consumption.
* Modify settings dynamically to improve performance.
* Control clustering (pm2).

Historically, it was popular to use a Node.js process manager like [PM2](https://github.com/Unitech/pm2). See their documentation if you wish to do this. However, we recommend using your init system for process management.

#### [Use an init system](#use-an-init-system)

The next layer of reliability is to ensure that your app restarts when the server restarts. Systems can still go down for a variety of reasons. To ensure that your app restarts if the server crashes, use the init system built into your OS. The main init system in use today is [systemd](https://wiki.debian.org/systemd).

There are two ways to use init systems with your Express app:

* Run your app in a process manager, and install the process manager as a service with the init system. The process manager will restart your app when the app crashes, and the init system will restart the process manager when the OS restarts. This is the recommended approach.
* Run your app (and Node) directly with the init system. This is somewhat simpler, but you don’t get the additional advantages of using a process manager.

##### [Systemd](#systemd)

Systemd is a Linux system and service manager. Most major Linux distributions have adopted systemd as their default init system.

A systemd service configuration file is called a *unit file*, with a filename ending in `.service`. Here’s an example unit file to manage a Node app directly. Replace the values enclosed in `<angle brackets>` for your system and app:

Terminal window

```
[Unit]
Description=<Awesome Express App>


[Service]
Type=simple
ExecStart=/usr/local/bin/node </projects/myapp/index.js>
WorkingDirectory=</projects/myapp>


User=nobody
Group=nogroup




Environment=NODE_ENV=production




LimitNOFILE=infinity




LimitCORE=infinity


StandardInput=null
StandardOutput=syslog
StandardError=syslog
Restart=always


[Install]
WantedBy=multi-user.target
```

For more information on systemd, see the [systemd reference (man page)](https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html).

### [Run your app in a cluster](#run-your-app-in-a-cluster)

In a multi-core system, you can increase the performance of a Node app by many times by launching a cluster of processes. A cluster runs multiple instances of the app, ideally one instance on each CPU core, thereby distributing the load and tasks among the instances.

IMPORTANT: Since the app instances run as separate processes, they do not share the same memory space. That is, objects are local to each instance of the app. Therefore, you cannot maintain state in the application code. However, you can use an in-memory datastore like [Redis](https://redis.io/) to store session-related data and state. This caveat applies to essentially all forms of horizontal scaling, whether clustering with multiple processes or multiple physical servers.

In clustered apps, worker processes can crash individually without affecting the rest of the processes. Apart from performance advantages, failure isolation is another reason to run a cluster of app processes. Whenever a worker process crashes, always make sure to log the event and spawn a new process using cluster.fork().

#### [Using Node’s cluster module](#using-nodes-cluster-module)

Clustering is made possible with Node’s [cluster module](https://nodejs.org/api/cluster.html). This enables a master process to spawn worker processes and distribute incoming connections among the workers.

#### [Using PM2](#using-pm2)

If you deploy your application with PM2, then you can take advantage of clustering *without* modifying your application code. You should ensure your [application is stateless](https://pm2.keymetrics.io/docs/usage/specifics/#stateless-apps) first, meaning no local data is stored in the process (such as sessions, websocket connections and the like).

When running an application with PM2, you can enable **cluster mode** to run it in a cluster with a number of instances of your choosing, such as the matching the number of available CPUs on the machine. You can manually change the number of processes in the cluster using the `pm2` command line tool without stopping the app.

To enable cluster mode, start your application like so:

Terminal window

```
$ pm2 start npm --name my-app -i 4 -- start


$ pm2 start npm --name my-app -i max -- start
```

This can also be configured within a PM2 process file (`ecosystem.config.js` or similar) by setting `exec_mode` to `cluster` and `instances` to the number of workers to start.

Once running, the application can be scaled like so:

Terminal window

```
$ pm2 scale my-app +3


$ pm2 scale my-app 2
```

For more information on clustering with PM2, see [Cluster Mode](https://pm2.keymetrics.io/docs/usage/cluster-mode/) in the PM2 documentation.

### [Cache request results](#cache-request-results)

Another strategy to improve the performance in production is to cache the result of requests, so that your app does not repeat the operation to serve the same request repeatedly.

Use a caching server like [Varnish](https://www.varnish.org/) or [Nginx](https://blog.nginx.org/blog/nginx-caching-guide) (see also [Nginx Caching](https://serversforhackers.com/c/nginx-caching)) to greatly improve the speed and performance of your app.

### [Use a load balancer](#use-a-load-balancer)

No matter how optimized an app is, a single instance can handle only a limited amount of load and traffic. One way to scale an app is to run multiple instances of it and distribute the traffic via a load balancer. Setting up a load balancer can improve your app’s performance and speed, and enable it to scale more than is possible with a single instance.

A load balancer is usually a reverse proxy that orchestrates traffic to and from multiple application instances and servers. You can easily set up a load balancer for your app by using [Nginx](https://nginx.org/en/docs/http/load_balancing.html) or [HAProxy](https://www.digitalocean.com/community/tutorials/an-introduction-to-haproxy-and-load-balancing-concepts).

With load balancing, you might have to ensure that requests that are associated with a particular session ID connect to the process that originated them. This is known as *session affinity*, or *sticky sessions*, and may be addressed by the suggestion above to use a data store such as Redis for session data (depending on your application). For a discussion, see [Using multiple nodes](https://socket.io/docs/v4/using-multiple-nodes/).

### [Use a reverse proxy](#use-a-reverse-proxy)

A reverse proxy sits in front of a web app and performs supporting operations on the requests, apart from directing requests to the app. It can handle error pages, compression, caching, serving files, and load balancing among other things.

Handing over tasks that do not require knowledge of application state to a reverse proxy frees up Express to perform specialized application tasks. For this reason, it is recommended to run Express behind a reverse proxy like [Nginx](https://nginx.org/) or [HAProxy](https://www.haproxy.org/) in production.

----
url: https://expressjs.com/en/4x/api/request
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/4x/api/request/index.mdx)

# [Request Object](#overview)

The `req` object represents the HTTP request and has properties for the request query string, parameters, body, HTTP headers, and so on. In this documentation and by convention, the object is always referred to as `req` (and the HTTP response is `res`) but its actual name is determined by the parameters to the callback function in which you’re working.

For example:

```
app.get('/user/:id', function (req, res) {
  res.send('user ' + req.params.id);
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/:id', function (req: Request, res: Response) {
  res.send('user ' + req.params.id);
});
```

But you could just as well have:

```
app.get('/user/:id', function (request, response) {
  response.send('user ' + request.params.id);
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/:id', function (request: Request, response: Response) {
  response.send('user ' + request.params.id);
});
```

The `req` object is an enhanced version of Node’s own request object and supports all [built-in fields and methods](https://nodejs.org/api/http.html#class-httpincomingmessage).

## [Properties](#properties)

The `req` object contains a number of properties that provide information about the HTTP request, such as headers, query parameters, and more.

### Caution

In Express 4, `req.files` is no longer available on the `req` object by default. To access uploaded files on the `req.files` object, use multipart-handling middleware like [multer](https://www.npmjs.com/package/multer), [multiparty](https://www.npmjs.com/package/multiparty), [busboy](https://www.npmjs.com/package/busboy), [formidable](https://www.npmjs.com/package/formidable), or [pez](https://www.npmjs.com/package/pez).

### [req.app](#reqapp)

Type:`Application`

This property holds a reference to the instance of the Express application that is using the middleware.

If you follow the pattern in which you create a module that just exports a middleware function and `require()` it in your main file, then the middleware can access the Express instance via `req.app`

For example:

index.cjs

```
app.get('/viewdirectory', require('./mymiddleware.cjs'));
```

index.mjs

```
import mymiddleware from './mymiddleware.mjs';


app.get('/viewdirectory', mymiddleware);
```

And the middleware module itself:

mymiddleware.cjs

```
module.exports = function (req, res) {
  res.send('The views directory is ' + req.app.get('views'));
};
```

mymiddleware.mjs

```
export default function (req, res) {
  res.send('The views directory is ' + req.app.get('views'));
}
```

mymiddleware.ts

```
import { type Request, type Response } from 'express';


export default function (req: Request, res: Response) {
  res.send('The views directory is ' + req.app.get('views'));
}
```

### [req.baseUrl](#reqbaseurl)

Type:`String`

The URL path on which a router instance was mounted.

The `req.baseUrl` property is similar to the [mountpath](/en/4x/api/application/#appmountpath) property of the `app` object, except `app.mountpath` returns the matched path pattern(s).

For example:

```
var greet = express.Router();


greet.get('/jp', function (req, res) {
  console.log(req.baseUrl); // /greet
  res.send('Konnichiwa!');
});


app.use('/greet', greet); // load the router on '/greet'
```

```
import { type Request, type Response } from 'express';


const greet = express.Router();


greet.get('/jp', function (req: Request, res: Response) {
  console.log(req.baseUrl); // /greet
  res.send('Konnichiwa!');
});


app.use('/greet', greet); // load the router on '/greet'
```

Even if you use a path pattern or a set of path patterns to load the router, the `baseUrl` property returns the matched string, not the pattern(s). In the following example, the `greet` router is loaded on two path patterns.

```
app.use(['/gre+t', '/hel{2}o'], greet); // load the router on '/gre+t' and '/hel{2}o'
```

When a request is made to `/greet/jp`, `req.baseUrl` is “/greet”. When a request is made to `/hello/jp`, `req.baseUrl` is “/hello”.

### [req.body](#reqbody)

Type:`Object`

Contains key-value pairs of data submitted in the request body. By default, it is `undefined`, and is populated when you use body-parsing middleware such as [`express.json()`](/en/4x/api/express/#expressjson) or [`express.urlencoded()`](/en/4x/api/express/#expressurlencoded).

### Warning

As `req.body`’s shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, `req.body.foo.toString()` may fail in multiple ways, for example `foo` may not be there or may not be a string, and `toString` may not be a function and instead a string or other user-input.

The following example shows how to use body-parsing middleware to populate `req.body`.

index.cjs

```
var express = require('express');


var app = express();


app.use(express.json()); // for parsing application/json
app.use(express.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded


app.post('/profile', function (req, res, next) {
  console.log(req.body);
  res.json(req.body);
});
```

index.mjs

```
import express from 'express';


const app = express();


app.use(express.json()); // for parsing application/json
app.use(express.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded


app.post('/profile', function (req, res, next) {
  console.log(req.body);
  res.json(req.body);
});
```

index.ts

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();


app.use(express.json()); // for parsing application/json
app.use(express.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded


app.post('/profile', function (req: Request, res: Response, next: NextFunction) {
  console.log(req.body);
  res.json(req.body);
});
```

### [req.cookies](#reqcookies)

Type:`Object`

When using [cookie-parser](https://www.npmjs.com/package/cookie-parser) middleware, this property is an object that contains cookies sent by the request. If the request contains no cookies, it defaults to `{}`.

```
// Cookie: name=tj
console.dir(req.cookies.name);
// => 'tj'
```

```
console.dir(req.fresh);
// => true
```

### [req.hostname](#reqhostname)

Type:`String`

Contains the hostname derived from the `Host` HTTP header.

When the [`trust proxy` setting](/en/4x/api/application/#options-for-trust-proxy-setting) does not evaluate to `false`, this property will instead get the value from the `X-Forwarded-Host` header field. This header can be set by the client or by the proxy.

If there is more than one `X-Forwarded-Host` header in the request, the value of the first header is used. This includes a single header with comma-separated values, in which the first value is used.

### Note

Prior to Express v4.17.0, the `X-Forwarded-Host` could not contain multiple values or be present more than once.

```
// Host: "example.com:3000"
console.dir(req.hostname);
// => 'example.com'
```

### [req.host](#reqhost)

Type:`String`

Deprecated in:`v4.5.0`

### Caution

`req.host` is a deprecated alias of [`req.hostname`](#reqhostname) and returns the same value — the hostname with the port number stripped off. It has emitted a deprecation warning since Express v4.5.0. Use `req.hostname` instead.

```
// Host: "example.com:3000"
console.dir(req.host);
// => 'example.com'
```

### [req.ip](#reqip)

Type:`String`

Contains the remote IP address of the request.

When the [`trust proxy` setting](/en/4x/api/application/#options-for-trust-proxy-setting) does not evaluate to `false`, the value of this property is derived from the left-most entry in the `X-Forwarded-For` header. This header can be set by the client or by the proxy.

```
console.dir(req.ip);
// => '127.0.0.1'
```

### [req.ips](#reqips)

Type:`String[]`

When the [`trust proxy` setting](/en/4x/api/application/#options-for-trust-proxy-setting) does not evaluate to `false`, this property contains an array of IP addresses specified in the `X-Forwarded-For` request header. Otherwise, it contains an empty array. This header can be set by the client or by the proxy.

For example, if `X-Forwarded-For` is `client, proxy1, proxy2`, `req.ips` would be `["client", "proxy1", "proxy2"]`, where `proxy2` is the furthest downstream.

```
// normal request, or `trust proxy` disabled (the default)
console.dir(req.ips);
// => []


// app.set('trust proxy', true) and
// request header `X-Forwarded-For: client, proxy1, proxy2`
console.dir(req.ips);
// => ['client', 'proxy1', 'proxy2']
```

### [req.method](#reqmethod)

Type:`String`

Contains a string corresponding to the HTTP method of the request: `GET`, `POST`, `PUT`, and so on.

```
app.use(function (req, res, next) {
  console.dir(req.method);
  // => 'GET'
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use(function (req: Request, res: Response, next: NextFunction) {
  console.dir(req.method);
  // => 'GET'
  next();
});
```

### [req.originalUrl](#reqoriginalurl)

Type:`String`

### Caution

`req.url` is not a native Express property, it is inherited from Node’s [http module](https://nodejs.org/api/http.html#messageurl).

This property is much like `req.url`; however, it retains the original request URL, allowing you to rewrite `req.url` freely for internal routing purposes. For example, the “mounting” feature of [app.use()](/en/4x/api/application/#appuse) will rewrite `req.url` to strip the mount point.

```
// GET /search?q=something
console.dir(req.originalUrl);
// => '/search?q=something'
```

`req.originalUrl` is available both in middleware and router objects, and is a combination of `req.baseUrl` and `req.url`. Consider following example:

```
app.use('/admin', function (req, res, next) {
  // GET 'http://www.example.com/admin/new?sort=desc'
  console.dir(req.originalUrl); // '/admin/new?sort=desc'
  console.dir(req.baseUrl); // '/admin'
  console.dir(req.path); // '/new'
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use('/admin', function (req: Request, res: Response, next: NextFunction) {
  // GET 'http://www.example.com/admin/new?sort=desc'
  console.dir(req.originalUrl); // '/admin/new?sort=desc'
  console.dir(req.baseUrl); // '/admin'
  console.dir(req.path); // '/new'
  next();
});
```

### [req.params](#reqparams)

Type:`Object`

This property is an object containing properties mapped to the [named route “parameters”](/en/4x/guide/routing/#route-parameters). For example, if you have the route `/user/:name`, then the “name” property is available as `req.params.name`. This object defaults to `{}`.

```
// GET /user/tj
console.dir(req.params.name);
// => 'tj'
```

When you use a regular expression for the route definition, capture groups are provided as integer keys using `req.params[n]`, where `n` is the nth capture group. This rule is applied to unnamed wild card matches with string routes such as `/file/*`:

```
// GET /file/javascripts/jquery.js
console.dir(req.params[0]);
// => 'javascripts/jquery.js'
```

Named capturing groups in regular expressions behave like named route parameters. For example the group from `/^\/file\/(?<path>.*)$/` expression is available as `req.params.path`.

If you need to make changes to a key in `req.params`, use the [app.param](/en/4x/api/application/#appparam) handler. Changes are applicable only to [parameters](/en/4x/guide/routing/#route-parameters) already defined in the route path.

Any changes made to the `req.params` object in a middleware or route handler will be reset.

### Note

Express automatically decodes the values in `req.params` (using `decodeURIComponent`).

### [req.path](#reqpath)

Type:`String`

Contains the path part of the request URL.

```
// example.com/users?sort=desc
console.dir(req.path);
// => '/users'
```

### Note

When called from a middleware, the mount point is not included in `req.path`. See [app.use()](/en/4x/api/application/#appuse) for more details.

### [req.protocol](#reqprotocol)

Type:`String`

Contains the request protocol string: either `http` or (for TLS requests) `https`.

When the [`trust proxy` setting](/en/4x/api/application/#options-for-trust-proxy-setting) does not evaluate to `false`, this property will use the value of the `X-Forwarded-Proto` header field if present. This header can be set by the client or by the proxy.

```
console.dir(req.protocol);
// => 'http'
```

### [req.query](#reqquery)

Type:`Object`

This property is an object containing a property for each query string parameter in the route. When [query parser](/en/4x/api/application/#application-settings) is set to disabled, it is an empty object `{}`, otherwise it is the result of the configured query parser.

### Warning

As `req.query`’s shape is based on user-controlled input, all properties and values in this object are untrusted and should be validated before trusting. For example, `req.query.foo.toString()` may fail in multiple ways, for example `foo` may not be there or may not be a string, and `toString` may not be a function and instead a string or other user-input.

The value of this property can be configured with the [query parser application setting](/en/4x/api/application/#application-settings) to work how your application needs it. A very popular query string parser is the [`qs` module](https://www.npmjs.com/package/qs), and this is used by default. The `qs` module is very configurable with many settings, and it may be desirable to use different settings than the default to populate `req.query`:

index.cjs

```
var qs = require('qs');
app.set('query parser', function (str) {
  return qs.parse(str, {
    /* custom options */
  });
});
```

index.mjs

```
import qs from 'qs';


app.set('query parser', function (str) {
  return qs.parse(str, {
    /* custom options */
  });
});
```

index.ts

```
import qs from 'qs';


app.set('query parser', function (str: string) {
  return qs.parse(str, {
    /* custom options */
  });
});
```

Check out the [query parser application setting](/en/4x/api/application/#application-settings) documentation for other customization options.

### [req.res](#reqres)

Type:`Response`

This property holds a reference to the [response object](/en/4x/api/response/) that relates to this request object.

```
app.get('/', function (req, res) {
  console.dir(req.res === res);
  // => true
  res.send('OK');
});
```

```
import { type Request, type Response } from 'express';


app.get('/', function (req: Request, res: Response) {
  console.dir(req.res === res);
  // => true
  res.send('OK');
});
```

### [req.route](#reqroute)

Type:`Route`

Contains the currently-matched route (a `Route` object). For example:

```
app.get('/user/:id?', function userIdHandler(req, res) {
  console.log(req.route);
  res.send('GET');
});
```

```
import { type Request, type Response } from 'express';


app.get('/user/:id?', function userIdHandler(req: Request, res: Response) {
  console.log(req.route);
  res.send('GET');
});
```

Example output from the previous snippet:

```
{ path: '/user/:id?',
  stack:
   [ { handle: [Function: userIdHandler],
       name: 'userIdHandler',
       params: undefined,
       path: undefined,
       keys: [],
       regexp: /^\/?$/i,
       method: 'get' } ],
  methods: { get: true } }
```

### [req.secure](#reqsecure)

Type:`Boolean`

A Boolean property that is true if a TLS connection is established. Equivalent to:

```
console.dir(req.protocol === 'https');
// => true
```

### [req.signedCookies](#reqsignedcookies)

Type:`Object`

When using [cookie-parser](https://www.npmjs.com/package/cookie-parser) middleware, this property contains signed cookies sent by the request, unsigned and ready for use. Signed cookies reside in a different object to show developer intent; otherwise, a malicious attack could be placed on `req.cookie` values (which are easy to spoof). Note that signing a cookie does not make it “hidden” or encrypted; but simply prevents tampering (because the secret used to sign is private).

If no signed cookies are sent, the property defaults to `{}`.

```
// Cookie: user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
console.dir(req.signedCookies.user);
// => 'tobi'
```

For more information, issues, or concerns, see [cookie-parser](https://github.com/expressjs/cookie-parser).

### [req.stale](#reqstale)

Type:`Boolean`

Indicates whether the request is “stale,” and is the opposite of `req.fresh`. For more information, see [req.fresh](#reqfresh).

```
console.dir(req.stale);
// => true
```

### [req.subdomains](#reqsubdomains)

Type:`String[]`

An array of subdomains in the domain name of the request.

```
// Host: "tobi.ferrets.example.com"
console.dir(req.subdomains);
// => ['ferrets', 'tobi']
```

The application property `subdomain offset`, which defaults to 2, is used for determining the beginning of the subdomain segments. To change this behavior, change its value using [app.set](/en/4x/api/application/#appset).

### [req.xhr](#reqxhr)

Type:`Boolean`

A Boolean property that is `true` if the request’s `X-Requested-With` header field is “XMLHttpRequest”, indicating that the request was issued by a client library such as jQuery.

```
console.dir(req.xhr);
// => true
```

```
// Accept: text/html
req.accepts('html');
// => "html"


// Accept: text/*, application/json
req.accepts('html');
// => "html"
req.accepts('text/html');
// => "text/html"
req.accepts(['json', 'text']);
// => "json"
req.accepts('application/json');
// => "application/json"


// Accept: text/*, application/json
req.accepts('image/png');
req.accepts('png');
// => false


// Accept: text/*;q=.5, application/json
req.accepts(['html', 'json']);
// => "json"
```

```
// Accept-Charset: utf-8, iso-8859-1;q=0.5
req.acceptsCharsets('utf-8', 'iso-8859-1');
// => 'utf-8'


req.acceptsCharsets('us-ascii');
// => false
```

For more information, or if you have issues or concerns, see [accepts](https://github.com/expressjs/accepts).

### [req.acceptsCharset()](#reqacceptscharset)

#### Arguments

`charset`

Type:`String | String[]`

One or more character sets to test against the request’s `Accept-Charset` header.

↵Returns:`String | false`

Deprecated in:`v4.5.0`

### Caution

`req.acceptsCharset()` is the singular alias of [`req.acceptsCharsets()`](#reqacceptscharsets) and behaves identically. It has emitted a deprecation warning since Express v4.5.0. Use `req.acceptsCharsets()` instead.

You can update your code automatically with the following codemod:

Terminal window

```
npx codemod@latest @expressjs/pluralize-method-names
```

Terminal window

```
yarn dlx codemod@latest @expressjs/pluralize-method-names
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/pluralize-method-names
```

Terminal window

```
bunx codemod@latest @expressjs/pluralize-method-names
```

```
// Accept-Encoding: gzip, deflate
req.acceptsEncodings('gzip', 'deflate');
// => 'gzip'


req.acceptsEncodings('br');
// => false
```

For more information, or if you have issues or concerns, see [accepts](https://github.com/expressjs/accepts).

### [req.acceptsEncoding()](#reqacceptsencoding)

#### Arguments

`encoding`

Type:`String | String[]`

One or more encodings to test against the request’s `Accept-Encoding` header.

↵Returns:`String | false`

Deprecated in:`v4.5.0`

### Caution

`req.acceptsEncoding()` is the singular alias of [`req.acceptsEncodings()`](#reqacceptsencodings) and behaves identically. It has emitted a deprecation warning since Express v4.5.0. Use `req.acceptsEncodings()` instead.

You can update your code automatically with the following codemod:

Terminal window

```
npx codemod@latest @expressjs/pluralize-method-names
```

Terminal window

```
yarn dlx codemod@latest @expressjs/pluralize-method-names
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/pluralize-method-names
```

Terminal window

```
bunx codemod@latest @expressjs/pluralize-method-names
```

```
// Accept-Language: en;q=0.8, es
req.acceptsLanguages('en', 'es');
// => 'es'


req.acceptsLanguages();
// => ['es', 'en']
```

For more information, or if you have issues or concerns, see [accepts](https://github.com/expressjs/accepts).

### [req.acceptsLanguage()](#reqacceptslanguage)

#### Arguments

`lang`

Type:`String | String[] | undefined`

One or more languages to test against the request’s `Accept-Language` header. If omitted, all accepted languages are returned as an array.

↵Returns:`String | String[] | false`

Deprecated in:`v4.5.0`

### Caution

`req.acceptsLanguage()` is the singular alias of [`req.acceptsLanguages()`](#reqacceptslanguages) and behaves identically. It has emitted a deprecation warning since Express v4.5.0. Use `req.acceptsLanguages()` instead.

You can update your code automatically with the following codemod:

Terminal window

```
npx codemod@latest @expressjs/pluralize-method-names
```

Terminal window

```
yarn dlx codemod@latest @expressjs/pluralize-method-names
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/pluralize-method-names
```

Terminal window

```
bunx codemod@latest @expressjs/pluralize-method-names
```

Express (4.x) source: [request.js line 179](https://github.com/expressjs/express/blob/4.x/lib/request.js#L179)

Accepts (1.3) source: [index.js line 195](https://github.com/jshttp/accepts/blob/f69c19e459bd501e59fb0b1a40b7471bb578113a/index.js#L195)

```
req.get('Content-Type');
// => "text/plain"


req.get('content-type');
// => "text/plain"


req.get('Something');
// => undefined
```

```
// With Content-Type: text/html; charset=utf-8
req.is('html');
// => 'html'
req.is('text/html');
// => 'text/html'
req.is('text/*');
// => 'text/*'


// When Content-Type is application/json
req.is('json');
// => 'json'
req.is('application/json');
// => 'application/json'
req.is('application/*');
// => 'application/*'


// Using arrays
// When Content-Type is application/json
req.is(['json', 'html']);
// => 'json'


// Using multiple arguments
// When Content-Type is application/json
req.is('json', 'html');
// => 'json'


req.is('html');
// => false
req.is(['xml', 'yaml']);
// => false
req.is('xml', 'yaml');
// => false
```

For more information, or if you have issues or concerns, see [type-is](https://github.com/expressjs/type-is).

### [req.param()](#reqparam)

#### Arguments

`name`

Type:`String`

The name of the parameter to look up, searched in `req.params`, then `req.body`, then `req.query`.

`defaultValue`

Type:`any | undefined`

A value to return when the parameter is not found in any of the request objects.

↵Returns:`any`

### Caution

Deprecated. Use either `req.params`, `req.body` or `req.query`, as applicable.

Returns the value of param `name` when present.

```
// ?name=tobi
req.param('name');
// => "tobi"


// POST name=tobi
req.param('name');
// => "tobi"


// /user/tobi for /user/:name
req.param('name');
// => "tobi"
```

Lookup is performed in the following order:

* `req.params`
* `req.body`
* `req.query`

Optionally, you can specify `defaultValue` to set a default value if the parameter is not found in any of the request objects.

### Warning

Direct access to `req.body`, `req.params`, and `req.query` should be favoured for clarity - unless you truly accept input from each object.

Body-parsing middleware must be loaded for `req.param()` to work predictably. Refer [req.body](#reqbody) for details.

```
// parse header from request
var range = req.range(1000);


// the type of the range
if (range.type === 'bytes') {
  // the ranges
  range.forEach(function (r) {
    // do something with r.start and r.end
  });
}
```

----
url: https://expressjs.com/en/4x/api/application/
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/4x/api/application/index.mdx)

# [Application Object](#overview)

The `app` object conventionally denotes the Express application. Create it by calling the top-level `express()` function exported by the Express module:

index.cjs

```
var express = require('express');
var app = express();


app.get('/', function (req, res) {
  res.send('hello world');
});


app.listen(3000);
```

index.mjs

```
import express from 'express';


const app = express();


app.get('/', function (req, res) {
  res.send('hello world');
});


app.listen(3000);
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


app.get('/', function (req: Request, res: Response) {
  res.send('hello world');
});


app.listen(3000);
```

The `app` object has methods for

* Routing HTTP requests; see for example, [app.METHOD](#appmethod) and [app.param](#appparam).
* Configuring middleware; see [app.route](#approute).
* Rendering HTML views; see [app.render](#apprender).
* Registering a template engine; see [app.engine](#appengine).

It also has settings (properties) that affect how the application behaves; for more information, see [Application Settings](#application-settings).

### Note

The Express application object can be referred from the [request object](/en/4x/api/request/) and the [response object](/en/4x/api/response/) as `req.app`, and `res.app`, respectively.

## [Properties](#properties)

### [app.locals](#applocals)

Type:`Object`

The `app.locals` object has properties that are local variables within the application, and will be available in templates rendered with [res.render](/en/4x/api/response/#resrender).

### Warning

The `locals` object is used by view engines to render a response. The object keys may be particularly sensitive and should not contain user-controlled input, as it may affect the operation of the view engine or provide a path to cross-site scripting. Consult the documentation for the used view engine for additional considerations.

```
console.dir(app.locals.title);
// => 'My App'


console.dir(app.locals.email);
// => 'me@myapp.com'
```

Once set, the value of `app.locals` properties persist throughout the life of the application, in contrast with [res.locals](/en/4x/api/response/#reslocals) properties that are valid only for the lifetime of the request.

You can access local variables in templates rendered within the application. This is useful for providing helper functions to templates, as well as application-level data. Local variables are available in middleware via `req.app.locals` (see [req.app](/en/4x/api/request/#reqapp))

```
app.locals.title = 'My App';
app.locals.strftime = require('strftime');
app.locals.email = 'me@myapp.com';
```

### [app.mountpath](#appmountpath)

Type:`String | String[]`

The `app.mountpath` property contains one or more path patterns on which a sub-app was mounted.

### Note

A sub-app is an instance of `express` that may be used for handling the request to a route.

index.cjs

```
var express = require('express');


var app = express(); // the main app
var admin = express(); // the sub app


admin.get('/', function (req, res) {
  console.log(admin.mountpath); // /admin
  res.send('Admin Homepage');
});


app.use('/admin', admin); // mount the sub app
```

index.mjs

```
import express from 'express';


const app = express(); // the main app
const admin = express(); // the sub app


admin.get('/', function (req, res) {
  console.log(admin.mountpath); // /admin
  res.send('Admin Homepage');
});


app.use('/admin', admin); // mount the sub app
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express(); // the main app
const admin: Express = express(); // the sub app


admin.get('/', function (req: Request, res: Response) {
  console.log(admin.mountpath); // /admin
  res.send('Admin Homepage');
});


app.use('/admin', admin); // mount the sub app
```

It is similar to the [baseUrl](/en/4x/api/request/#reqbaseurl) property of the `req` object, except `req.baseUrl` returns the matched URL path, instead of the matched patterns.

If a sub-app is mounted on multiple path patterns, `app.mountpath` returns the list of patterns it is mounted on, as shown in the following example.

```
var admin = express();


admin.get('/', function (req, res) {
  console.dir(admin.mountpath); // [ '/adm*n', '/manager' ]
  res.send('Admin Homepage');
});


var secret = express();
secret.get('/', function (req, res) {
  console.log(secret.mountpath); // /secr*t
  res.send('Admin Secret');
});


admin.use('/secr*t', secret); // load the 'secret' router on '/secr*t', on the 'admin' sub app
app.use(['/adm*n', '/manager'], admin); // load the 'admin' router on '/adm*n' and '/manager', on the parent app
```

```
import express, { type Express, type Request, type Response } from 'express';


const admin: Express = express();


admin.get('/', function (req: Request, res: Response) {
  console.dir(admin.mountpath); // [ '/adm*n', '/manager' ]
  res.send('Admin Homepage');
});


const secret: Express = express();
secret.get('/', function (req: Request, res: Response) {
  console.log(secret.mountpath); // /secr*t
  res.send('Admin Secret');
});


admin.use('/secr*t', secret); // load the 'secret' router on '/secr*t', on the 'admin' sub app
app.use(['/adm*n', '/manager'], admin); // load the 'admin' router on '/adm*n' and '/manager', on the parent app
```

```
var admin = express();


admin.on('mount', function (parent) {
  console.log('Admin Mounted');
  console.log(parent); // refers to the parent app
});


admin.get('/', function (req, res) {
  res.send('Admin Homepage');
});


app.use('/admin', admin);
```

```
import express, { type Express, type Application, type Request, type Response } from 'express';


const admin: Express = express();


admin.on('mount', function (parent: Application) {
  console.log('Admin Mounted');
  console.log(parent); // refers to the parent app
});


admin.get('/', function (req: Request, res: Response) {
  res.send('Admin Homepage');
});


app.use('/admin', admin);
```

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/4x/api/router/) and [app](/en/4x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

This method is like the standard [app.METHOD()](#appmethod) methods, except it matches all HTTP verbs.

#### [Examples](#examples)

The following callback is executed for requests to `/secret` whether using GET, POST, PUT, DELETE, or any other HTTP request method:

```
app.all('/secret', function (req, res, next) {
  console.log('Accessing the secret section ...');
  next(); // pass control to the next handler
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.all('/secret', function (req: Request, res: Response, next: NextFunction) {
  console.log('Accessing the secret section ...');
  next(); // pass control to the next handler
});
```

The `app.all()` method is useful for mapping “global” logic for specific path prefixes or arbitrary matches. For example, if you put the following at the top of all other route definitions, it requires that all routes from that point on require authentication, and automatically load a user. Keep in mind that these callbacks do not have to act as end-points: `loadUser` can perform a task, then call `next()` to continue matching subsequent routes.

```
app.all('*', requireAuthentication, loadUser);
```

Or the equivalent:

```
app.all('*', requireAuthentication);
app.all('*', loadUser);
```

Another example is white-listed “global” functionality. The example is similar to the ones above, but it only restricts paths that start with “/api”:

```
app.all('/api/*', requireAuthentication);
```

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/4x/api/router/) and [app](/en/4x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

Routes HTTP DELETE requests to the specified path with the specified callback functions. For more information, see the [routing guide](/en/4x/guide/routing/).

#### [Example](#example)

```
app.delete('/', function (req, res) {
  res.send('DELETE request to homepage');
});
```

```
import { type Request, type Response } from 'express';


app.delete('/', function (req: Request, res: Response) {
  res.send('DELETE request to homepage');
});
```

### [app.del()](#appdel)

#### Arguments

`path`

Type:`String | RegExp | Array`

The path for which the middleware function is invoked; same as [app.delete()](#appdelete).

`callback`

Type:`Function | Function[]`

Callback functions; same as [app.delete()](#appdelete).

Deprecated in:`v4.2.0`

### Caution

`app.del()` is the alias of [`app.delete()`](#appdelete), originally introduced because `delete` was a reserved word in older JavaScript engines. It has emitted a deprecation warning since Express v4.2.0. Use `app.delete()` instead.

You can update your code automatically with the following codemod:

Terminal window

```
npx codemod@latest @expressjs/route-del-to-delete
```

Terminal window

```
yarn dlx codemod@latest @expressjs/route-del-to-delete
```

Terminal window

```
pnpm dlx codemod@latest @expressjs/route-del-to-delete
```

Terminal window

```
bunx codemod@latest @expressjs/route-del-to-delete
```

```
app.disable('trust proxy');
app.get('trust proxy');
// => false
```

```
app.disabled('trust proxy');
// => true


app.enable('trust proxy');
app.disabled('trust proxy');
// => false
```

```
app.enable('trust proxy');
app.get('trust proxy');
// => true
```

```
app.enabled('trust proxy');
// => false


app.enable('trust proxy');
app.enabled('trust proxy');
// => true
```

```
app.engine('pug', require('pug').__express);
```

Use this method for engines that do not provide `.__express` out of the box, or if you wish to “map” a different extension to the template engine.

For example, to map the EJS template engine to “.html” files:

```
app.engine('html', require('ejs').renderFile);
```

In this case, EJS provides a `.renderFile()` method with the same signature that Express expects: `(path, options, callback)`, though note that it aliases this method as `ejs.__express` internally so if you’re using “.ejs” extensions you don’t need to do anything.

Some template engines do not follow this convention. The [consolidate.js](https://github.com/tj/consolidate.js) library maps Node template engines to follow this convention, so they work seamlessly with Express.

index.cjs

```
var engines = require('consolidate');
app.engine('haml', engines.haml);
app.engine('html', engines.hogan);
```

index.mjs

```
import engines from 'consolidate';


app.engine('haml', engines.haml);
app.engine('html', engines.hogan);
```

```
app.get('title');
// => undefined


app.set('title', 'My Site');
app.get('title');
// => "My Site"
```

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/4x/api/router/) and [app](/en/4x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

Routes HTTP GET requests to the specified path with the specified callback functions.

For more information, see the [routing guide](/en/4x/guide/routing/).

#### [Example](#example-1)

```
app.get('/', function (req, res) {
  res.send('GET request to homepage');
});
```

```
import { type Request, type Response } from 'express';


app.get('/', function (req: Request, res: Response) {
  res.send('GET request to homepage');
});
```

A function to call once the server is listening.

↵Returns:`http.Server`

Binds and listens for connections on the specified host and port, or starts a UNIX socket and listens for connections on the given path. This method is identical to Node’s [http.Server.listen()](https://nodejs.org/api/http.html#serverlisten).

If port is omitted or is 0, the operating system will assign an arbitrary unused port, which is useful for cases like automated tasks (tests, etc.).

index.cjs

```
var express = require('express');
var app = express();


app.listen(3000); // bind and listen on a TCP port
app.listen('/tmp/sock'); // or listen on a UNIX socket
```

index.mjs

```
import express from 'express';


const app = express();


app.listen(3000); // bind and listen on a TCP port
app.listen('/tmp/sock'); // or listen on a UNIX socket
```

index.ts

```
import express, { type Express } from 'express';


const app: Express = express();


app.listen(3000); // bind and listen on a TCP port
app.listen('/tmp/sock'); // or listen on a UNIX socket
```

The `app` returned by `express()` is in fact a JavaScript `Function`, designed to be passed to Node’s HTTP servers as a callback to handle requests. This makes it easy to provide both HTTP and HTTPS versions of your app with the same code base, as the app does not inherit from these (it is simply a callback):

index.cjs

```
var express = require('express');
var https = require('https');
var http = require('http');
var app = express();


http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
```

index.mjs

```
import express from 'express';
import https from 'https';
import http from 'http';


const app = express();


http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
```

index.ts

```
import express, { type Express } from 'express';
import https from 'https';
import http from 'http';


const app: Express = express();


http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
```

The `app.listen()` method returns an [http.Server](https://nodejs.org/api/http.html#class-httpserver) object and (for HTTP) is a convenience method for the following:

```
app.listen = function () {
  var server = http.createServer(this);
  return server.listen.apply(server, arguments);
};
```

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/4x/api/router/) and [app](/en/4x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

```
app.get('/', function (req, res) {
  res.send('GET request to homepage');
});


app.post('/', function (req, res) {
  res.send('POST request to homepage');
});


// methods that are invalid JavaScript variable names use bracket notation
app['m-search']('/', function (req, res) {
  res.send('M-SEARCH request to homepage');
});
```

```
import { type Request, type Response } from 'express';


app.get('/', function (req: Request, res: Response) {
  res.send('GET request to homepage');
});


app.post('/', function (req: Request, res: Response) {
  res.send('POST request to homepage');
});


// methods that are invalid JavaScript variable names use bracket notation
app['m-search']('/', function (req: Request, res: Response) {
  res.send('M-SEARCH request to homepage');
});
```

### Note

The `app.get()` function is automatically called for the HTTP `HEAD` method in addition to the `GET` method if `app.head()` was not called for the path before `app.get()`.

The method, `app.all()`, is not derived from any HTTP method and loads middleware at the specified path for *all* HTTP request methods. For more information, see [app.all](#appall).

For more information on routing, see the [routing guide](/en/4x/guide/routing/).

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/4x/api/router/) and [app](/en/4x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

Requires runtime:`Node.js >=20.19.3 <21 || >=22.2.0`

Routes HTTP QUERY requests to the specified path with the specified callback functions. For more information, see the [routing guide](/en/4x/guide/routing/).

### Caution

The HTTP QUERY method was standardized on June 15, 2026 as [RFC 10008](https://www.rfc-editor.org/rfc/rfc10008.html). Client and intermediary support is still limited. Verify that your target environments support the QUERY verb before relying on it in production.

The HTTP QUERY method ([RFC 10008](https://www.rfc-editor.org/rfc/rfc10008.html)) is designed for queries whose input is too large or too sensitive to encode in the URL. Unlike `GET`, a QUERY request carries a body containing the query input. Unlike `POST`, it is explicitly **safe and idempotent**, intermediaries and caches can retry it automatically, and the response is cacheable (with the request body included in the cache key).

Use `app.query()` when query parameters would exceed URL length limits, contain sensitive data that should not appear in server logs or browser history, or are too complex to express cleanly as a URL query string, such as deeply nested filters or structured criteria.

Because the query input travels in the request body, `req.body` is `undefined` until you mount a body-parsing middleware such as [`express.json()`](/en/4x/api/express/#expressjson) or [`express.urlencoded()`](/en/4x/api/express/#expressurlencoded) that matches the request’s `Content-Type`.

#### [Example](#example-2)

index.js

```
app.use(express.json()); // populate req.body for application/json payloads


app.query('/search', (req, res) => {
  // complex filter criteria arrive in req.body, not the URL
  const results = db.search(req.body);
  res.json(results);
});
```

index.ts

```
import express, { type Request, type Response } from 'express';


app.use(express.json()); // populate req.body for application/json payloads


app.query('/search', (req: Request, res: Response) => {
  // complex filter criteria arrive in req.body, not the URL
  const results = db.search(req.body);
  res.json(results);
});
```

### [app.param()](#appparam)

#### Arguments

`name`

Type:`String | String[] | undefined`

The name of the route parameter, or an array of names.

`callback`

Type:`Function`

The trigger called as `callback(req, res, next, value, name)`: the request object, the response object, the next middleware, the value of the parameter, and the name of the parameter, in that order.

Add callback triggers to [route parameters](/en/4x/guide/routing/#route-parameters), where `name` is the name of the parameter or an array of them, and `callback` is the callback function. The parameters of the callback function are the request object, the response object, the next middleware, the value of the parameter and the name of the parameter, in that order.

If `name` is an array, the `callback` trigger is registered for each parameter declared in it, in the order in which they are declared. Furthermore, for each declared parameter except the last one, a call to `next` inside the callback will call the callback for the next declared parameter. For the last parameter, a call to `next` will call the next middleware in place for the route currently being processed, just like it would if `name` were just a string.

For example, when `:user` is present in a route path, you may map user loading logic to automatically provide `req.user` to the route, or perform validations on the parameter input.

```
app.param('user', function (req, res, next, id) {
  // try to get the user details from the User model and attach it to the request object
  User.find(id, function (err, user) {
    if (err) {
      next(err);
    } else if (user) {
      req.user = user;
      next();
    } else {
      next(new Error('failed to load user'));
    }
  });
});
```

Param callback functions are local to the router on which they are defined. They are not inherited by mounted apps or routers, nor are they triggered for route parameters inherited from parent routers. Hence, param callbacks defined on `app` will be triggered only by route parameters defined on `app` routes.

All param callbacks will be called before any handler of any route in which the param occurs, and they will each be called only once in a request-response cycle, even if the parameter is matched in multiple routes, as shown in the following examples.

```
app.param('id', function (req, res, next, id) {
  console.log('CALLED ONLY ONCE');
  next();
});


app.get('/user/:id', function (req, res, next) {
  console.log('although this matches');
  next();
});


app.get('/user/:id', function (req, res) {
  console.log('and this matches too');
  res.end();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.param('id', function (req: Request, res: Response, next: NextFunction, id: string) {
  console.log('CALLED ONLY ONCE');
  next();
});


app.get('/user/:id', function (req: Request, res: Response, next: NextFunction) {
  console.log('although this matches');
  next();
});


app.get('/user/:id', function (req: Request, res: Response) {
  console.log('and this matches too');
  res.end();
});
```

On `GET /user/42`, the following is printed:

```
CALLED ONLY ONCE
although this matches
and this matches too
```

```
app.param(['id', 'page'], function (req, res, next, value) {
  console.log('CALLED ONLY ONCE with', value);
  next();
});


app.get('/user/:id/:page', function (req, res, next) {
  console.log('although this matches');
  next();
});


app.get('/user/:id/:page', function (req, res) {
  console.log('and this matches too');
  res.end();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.param(
  ['id', 'page'],
  function (req: Request, res: Response, next: NextFunction, value: string) {
    console.log('CALLED ONLY ONCE with', value);
    next();
  }
);


app.get('/user/:id/:page', function (req: Request, res: Response, next: NextFunction) {
  console.log('although this matches');
  next();
});


app.get('/user/:id/:page', function (req: Request, res: Response) {
  console.log('and this matches too');
  res.end();
});
```

On `GET /user/42/3`, the following is printed:

```
CALLED ONLY ONCE with 42
CALLED ONLY ONCE with 3
although this matches
and this matches too
```

### Caution

The following section describes `app.param(callback)`, which is deprecated as of v4.11.0.

The behavior of the `app.param(name, callback)` method can be altered entirely by passing only a function to `app.param()`. This function is a custom implementation of how `app.param(name, callback)` should behave - it accepts two parameters and must return a middleware.

The first parameter of this function is the name of the URL parameter that should be captured, the second parameter can be any JavaScript object which might be used for returning the middleware implementation.

The middleware returned by the function decides the behavior of what happens when a URL parameter is captured.

In this example, the `app.param(name, callback)` signature is modified to `app.param(name, accessId)`. Instead of accepting a name and a callback, `app.param()` will now accept a name and a number.

index.cjs

```
var express = require('express');
var app = express();


// customizing the behavior of app.param()
app.param(function (param, option) {
  return function (req, res, next, val) {
    if (val === option) {
      next();
    } else {
      next('route');
    }
  };
});


// using the customized app.param()
app.param('id', 1337);


// route to trigger the capture
app.get('/user/:id', function (req, res) {
  res.send('OK');
});


app.listen(3000, function () {
  console.log('Ready');
});
```

index.mjs

```
import express from 'express';


const app = express();


// customizing the behavior of app.param()
app.param(function (param, option) {
  return function (req, res, next, val) {
    if (val === option) {
      next();
    } else {
      next('route');
    }
  };
});


// using the customized app.param()
app.param('id', 1337);


// route to trigger the capture
app.get('/user/:id', function (req, res) {
  res.send('OK');
});


app.listen(3000, function () {
  console.log('Ready');
});
```

In this example, the `app.param(name, callback)` signature remains the same, but instead of a middleware callback, a custom data type checking function has been defined to validate the data type of the user id.

```
app.param(function (param, validator) {
  return function (req, res, next, val) {
    if (validator(val)) {
      next();
    } else {
      next('route');
    }
  };
});


app.param('id', function (candidate) {
  return !isNaN(parseFloat(candidate)) && isFinite(candidate);
});
```

### Note

The ‘`.`’ character can’t be used to capture a character in your capturing regexp. For example you can’t use `'/user-.+/'` to capture `'users-gami'`, use `[\s\S]` or `[\w\W]` instead (as in `'/user-[\s\S]+/'`.

Examples:

```
// captures '1-a_6' but not '543-azser-sder'
router.get('/[0-9]+-[[\w]]*', function (req, res, next) {
  next();
});


// captures '1-a_6' and '543-az(ser"-sder' but not '5-a s'
router.get('/[0-9]+-[[\S]]*', function (req, res, next) {
  next();
});


// captures all (equivalent to '.*')
router.get('[[\s\S]]*', function (req, res, next) {
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


// captures '1-a_6' but not '543-azser-sder'
router.get('/[0-9]+-[[\w]]*', function (req: Request, res: Response, next: NextFunction) {
  next();
});


// captures '1-a_6' and '543-az(ser"-sder' but not '5-a s'
router.get('/[0-9]+-[[\S]]*', function (req: Request, res: Response, next: NextFunction) {
  next();
});


// captures all (equivalent to '.*')
router.get('[[\s\S]]*', function (req: Request, res: Response, next: NextFunction) {
  next();
});
```

### [app.path()](#apppath)

↵Returns:`String`

Returns the canonical path of the app, a string.

index.js

```
var app = express();
var blog = express();
var blogAdmin = express();


app.use('/blog', blog);
blog.use('/admin', blogAdmin);


console.dir(app.path()); // ''
console.dir(blog.path()); // '/blog'
console.dir(blogAdmin.path()); // '/blog/admin'
```

index.ts

```
import express, { type Express } from 'express';


const app: Express = express();
const blog: Express = express();
const blogAdmin: Express = express();


app.use('/blog', blog);
blog.use('/admin', blogAdmin);


console.dir(app.path()); // ''
console.dir(blog.path()); // '/blog'
console.dir(blogAdmin.path()); // '/blog/admin'
```

The behavior of this method can become very complicated in complex cases of mounted apps: it is usually better to use [req.baseUrl](/en/4x/api/request/#reqbaseurl) to get the canonical path of the app.

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/4x/api/router/) and [app](/en/4x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

Routes HTTP POST requests to the specified path with the specified callback functions. For more information, see the [routing guide](/en/4x/guide/routing/).

#### [Example](#example-3)

```
app.post('/', function (req, res) {
  res.send('POST request to homepage');
});
```

```
import { type Request, type Response } from 'express';


app.post('/', function (req: Request, res: Response) {
  res.send('POST request to homepage');
});
```

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/4x/api/router/) and [app](/en/4x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

Routes HTTP PUT requests to the specified path with the specified callback functions.

#### [Example](#example-4)

```
app.put('/', function (req, res) {
  res.send('PUT request to homepage');
});
```

```
import { type Request, type Response } from 'express';


app.put('/', function (req: Request, res: Response) {
  res.send('PUT request to homepage');
});
```

Returns the rendered HTML of a view via the `callback` function. It accepts an optional parameter that is an object containing local variables for the view. It is like [res.render()](/en/4x/api/response/#resrender), except it cannot send the rendered view to the client on its own.

```
app.render('email', function (err, html) {
  // ...
});


app.render('email', { name: 'Tobi' }, function (err, html) {
  // ...
});
```

```
var app = express();


app
  .route('/events')
  .all(function (req, res, next) {
    // runs for all HTTP verbs first
    // think of it as route specific middleware!
  })
  .get(function (req, res, next) {
    res.json({});
  })
  .post(function (req, res, next) {
    // maybe add a new event...
  });
```

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const app: Express = express();


app
  .route('/events')
  .all(function (req: Request, res: Response, next: NextFunction) {
    // runs for all HTTP verbs first
    // think of it as route specific middleware!
  })
  .get(function (req: Request, res: Response, next: NextFunction) {
    res.json({});
  })
  .post(function (req: Request, res: Response, next: NextFunction) {
    // maybe add a new event...
  });
```

```
app.set('title', 'My Site');
app.get('title'); // "My Site"
```

Type:`Boolean | String | Function`Default:`"extended"`

Read [Express behind proxies](/en/4x/guide/behind-proxies/) for more information.

```
app.set('trust proxy', 'loopback');
```

Specify a subnet and an address:

```
app.set('trust proxy', 'loopback, 123.123.123.123');
```

Specify multiple subnets as CSV:

```
app.set('trust proxy', 'loopback, linklocal, uniquelocal');
```

Specify multiple subnets as an array:

```
app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']);
```

When specified, the IP addresses or the subnets are excluded from the address determination process, and the untrusted IP address nearest to the application server is determined as the client’s IP address.

**Number**: Trust the *n*th hop from the front-facing proxy server as the client.

**Function**: Custom trust implementation. Use this only if you know what you are doing.

```
app.set('trust proxy', function (ip) {
  if (ip === '127.0.0.1' || ip === '123.123.123.123')
    return true; // trusted IPs
  else return false;
});
```

```
app.set('etag', function (body, encoding) {
  return generateHash(body, encoding); // consider the function is defined
});
```

Callback functions; can be: a middleware function, a series of middleware functions (separated by commas), an array of middleware functions, or a combination of all of the above. You can provide multiple callback functions that behave just like middleware, except that these callbacks can invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there is no reason to proceed with the current route. Since [router](/en/4x/api/router/) and [app](/en/4x/api/application/) implement the middleware interface, you can use them as you would any other middleware function. For examples, see [Middleware callback function examples](#middleware-callback-function-examples).

Mounts the specified [middleware](/en/4x/guide/using-middleware/) function or functions at the specified path: the middleware function is executed when the base of the requested path matches `path`.

#### [Description](#description)

A route will match any path that follows its path immediately with a “`/`”. For example: `app.use('/apple', ...)` will match “/apple”, “/apple/images”, “/apple/images/news”, and so on.

Since `path` defaults to ”/”, middleware mounted without a path will be executed for every request to the app. For example, this middleware function will be executed for *every* request to the app:

```
app.use(function (req, res, next) {
  console.log('Time: %d', Date.now());
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use(function (req: Request, res: Response, next: NextFunction) {
  console.log('Time: %d', Date.now());
  next();
});
```

### Note

Sub-apps will:

* Not inherit the value of settings that have a default value. You must set the value in the sub-app.
* Inherit the value of settings with no default value.

For details, see [Application settings](#application-settings).

Middleware functions are executed sequentially, therefore the order of middleware inclusion is important.

```
// this middleware will not allow the request to go beyond it
app.use(function (req, res, next) {
  res.send('Hello World');
});


// requests will never reach this route
app.get('/', function (req, res) {
  res.send('Welcome');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


// this middleware will not allow the request to go beyond it
app.use(function (req: Request, res: Response, next: NextFunction) {
  res.send('Hello World');
});


// requests will never reach this route
app.get('/', function (req: Request, res: Response) {
  res.send('Welcome');
});
```

**Error-handling middleware**

Error-handling middleware always takes *four* arguments. You must provide four arguments to identify it as an error-handling middleware function. Even if you don’t need to use the `next` object, you must specify it to maintain the signature. Otherwise, the `next` object will be interpreted as regular middleware and will fail to handle errors. For details about error-handling middleware, see: [Error handling](/en/4x/guide/error-handling/).

Define error-handling middleware functions in the same way as other middleware functions, except with four arguments instead of three, specifically with the signature `(err, req, res, next)`):

```
app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use(function (err: Error, req: Request, res: Response, next: NextFunction) {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
```

#### [Path examples](#path-examples)

The following table provides some simple examples of valid `path` values for mounting middleware.

**Path**: Matches the exact path `/abcd` and any sub-paths starting with `/abcd/` (for example, `/abcd/foo`):

```
app.use('/abcd', function (req, res, next) {
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use('/abcd', function (req: Request, res: Response, next: NextFunction) {
  next();
});
```

**Path Pattern**: This will match paths starting with `/abcd` and `/abd`:

```
app.use('/abc?d', function (req, res, next) {
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use('/abc?d', function (req: Request, res: Response, next: NextFunction) {
  next();
});
```

This will match paths starting with `/abcd`, `/abbcd`, `/abbbbbcd`, and so on:

```
app.use('/ab+cd', function (req, res, next) {
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use('/ab+cd', function (req: Request, res: Response, next: NextFunction) {
  next();
});
```

This will match paths starting with `/abcd`, `/abxcd`, `/abFOOcd`, `/abbArcd`, and so on:

```
app.use('/ab*cd', function (req, res, next) {
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use('/ab*cd', function (req: Request, res: Response, next: NextFunction) {
  next();
});
```

This will match paths starting with `/ad` and `/abcd`:

```
app.use('/a(bc)?d', function (req, res, next) {
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use('/a(bc)?d', function (req: Request, res: Response, next: NextFunction) {
  next();
});
```

**Regular Expression**: This will match paths starting with `/abc` and `/xyz`:

```
app.use(/\/abc|\/xyz/, function (req, res, next) {
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use(/\/abc|\/xyz/, function (req: Request, res: Response, next: NextFunction) {
  next();
});
```

**Array**: This will match paths starting with `/abcd`, `/xyza`, `/lmn`, and `/pqr`:

```
app.use(['/abcd', '/xyza', /\/lmn|\/pqr/], function (req, res, next) {
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use(
  ['/abcd', '/xyza', /\/lmn|\/pqr/],
  function (req: Request, res: Response, next: NextFunction) {
    next();
  }
);
```

#### [Middleware callback function examples](#middleware-callback-function-examples)

The following table provides some simple examples of middleware functions that can be used as the `callback` argument to `app.use()`, `app.METHOD()`, and `app.all()`.

**Single Middleware**: You can define and mount a middleware function locally.

```
app.use(function (req, res, next) {
  next();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


app.use(function (req: Request, res: Response, next: NextFunction) {
  next();
});
```

A router is valid middleware.

```
var router = express.Router();
router.get('/', function (req, res, next) {
  next();
});
app.use(router);
```

```
import express, { type Request, type Response, type NextFunction } from 'express';


const router = express.Router();
router.get('/', function (req: Request, res: Response, next: NextFunction) {
  next();
});
app.use(router);
```

An Express app is valid middleware.

```
var subApp = express();
subApp.get('/', function (req, res, next) {
  next();
});
app.use(subApp);
```

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


const subApp: Express = express();
subApp.get('/', function (req: Request, res: Response, next: NextFunction) {
  next();
});
app.use(subApp);
```

**Series of Middleware**: You can specify more than one middleware function at the same mount path.

```
var r1 = express.Router();
r1.get('/', function (req, res, next) {
  next();
});


var r2 = express.Router();
r2.get('/', function (req, res, next) {
  next();
});


app.use(r1, r2);
```

```
import express, { type Request, type Response, type NextFunction } from 'express';


const r1 = express.Router();
r1.get('/', function (req: Request, res: Response, next: NextFunction) {
  next();
});


const r2 = express.Router();
r2.get('/', function (req: Request, res: Response, next: NextFunction) {
  next();
});


app.use(r1, r2);
```

**Array**: Use an array to group middleware logically.

```
var r1 = express.Router();
r1.get('/', function (req, res, next) {
  next();
});


var r2 = express.Router();
r2.get('/', function (req, res, next) {
  next();
});


app.use([r1, r2]);
```

```
import express, { type Request, type Response, type NextFunction } from 'express';


const r1 = express.Router();
r1.get('/', function (req: Request, res: Response, next: NextFunction) {
  next();
});


const r2 = express.Router();
r2.get('/', function (req: Request, res: Response, next: NextFunction) {
  next();
});


app.use([r1, r2]);
```

**Combination**: You can combine all the above ways of mounting middleware.

```
function mw1(req, res, next) {
  next();
}
function mw2(req, res, next) {
  next();
}


var r1 = express.Router();
r1.get('/', function (req, res, next) {
  next();
});


var r2 = express.Router();
r2.get('/', function (req, res, next) {
  next();
});


var subApp = express();
subApp.get('/', function (req, res, next) {
  next();
});


app.use(mw1, [mw2, r1, r2], subApp);
```

```
import express, { type Express, type Request, type Response, type NextFunction } from 'express';


function mw1(req: Request, res: Response, next: NextFunction) {
  next();
}
function mw2(req: Request, res: Response, next: NextFunction) {
  next();
}


const r1 = express.Router();
r1.get('/', function (req: Request, res: Response, next: NextFunction) {
  next();
});


const r2 = express.Router();
r2.get('/', function (req: Request, res: Response, next: NextFunction) {
  next();
});


const subApp: Express = express();
subApp.get('/', function (req: Request, res: Response, next: NextFunction) {
  next();
});


app.use(mw1, [mw2, r1, r2], subApp);
```

Following are some examples of using the [express.static](/en/4x/guide/using-middleware/#built-in-middleware) middleware in an Express app.

Serve static content for the app from the “public” directory in the application directory:

```
// GET /style.css etc
app.use(express.static(path.join(__dirname, 'public')));
```

Mount the middleware at “/static” to serve static content only when their request path is prefixed with “/static”:

```
// GET /static/style.css etc.
app.use('/static', express.static(path.join(__dirname, 'public')));
```

Disable logging for static content requests by loading the logger middleware after the static middleware:

```
app.use(express.static(path.join(__dirname, 'public')));
app.use(logger());
```

Serve static files from multiple directories, but give precedence to ”./public” over the others:

```
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'files')));
app.use(express.static(path.join(__dirname, 'uploads')));
```

----
url: https://expressjs.com/en/blog/write-post
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/write-post)

# [How to write a blog post](#overview)

Express Technical Committee

[](https://x.com/intent/tweet?text=How%20to%20write%20a%20blog%20post\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2Fwrite-post%2F)[](https://bsky.app/intent/compose?text=How%20to%20write%20a%20blog%20post%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2Fwrite-post%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2Fwrite-post%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2Fwrite-post%2F\&text=How%20to%20write%20a%20blog%20post)[](https://wa.me/?text=How%20to%20write%20a%20blog%20post%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2Fwrite-post%2F)[](/feed.xml)

If you have an idea for a blog post, follow these steps to propose it and potentially get it published!

1. **Propose your post**

   Before taking the time to write a post, please confirm that we will be able to publish it. We’re looking for topics specifically related to Express, and so we want to pre-approve all posts. For the moment, this means we aren’t accepting any unsolicited posts. To propose a blog post, [open an issue](https://github.com/expressjs/expressjs.com/issues) entitled `Blog post proposal: <your idea>`.

2. **Fork the repository**

   If the Express TC accepts your proposal, start to write your post by forking the [expressjs.com](https://github.com/expressjs/expressjs.com) repository and cloning it to your local machine. Once you open a pull request, you’ll be able to preview your post on GitHub. See step six below.

> Optional: To run the site locally and preview your post before opening a PR, see the [setup instructions in the README](https://github.com/expressjs/expressjs.com?tab=readme-ov-file#expressjscom).

1. **Create a new file**

   Create a new file in the `src/content/blog` directory named using following the format: `YYYY-MM-DD-title.md`. The date prefix is used as the publication date unless you set a `date` field in the front matter (see below).

2. **Add the required front matter**

   Copy the following front matter, including the dotted lines, and paste it at the top of file you just created. Replace the placeholder values with as desired.

   ```
   ---
   title: <your-title>
   description: <description-of-your-post>
   date: YYYY-MM-DD
   tags: ['tag1', 'tag2']
   authors:
     - name: <your-name>
       github: <github-username>
   cover: <optional-cover-image-path>
   ---
   ```

   The `github` property of an author is optional. Including your username only (not your full profile URL) will ensure that your blog post links out to it.

   The `date` property is optional. When set, it determines the post’s publication date (used for ordering, display, and feeds); otherwise the `YYYY-MM-DD` prefix in the filename is used.

   The `cover` property is optional. If omitted, an Open Graph image will be automatically generated from the post title. If you want a custom cover image, place it in the `public` directory and reference its path (e.g. `/images/my-cover.jpg`).

3. **Add your content**

   Finally, start writing your content below the front matter. Use standard markdown formatting.

   **Using components (MDX)**

   If you need to use interactive components like alerts, callouts, or other UI elements inside your post, rename your file from `.md` to `.mdx`. MDX lets you import and use Astro components directly in your markdown.

   For example, to add an alert:

   ```
   ---
   title: My blog post
   description: A post with alerts
   tags: ['security']
   authors:
     - name: John Doe
       github: johndoe
   ---


   import Alert from '@components/primitives/Alert/Alert.astro';


   This is regular markdown content.


   <Alert type="warning">
     We strongly recommend upgrading to the latest version as soon as possible.
   </Alert>


   <Alert type="info">This feature is available starting from Express 5.0.</Alert>


   <Alert type="alert">
     This is a breaking change. Please review the migration guide before upgrading.
   </Alert>
   ```

   The available alert types are `info`, `warning`, and `alert`.

4. **Open a pull request (PR)**

   Once you open a PR, you will be able to preview your results: There will be a section on the page entitled `Deploy Preview for expressjscom-preview ready!` Click the link to see the site rendered from your fork/branch.

   You can use this feature over multiple commits to refine your post by making a `draft` pull request. Once it’s ready for review, switch it to a formal PR.

[security](/en/blog/2026-08-31-security-releases)

## [August 2026 Security Releases](/en/blog/2026-08-31-security-releases)

[Ulises GasconAugust 31, 2026](/en/blog/2026-08-31-security-releases)

----
url: https://expressjs.com/en/resources/middleware/morgan
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/pages/en/resources/middleware/morgan.mdx)

# [morgan middleware](#overview)

v1.12.1[GitHub](https://github.com/expressjs/morgan)[Changelog](https://github.com/expressjs/morgan/releases)[npm](https://www.npmjs.com/package/morgan)

HTTP request logger middleware for node.js

> Named after [Dexter](https://en.wikipedia.org/wiki/Dexter_Morgan), a show you should not watch until completion.

## [Installation](#installation)

This is a [Node.js](https://nodejs.org/en/) module available through the [npm registry](https://www.npmjs.com/). Installation is done using the [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):

Terminal window

```
npm install morgan
```

Terminal window

```
yarn add morgan
```

Terminal window

```
pnpm add morgan
```

Terminal window

```
bun add morgan
```

### Note

`morgan` does not include its own TypeScript type definitions. If you use TypeScript, also install the community-maintained types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) as a development dependency:

Terminal window

```
npm install --save-dev @types/morgan
```

Terminal window

```
yarn add --dev @types/morgan
```

Terminal window

```
pnpm add --save-dev @types/morgan
```

Terminal window

```
bun add --dev @types/morgan
```

## [API](#api)

For ES Modules:

```
import morgan from 'morgan';
```

For CommonJS:

```
var morgan = require('morgan');
```

### [morgan(format, options)](#morganformat-options)

Create a new morgan logger middleware function using the given `format` and `options`. The `format` argument may be a string of a predefined name (see below for the names), a string of a format string, or a function that will produce a log entry.

The `format` function will be called with three arguments `tokens`, `req`, and `res`, where `tokens` is an object with all defined tokens, `req` is the HTTP request and `res` is the HTTP response. The function is expected to return a string that will be the log line, or `undefined` / `null` to skip logging.

#### [Using a predefined format string](#using-a-predefined-format-string)

```
morgan('tiny');
```

#### [Using format string of predefined tokens](#using-format-string-of-predefined-tokens)

```
morgan(':method :url :status :res[content-length] - :response-time ms');
```

#### [Using a custom format function](#using-a-custom-format-function)

```
morgan(function (tokens, req, res) {
  return [
    tokens.method(req, res),
    tokens.url(req, res),
    tokens.status(req, res),
    tokens.res(req, res, 'content-length'),
    '-',
    tokens['response-time'](req, res),
    'ms',
  ].join(' ');
});
```

#### [Options](#options)

Morgan accepts these properties in the options object.

##### [immediate](#immediate)

Write log line on request instead of response. This means that requests will be logged even if the server crashes, *but data from the response (like the response code, content length, etc.) cannot be logged*.

##### [skip](#skip)

Function to determine if logging is skipped, defaults to `false`. This function will be called as `skip(req, res)`.

```
// EXAMPLE: only log error responses
morgan('combined', {
  skip: function (req, res) {
    return res.statusCode < 400;
  },
});
```

##### [stream](#stream)

Output stream for writing log lines, defaults to `process.stdout`.

If the stream is in object mode (`stream.writableObjectMode` is `true`) and the format function returns an object, the object is written to the stream as-is, without a trailing newline. This allows passing structured log entries to loggers that accept objects:

```
morgan(
  function (tokens, req, res) {
    return {
      method: tokens.method(req, res),
      url: tokens.url(req, res),
      status: Number(tokens.status(req, res)),
    };
  },
  {
    stream: {
      writableObjectMode: true,
      write: function (entry) {
        // entry is the object returned by the format function
      },
    },
  }
);
```

#### [Predefined Formats](#predefined-formats)

There are various pre-defined formats provided:

##### [combined](#combined)

Standard Apache combined log output.

```
:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"
# will output
::1 - - [27/Nov/2024:06:21:42 +0000] "GET /combined HTTP/1.1" 200 2 "-" "curl/8.7.1"
```

##### [common](#common)

Standard Apache common log output.

```
:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length]
# will output
::1 - - [27/Nov/2024:06:21:46 +0000] "GET /common HTTP/1.1" 200 2
```

##### [dev](#dev)

Concise output colored by response status for development use. The `:status` token will be colored green for success codes, red for server error codes, yellow for client error codes, cyan for redirection codes, and uncolored for information codes.

```
:method :url :status :response-time ms - :res[content-length]
# will output
GET /dev 200 0.224 ms - 2
```

Coloring is disabled when the [`NO_COLOR`](https://no-color.org) environment variable is set to any non-empty value, in which case the output above is written without any escape sequences. The variable is read once, when `morgan` is first required.

##### [short](#short)

Shorter than default, also including response time.

```
:remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms
# will output
::1 - GET /short HTTP/1.1 200 2 - 0.283 ms
```

##### [tiny](#tiny)

The minimal output.

```
:method :url :status :res[content-length] - :response-time ms
# will output
GET /tiny 200 2 - 0.188 ms
```

#### [Tokens](#tokens)

##### [Creating new tokens](#creating-new-tokens)

To define a token, simply invoke `morgan.token()` with the name and a callback function. This callback function is expected to return a string value. The value returned is then available as “:type” in this case:

```
morgan.token('type', function (req, res) {
  return req.headers['content-type'];
});
```

Calling `morgan.token()` using the same name as an existing token will overwrite that token definition.

The token function is expected to be called with the arguments `req` and `res`, representing the HTTP request and HTTP response. Additionally, the token can accept further arguments of its choosing to customize behavior.

##### [:date\[format\]](#dateformat)

The current date and time in UTC. The available formats are:

* `clf` for the common log format (`"10/Oct/2000:13:55:36 +0000"`)
* `iso` for the common ISO 8601 date time format (`2000-10-10T13:55:36.000Z`)
* `web` for the common RFC 1123 date time format (`Tue, 10 Oct 2000 13:55:36 GMT`)

If no format is given, then the default is `web`.

##### [:http-version](#http-version)

The HTTP version of the request.

##### [:method](#method)

The HTTP method of the request.

##### [:pid](#pid)

The process ID of the Node.js process handling the request.

##### [:referrer](#referrer)

The Referrer header of the request. This will use the standard mis-spelled Referer header if it exists, otherwise Referrer.

##### [:remote-addr](#remote-addr)

The remote address of the request. This will use `req.ip`, otherwise the standard `req.connection.remoteAddress` value (socket address).

##### [:remote-user](#remote-user)

The user authenticated as part of Basic auth for the request.

##### [:req\[header\]](#reqheader)

The given `header` of the request. If the header is not present, the value will be displayed as `"-"` in the log.

##### [:res\[header\]](#resheader)

The given `header` of the response. If the header is not present, the value will be displayed as `"-"` in the log.

##### [:response-time\[digits\]](#response-timedigits)

The time between the request coming into `morgan` and when the response headers are written, in milliseconds.

The `digits` argument is a number that specifies the number of digits to include on the number, defaulting to `3`, which provides microsecond precision.

##### [:status](#status)

The status code of the response.

If the request/response cycle completes before a response was sent to the client (for example, the TCP socket closed prematurely by a client aborting the request), then the status will be empty (displayed as `"-"` in the log).

##### [:total-time\[digits\]](#total-timedigits)

The time between the request coming into `morgan` and when the response has finished being written out to the connection, in milliseconds.

The `digits` argument is a number that specifies the number of digits to include on the number, defaulting to `3`, which provides microsecond precision.

##### [:url](#url)

The URL of the request. This will use `req.originalUrl` if it exists, otherwise `req.url`.

##### [:user-agent](#user-agent)

The contents of the User-Agent header of the request.

### [morgan.compile(format)](#morgancompileformat)

Compile a format string into a `format` function for use by `morgan`. A format string is a string that represents a single log line and can utilize token syntax. Tokens are referenced by `:token-name`. If tokens accept arguments, they can be passed using `[]`, for example: `:token-name[pretty]` would pass the string `'pretty'` as an argument to the token `token-name`.

The function returned from `morgan.compile` takes three arguments `tokens`, `req`, and `res`, where `tokens` is an object with all defined tokens, `req` is the HTTP request and `res` is the HTTP response. The function will return a string that will be the log line, or `undefined` / `null` to skip logging.

Normally formats are defined using `morgan.format(name, format)`, but for certain advanced uses, this compile function is directly available.

## [Examples](#examples)

### [express/connect](#expressconnect)

Sample app that will log all requests in the Apache combined format to STDOUT

```
var express = require('express');
var morgan = require('morgan');


var app = express();


app.use(morgan('combined'));


app.get('/', function (req, res) {
  res.send('hello, world!');
});
```

### [vanilla http server](#vanilla-http-server)

Sample app that will log all requests in the Apache combined format to STDOUT

```
var finalhandler = require('finalhandler');
var http = require('http');
var morgan = require('morgan');


// create "middleware"
var logger = morgan('combined');


http.createServer(function (req, res) {
  var done = finalhandler(req, res);
  logger(req, res, function (err) {
    if (err) return done(err);


    // respond to request
    res.setHeader('content-type', 'text/plain');
    res.end('hello, world!');
  });
});
```

### [write logs to a file](#write-logs-to-a-file)

#### [single file](#single-file)

Sample app that will log all requests in the Apache combined format to the file `access.log`.

```
var express = require('express');
var fs = require('fs');
var morgan = require('morgan');
var path = require('path');


var app = express();


// create a write stream (in append mode)
var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' });


// setup the logger
app.use(morgan('combined', { stream: accessLogStream }));


app.get('/', function (req, res) {
  res.send('hello, world!');
});
```

#### [log file rotation](#log-file-rotation)

Sample app that will log all requests in the Apache combined format to one log file per day in the `log/` directory using the [rotating-file-stream module](https://www.npmjs.com/package/rotating-file-stream).

```
var express = require('express');
var morgan = require('morgan');
var path = require('path');
var rfs = require('rotating-file-stream'); // version 2.x


var app = express();


// create a rotating write stream
var accessLogStream = rfs.createStream('access.log', {
  interval: '1d', // rotate daily
  path: path.join(__dirname, 'log'),
});


// setup the logger
app.use(morgan('combined', { stream: accessLogStream }));


app.get('/', function (req, res) {
  res.send('hello, world!');
});
```

### [split / dual logging](#split--dual-logging)

The `morgan` middleware can be used as many times as needed, enabling combinations like:

* Log entry on request and one on response
* Log all requests to file, but errors to console
* … and more!

Sample app that will log all requests to a file using Apache format, but error responses are logged to the console:

```
var express = require('express');
var fs = require('fs');
var morgan = require('morgan');
var path = require('path');


var app = express();


// log only 4xx and 5xx responses to console
app.use(
  morgan('dev', {
    skip: function (req, res) {
      return res.statusCode < 400;
    },
  })
);


// log all requests to access.log
app.use(
  morgan('common', {
    stream: fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' }),
  })
);


app.get('/', function (req, res) {
  res.send('hello, world!');
});
```

### [use custom token formats](#use-custom-token-formats)

Sample app that will use custom token formats. This adds an ID to all requests and displays it using the `:id` token.

```
var express = require('express');
var morgan = require('morgan');
var uuid = require('uuid');


morgan.token('id', function getId(req) {
  return req.id;
});


var app = express();


app.use(assignId);
app.use(morgan(':id :method :url :response-time'));


app.get('/', function (req, res) {
  res.send('hello, world!');
});


function assignId(req, res, next) {
  req.id = uuid.v4();
  next();
}
```

## [License](#license)

[MIT](https://github.com/expressjs/morgan/blob/HEAD/LICENSE)

----
url: https://expressjs.com/en/blog/3
----

# Blog

Stay tuned for details on new releases, enhancements, and everything you need to know to make the most of your Express applications. Let's dive into what's new!

[Security](/en/blog/2025-06-05-vulnerability-reporting-process-overhaul)

## [How Express.js Rebuilt Its Vulnerability Reporting Process](/en/blog/2025-06-05-vulnerability-reporting-process-overhaul)

[Ulises GascónJun 5, 2025](/en/blog/2025-06-05-vulnerability-reporting-process-overhaul)

[Security](/en/blog/2025-05-19-security-releases)

## [May 2025 Security Releases](/en/blog/2025-05-19-security-releases)

[Ulises GascónMay 19, 2025](/en/blog/2025-05-19-security-releases)

[Announcements](/en/blog/2025-05-16-express-cleanup-legacy-packages)

## [Spring Cleaning in Express.js: Deprecations and the Path Ahead](/en/blog/2025-05-16-express-cleanup-legacy-packages)

[Express Technical CommitteeMay 16, 2025](/en/blog/2025-05-16-express-cleanup-legacy-packages)

[Announcements](/en/blog/2025-03-31-v5-1-latest-release)

## [Express@5.1.0: Now the Default on npm with LTS Timeline](/en/blog/2025-03-31-v5-1-latest-release)

[Express Technical CommitteeMar 31, 2025](/en/blog/2025-03-31-v5-1-latest-release)

[Announcements](/en/blog/2025-01-09-rewind-2024-triumphs-and-2025-vision)

## [A New Chapter for Express.js: Triumphs of 2024 and an ambitious 2025](/en/blog/2025-01-09-rewind-2024-triumphs-and-2025-vision)

[Express Technical CommitteeJan 9, 2025](/en/blog/2025-01-09-rewind-2024-triumphs-and-2025-vision)

[SecurityAnnouncements](/en/blog/2024-10-22-security-audit-milestone-achievement)

## [Express.js Security Audit: A Milestone Achievement](/en/blog/2024-10-22-security-audit-milestone-achievement)

[Express Technical CommitteeOct 22, 2024](/en/blog/2024-10-22-security-audit-milestone-achievement)

----
url: https://expressjs.com/en/blog/2026-09-09-joining-the-openjs-cna-security-break
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2026-09-09-joining-the-openjs-cna-security-break)

security

# [Express is joining the OpenJS CNA coordinated break](#overview)

Express Security TeamSeptember 9, 2026

[](https://x.com/intent/tweet?text=Express%20is%20joining%20the%20OpenJS%20CNA%20coordinated%20break\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-09-09-joining-the-openjs-cna-security-break%2F)[](https://bsky.app/intent/compose?text=Express%20is%20joining%20the%20OpenJS%20CNA%20coordinated%20break%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-09-09-joining-the-openjs-cna-security-break%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-09-09-joining-the-openjs-cna-security-break%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-09-09-joining-the-openjs-cna-security-break%2F\&text=Express%20is%20joining%20the%20OpenJS%20CNA%20coordinated%20break)[](https://wa.me/?text=Express%20is%20joining%20the%20OpenJS%20CNA%20coordinated%20break%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2026-09-09-joining-the-openjs-cna-security-break%2F)[](/feed.xml)

The [OpenJS Foundation CNA](https://cna.openjsf.org/) is taking a [coordinated break from September 17 to October 6, 2026](https://openjsf.org/blog/the-openjs-foundation-cna-is-taking-a-coordinated-break), and setting a good example for the community while doing it. The Express security team is joining the pause for the same window. Their post explains the reasoning, and it matches what we see in the Express ecosystem firsthand.

## [What this means for Express](#what-this-means-for-express)

From September 17 to October 6, 2026:

* Triage, patch development, advisory validation, CVE assignment, and security releases are paused.
* Channels stay open, so you can still file reports, but please do not expect a response until we return on **October 7**.
* Where possible, please hold non urgent reports until after the break, and keep following coordinated disclosure.

**Emergency exception:** if a vulnerability is being actively exploited, or poses immediate and serious risk, we will still respond. Reach out in the **#express** channel on the [OpenJS Foundation Slack](https://slack-invite.openjsf.org/), keep the first message high level, and mark it urgent.

We will be back on **October 7, 2026**. Thank you for following coordinated disclosure.

To the maintainers who build on Express, and to the wider community: we hope you find your own moments to rest and recharge too.

The Express Security Team

## More from Express

[security](/en/blog/2026-09-30-security-releases)

## [September 2026 Security Releases](/en/blog/2026-09-30-security-releases)

[Ulises GasconSeptember 30, 2026](/en/blog/2026-09-30-security-releases)

----
url: https://expressjs.com/en/4x/api/
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/4x/api.mdx)

# [4.x API Reference](#overview)

This section provides an overview of the modules and APIs available in Express 4.x for building web applications and HTTP services.

index.cjs

```
var express = require('express');
var app = express();


app.get('/', function (req, res) {
  res.send('hello world');
});


app.listen(3000);
```

index.mjs

```
import express from 'express';


const app = express();


app.get('/', function (req, res) {
  res.send('hello world');
});


app.listen(3000);
```

index.ts

```
import express, { type Express, type Request, type Response } from 'express';


const app: Express = express();


app.get('/', function (req: Request, res: Response) {
  res.send('hello world');
});


app.listen(3000);
```

### Note

Express 4.x requires **Node.js 0.10.0 or higher**.

With express v4.x, you can define routes, configure middleware, and start handling HTTP requests using the application instance created by the `express()` function. The API is organized into the following sections:

### [express()](/en/4x/api/express/)

[Learn about the express() function, which creates an Express application.](/en/4x/api/express/)

### [Application Object](/en/4x/api/application/)

[Learn about the properties and methods of the Express 4.x application object.](/en/4x/api/application/)

### [Request Object](/en/4x/api/request/)

[Learn about the properties and methods of the Express 4.x request object.](/en/4x/api/request/)

### [Response Object](/en/4x/api/response/)

[Learn about the properties and methods of the Express 4.x response object.](/en/4x/api/response/)

### [Router](/en/4x/api/router/)

[Learn about the properties and methods of the Express 4.x router.](/en/4x/api/router/)

----
url: https://expressjs.com/en/blog/2025-01-09-rewind-2024-triumphs-and-2025-vision
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/blog/2025-01-09-rewind-2024-triumphs-and-2025-vision)

announcements

# [A New Chapter for Express.js: Triumphs of 2024 and an ambitious 2025](#overview)

Express Technical CommitteeJanuary 9, 2025

[](https://x.com/intent/tweet?text=A%20New%20Chapter%20for%20Express.js%3A%20Triumphs%20of%202024%20and%20an%20ambitious%202025\&url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-01-09-rewind-2024-triumphs-and-2025-vision%2F)[](https://bsky.app/intent/compose?text=A%20New%20Chapter%20for%20Express.js%3A%20Triumphs%20of%202024%20and%20an%20ambitious%202025%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-01-09-rewind-2024-triumphs-and-2025-vision%2F)[](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-01-09-rewind-2024-triumphs-and-2025-vision%2F)[](https://t.me/share/url?url=https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-01-09-rewind-2024-triumphs-and-2025-vision%2F\&text=A%20New%20Chapter%20for%20Express.js%3A%20Triumphs%20of%202024%20and%20an%20ambitious%202025)[](https://wa.me/?text=A%20New%20Chapter%20for%20Express.js%3A%20Triumphs%20of%202024%20and%20an%20ambitious%202025%20https%3A%2F%2Fexpressjs.com%2Fen%2Fblog%2F2025-01-09-rewind-2024-triumphs-and-2025-vision%2F)[](/feed.xml)

As we step into the new year, it’s almost impossible to ignore the unmistakable energy coursing through the Express.js community. The past twelve months have proven both foundational and forward-looking: an era of governance overhauls, technical triumphs, and security enhancements that not only shaped 2024 but also laid the groundwork for what promises to be a transformative 2025. In this long-form recap and forecast, we’ll journey through the story of Express.js with its evolution, its hurdles, and the new heights it’s poised to reach.

***

## [A Transformative 2024](#a-transformative-2024)

Few could have predicted just how pivotal 2024 would be for the Express.js project. From the revitalization of its governance structures to the unveiling of long-awaited features, it was a year that solidified the framework’s role as a mainstay in the Node.js ecosystem.

### [Governance and Community Milestones](#governance-and-community-milestones)

Central to the project’s growth was the [Express Forward Plan](https://github.com/expressjs/discussions/issues/160), devised to ensure strategic alignment and long-term sustainability. This year also saw the introduction of a new generation of Technical Committee (TC) members, each bringing fresh insights and energy to the community. Those members include [Blake Embrey](https://github.com/blakeembrey), [Chris de Almeida](https://github.com/ctcpip), [Jean Burellier](https://github.com/sheplu), [Jon Church](https://github.com/jonchurch), [Linus Unnebäck](https://github.com/LinusU), [Rand McKinney](https://github.com/crandmck), [Ulises Gascón](https://github.com/ulisesgascon), and [Wes Todd](https://github.com/wesleytodd). By defining a clear path and transparent processes, the community was able to collaborate on ambitious updates more cohesively than ever before. A revitalized release process further streamlined how new versions are planned and executed, eliminating much of the guesswork and inconsistent timing that had previously challenged contributors.

In parallel, the [Security Working Group](https://github.com/expressjs/discussions/issues/165) took shape. Express.js, widely recognized for its importance to the broader Node.js landscape, formally introduced a [security triage team](https://github.com/expressjs/security-wg#security-triage-team) dedicated to proactively identifying and resolving vulnerabilities. This forward-thinking approach was bolstered by the adoption of a [Threat Model for Express.js](https://github.com/expressjs/express/pull/5526), underscoring the project’s commitment to robust, future-proof security.

As if these achievements weren’t enough, Express.js proudly reached [Impact Project status](https://github.com/openjs-foundation/cross-project-council/pull/1404) under the OpenJS Foundation. This acknowledgment affirmed the significance of the framework to the JavaScript ecosystem and showcased the community’s tireless efforts in ensuring its enduring relevance.

### [Technical Advancements and the Release of Express 5.0](#technical-advancements-and-the-release-of-express-50)

Naturally, 2024 will forever be remembered as the year when Express.js finally introduced its much-anticipated [Express 5.0](/en/blog/2024-10-15-v5-release/). After more than a decade of community discussions and behind-the-scenes experimentation, this release brought modern features and a future-oriented architecture to the framework, acting as a catalyst for the next chapter of Express.js development.

But the story did not end there. Even before the release of Express 5.0 was fully established, the community had already begun charting the course for [Express 6.0](https://github.com/expressjs/discussions/issues/267), reflecting an unwavering commitment to innovation. Guiding critical decisions throughout 2024 were new [decision framework](https://github.com/expressjs/discussions/issues/285), which helped the Technical Committee tackle pressing matters such as [engine usage](https://github.com/expressjs/discussions/issues/286) and [dependency management](https://github.com/expressjs/discussions/issues/279). Collectively, these measures fostered transparency and agility, ensuring that Express.js continues to evolve in response to the community’s most urgent needs.

### [Maintenance, Tooling, and Collaboration](#maintenance-tooling-and-collaboration)

Express.js also deepened its relationship with the Node.js community by re-integrating into the [Node.js CITGM project](https://github.com/expressjs/express/issues/5489). This move ensured broader ecosystem compatibility and provided developers with further validation that they can rely on Express.js as a dependable cornerstone of their Node.js applications.

### [A Heightened Security Posture](#a-heightened-security-posture)

Above all, 2024 will stand out for Express.js’s vigorous approach to security. In partnership with the [OpenJS Foundation](https://openjsf.org/) and [OSTIF](https://ostif.org/), the project undertook a comprehensive [security audit](/en/blog/2024-10-22-security-audit-milestone-achievement/) that yielded critical insights and propelled immediate improvements. The sense of proactive vigilance extended to the adoption of the [OSSF Scorecard](https://github.com/expressjs/discussions/issues/162), implemented at an organizational level to keep track of security metrics and maintain focus on ongoing enhancements.

Throughout the year, maintainers rapidly responded to disclosed vulnerabilities such as [CVE-2024-43796](https://github.com/expressjs/express/security/advisories/GHSA-qw6h-vgh9-j6wx), [CVE-2024-45590](https://github.com/expressjs/body-parser/security/advisories/GHSA-qwcr-r2fm-qrc7), and [CVE-2024-47178](https://github.com/expressjs/basic-auth-connect/security/advisories/GHSA-7p89-p6hx-q4fw). Each instance underscored the community’s readiness to defend the framework’s integrity and safeguard its user base. In a further demonstration of long-term commitment, Express.js teamed up with [HeroDevs](https://www.herodevs.com/) to establish [Never-Ending Support (NES)](https://openjsf.org/blog/at-the-openjs-foundation-were-excited-to-announce-), offering an extended maintenance plan that reaffirms Express.js as a reliable foundation for developers now and in the years to come.

***

## [A Bold Vision for 2025](#a-bold-vision-for-2025)

While 2024 laid a sturdy bedrock, the Express.js Technical Committee is not resting on its laurels. The newly revealed roadmap for 2025—bolstered by the [Sovereign Tech Fund (STF)](https://www.sovereign.tech/)—embodies a spirit of forward momentum. It promises notable strides in security, performance, and general developer experience, with each initiative building on the insights gained over the past year.

### [Automating npm Releases](#automating-npm-releases)

At the forefront of this plan is the automation of npm releases, an endeavor designed to free maintainers from manual steps and human error. By streamlining the publishing process, the project can achieve faster turnaround times for patches and new features, preserving the stability that developers have come to expect from Express.js. It’s an internal shift with massive external benefits: smoother upgrades, more frequent releases, and a deeper reservoir of confidence for users.

### [Introducing Scoped Packages](#introducing-scoped-packages)

Express.js will also explore a transition toward scoped packages. By clearly delineating which modules fall under the Express.js umbrella, the maintainers hope to reduce confusion and foster an environment more conducive to organized expansion. As new packages and features are proposed, scoping will make it simpler to track official tools and ensure that community contributions meet consistent quality standards.

### [Strengthening Security Reporting and Procedures](#strengthening-security-reporting-and-procedures)

Since security remains one of the project’s primary pillars, 2025 will see a significant push to refine how vulnerabilities are reported and managed. Building upon the success of the Security Working Group, the new process will introduce transparent guidelines for reporting potential issues and a consistent triage routine for mitigating them. Additional training for both the Security Triage group and the Technical Committee will further cultivate a shared culture of readiness. Moreover, Express.js is poised to integrate [OSSF Scorecard](https://github.com/expressjs/discussions/issues/162) even more deeply into daily operations, ensuring that both maintainers and users have real-time insights into the project’s health.

### [Performance Monitoring and Deep-Level Optimizations](#performance-monitoring-and-deep-level-optimizations)

Performance is another focal point. By systematically monitoring the framework’s speed and responsiveness—along with that of its dependencies—the Express.js team aims to pinpoint bottlenecks more rapidly. Over time, insights from these monitoring efforts will drive deeper optimizations in the core Express.js code and its core libraries. These improvements, expected to come to fruition by mid-2026, promise a faster, more scalable framework that can handle the heaviest production workloads with ease.

### [Phasing Out Legacy Techniques and Enhancing Documentation](#phasing-out-legacy-techniques-and-enhancing-documentation)

A future of agility and resilience depends on eliminating outdated techniques that invite complexity and fragility. As a result, Express.js will begin phasing out monkey-patching and passthrough APIs that rely too heavily on Node.js internals. This modernization strategy not only reduces technical debt but also ensures that Express.js remains aligned with Node.js updates going forward.

In tandem, the project will make a concerted effort to bolster its security documentation. Through updated guides and best practices, maintainers hope to demystify crucial topics like secure session handling, input validation, and access control. The goal is to arm developers—from novices to seasoned engineers—with the knowledge they need to protect their applications against an ever-evolving threat landscape.

***

## [The Road Ahead](#the-road-ahead)

As Express.js steps into 2025, it does so with a powerful sense of purpose. The achievements of the past year—culminating in the official release of Express 5.0 and wide-reaching governance enhancements—serve as a sturdy foundation for what’s to come. Yet, the framework’s leadership knows there is always more to build, more to secure, and more to imagine.

Through automated releases, scopes for packages, rigorous security protocols, performance monitoring, and an ongoing effort to modernize core APIs, Express.js is evolving in real-time. And it isn’t just about technology; it’s about forging a collaborative environment where contributors can rely on transparent processes, robust training, and a supportive governance structure.

Whether you’re a seasoned maintainer, an occasional contributor, or a newcomer to this thriving ecosystem, your voice matters. Join the [Express.js GitHub Discussions](https://github.com/expressjs/discussions), attend open meetings, and stay tuned for updates on [Express.js blog](https://expressjs.com/) as we finalize timetables for these initiatives. Each advancement, no matter how technical, flows from a common aspiration: to sustain Express.js as a fast, safe, and influential framework for millions of developers worldwide. Together, we’ll keep the spirit of 2024 alive—pushing boundaries, refining practices, and laying the path to a future where Express.js remains at the heart of modern web development.

----
url: https://expressjs.com/en/5x/api/router
----

[Edit on GitHub](https://github.com/expressjs/expressjs.com/edit/main/src/content/api/5x/api/router/index.mdx)

# [Router](#overview)

A `router` object is an instance of middleware and routes. You can think of it as a “mini-application,” capable only of performing middleware and routing functions. Every Express application has a built-in app router.

A router behaves like middleware itself, so you can use it as an argument to [app.use()](/en/5x/api/application/#appuse) or as the argument to another router’s [use()](#routeruse) method.

The top-level `express` object has a [Router()](/en/5x/api/express/#expressrouter) method that creates a new `router` object.

Once you’ve created a router object, you can add middleware and HTTP method routes (such as `get`, `put`, `post`, and so on) to it just like an application. For example:

```
// invoked for any requests passed to this router
router.use((req, res, next) => {
  // .. some logic here .. like any other middleware
  next();
});


// will handle any request that ends in /events
// depends on where the router is "use()'d"
router.get('/events', (req, res, next) => {
  // ..
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


// invoked for any requests passed to this router
router.use((req: Request, res: Response, next: NextFunction) => {
  // .. some logic here .. like any other middleware
  next();
});


// will handle any request that ends in /events
// depends on where the router is "use()'d"
router.get('/events', (req: Request, res: Response, next: NextFunction) => {
  // ..
});
```

You can then use a router for a particular root URL in this way separating your routes into files or even mini-apps.

```
// only requests to /calendar/* will be sent to our "router"
app.use('/calendar', router);
```

```
const express = require('express');
const router = express.Router({ caseSensitive: true, strict: true });


router.get('/events', (req, res) => {
  res.send('events');
});


// mount the router on an app
app.use('/calendar', router);
```

index.mjs

```
import express from 'express';


const router = express.Router({ caseSensitive: true, strict: true });


router.get('/events', (req, res) => {
  res.send('events');
});


// mount the router on an app
app.use('/calendar', router);
```

index.ts

```
import express, { type Request, type Response } from 'express';


const router = express.Router({ caseSensitive: true, strict: true });


router.get('/events', (req: Request, res: Response) => {
  res.send('events');
});


// mount the router on an app
app.use('/calendar', router);
```

```
router.all('{*splat}', requireAuthentication, loadUser);
```

Or the equivalent:

```
router.all('{*splat}', requireAuthentication);
router.all('{*splat}', loadUser);
```

Another example of this is white-listed “global” functionality. Here, the example is much like before, but it only restricts paths prefixed with “/api”:

```
router.all('/api/{*splat}', requireAuthentication);
```

`router.query()` routes HTTP `QUERY` requests, mirroring [`app.query()`](/en/5x/api/application/#appquery). The `QUERY` method is gated by the runtime and requires Node.js `>=20.19.3 <21 || >=22.2.0`.

You can provide multiple callbacks, and all are treated equally, and behave just like middleware, except that these callbacks may invoke `next('route')` to bypass the remaining route callback(s). You can use this mechanism to perform pre-conditions on a route then pass control to subsequent routes when there is no reason to proceed with the route matched.

The following snippet illustrates the most simple route definition possible. Express translates the path strings to regular expressions, used internally to match incoming requests. Query strings are *not* considered when performing these matches, for example “GET /” would match the following route, as would “GET /?name=tobi”.

```
router.get('/', (req, res) => {
  res.send('hello world');
});
```

```
import { type Request, type Response } from 'express';


router.get('/', (req: Request, res: Response) => {
  res.send('hello world');
});
```

You can also use regular expressions—useful if you have very specific constraints, for example the following would match “GET /commits/71dbb9c” as well as “GET /commits/71dbb9c..4c084f9”.

```
router.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/, (req, res) => {
  const from = req.params[0];
  const to = req.params[1] || 'HEAD';
  res.send(`commit range ${from}..${to}`);
});
```

```
import { type Request, type Response } from 'express';


router.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/, (req: Request, res: Response) => {
  const from = req.params[0];
  const to = req.params[1] || 'HEAD';
  res.send(`commit range ${from}..${to}`);
});
```

You can use `next` primitive to implement a flow control between different middleware functions, based on a specific program state. Invoking `next` with the string `'router'` will cause all the remaining route callbacks on that router to be bypassed.

The following example illustrates `next('router')` usage.

```
function fn(req, res, next) {
  console.log('I come here');
  next('router');
}
router.get('/foo', fn, (req, res, next) => {
  console.log("I don't come here");
});
router.get('/foo', (req, res, next) => {
  console.log("I don't come here");
});
app.get('/foo', (req, res) => {
  console.log(' I come here too');
  res.end('good');
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


function fn(req: Request, res: Response, next: NextFunction) {
  console.log('I come here');
  next('router');
}
router.get('/foo', fn, (req: Request, res: Response, next: NextFunction) => {
  console.log("I don't come here");
});
router.get('/foo', (req: Request, res: Response, next: NextFunction) => {
  console.log("I don't come here");
});
app.get('/foo', (req: Request, res: Response) => {
  console.log(' I come here too');
  res.end('good');
});
```

Adds callback triggers to route parameters, where `name` is the name of the parameter and `callback` is the callback function. The `name` parameter is required.

```
router.param('user', (req, res, next, id) => {
  // try to get the user details from the User model and attach it to the request object
  User.find(id, (err, user) => {
    if (err) {
      next(err);
    } else if (user) {
      req.user = user;
      next();
    } else {
      next(new Error('failed to load user'));
    }
  });
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


router.param('user', (req: Request, res: Response, next: NextFunction, id: string) => {
  // try to get the user details from the User model and attach it to the request object
  User.find(id, (err, user) => {
    if (err) {
      next(err);
    } else if (user) {
      req.user = user;
      next();
    } else {
      next(new Error('failed to load user'));
    }
  });
});
```

Param callback functions are local to the router on which they are defined. They are not inherited by mounted apps or routers, nor are they triggered for route parameters inherited from parent routers. Hence, param callbacks defined on `router` will be triggered only by route parameters defined on `router` routes.

A param callback will be called only once in a request-response cycle, even if the parameter is matched in multiple routes, as shown in the following examples.

```
router.param('id', (req, res, next, id) => {
  console.log('CALLED ONLY ONCE');
  next();
});


router.get('/user/:id', (req, res, next) => {
  console.log('although this matches');
  next();
});


router.get('/user/:id', (req, res) => {
  console.log('and this matches too');
  res.end();
});
```

```
import { type Request, type Response, type NextFunction } from 'express';


router.param('id', (req: Request, res: Response, next: NextFunction, id: string) => {
  console.log('CALLED ONLY ONCE');
  next();
});


router.get('/user/:id', (req: Request, res: Response, next: NextFunction) => {
  console.log('although this matches');
  next();
});


router.get('/user/:id', (req: Request, res: Response) => {
  console.log('and this matches too');
  res.end();
});
```

On `GET /user/42`, the following is printed:

```
CALLED ONLY ONCE
although this matches
and this matches too
```

```
const router = express.Router();


router.param('user_id', (req, res, next, id) => {
  // sample user, would actually fetch from DB, etc...
  req.user = {
    id,
    name: 'TJ',
  };
  next();
});


router
  .route('/users/:user_id')
  .all((req, res, next) => {
    // runs for all HTTP verbs first
    // think of it as route specific middleware!
    next();
  })
  .get((req, res, next) => {
    res.json(req.user);
  })
  .put((req, res, next) => {
    // just an example of maybe updating the user
    req.user.name = req.params.name;
    // save user ... etc
    res.json(req.user);
  })
  .post((req, res, next) => {
    next(new Error('not implemented'));
  })
  .delete((req, res, next) => {
    next(new Error('not implemented'));
  });
```

index.ts

```
import express, { type Request, type Response, type NextFunction } from 'express';


const router = express.Router();


router.param('user_id', (req: Request, res: Response, next: NextFunction, id: string) => {
  // sample user, would actually fetch from DB, etc...
  req.user = {
    id,
    name: 'TJ',
  };
  next();
});


router
  .route('/users/:user_id')
  .all((req: Request, res: Response, next: NextFunction) => {
    // runs for all HTTP verbs first
    // think of it as route specific middleware!
    next();
  })
  .get((req: Request, res: Response, next: NextFunction) => {
    res.json(req.user);
  })
  .put((req: Request, res: Response, next: NextFunction) => {
    // just an example of maybe updating the user
    req.user.name = req.params.name;
    // save user ... etc
    res.json(req.user);
  })
  .post((req: Request, res: Response, next: NextFunction) => {
    next(new Error('not implemented'));
  })
  .delete((req: Request, res: Response, next: NextFunction) => {
    next(new Error('not implemented'));
  });
```

This method is similar to [app.use()](/en/5x/api/application/#appuse). A simple example and use case is described below. See [app.use()](/en/5x/api/application/#appuse) for more information.

Middleware is like a plumbing pipe: requests start at the first middleware function defined and work their way “down” the middleware stack processing for each path they match.

index.cjs

```
const express = require('express');
const app = express();
const router = express.Router();


// simple logger for this router's requests
// all requests to this router will first hit this middleware
router.use((req, res, next) => {
  console.log('%s %s %s', req.method, req.url, req.path);
  next();
});


// this will only be invoked if the path starts with /bar from the mount point
router.use('/bar', (req, res, next) => {
  // ... maybe some additional /bar logging ...
  next();
});


// always invoked
router.use((req, res, next) => {
  res.send('Hello World');
});


app.use('/foo', router);


app.listen(3000);
```

index.mjs

```
import express from 'express';


const app = express();
const router = express.Router();


// simple logger for this router's requests
// all requests to this router will first hit this middleware
router.use((req, res, next) => {
  console.log('%s %s %s', req.method, req.url, req.path);
  next();
});


// this will only be invoked if the path starts with /bar from the mount point
router.use('/bar', (req, res, next) => {
  // ... maybe some additional /bar logging ...
  next();
});


// always invoked
router.use((req, res, next) => {
  res.send('Hello World');
});


app.use('/foo', router);


app.listen(3000);
```

index.ts

```
import express, { type Request, type Response, type NextFunction } from 'express';


const app = express();
const router = express.Router();


// simple logger for this router's requests
// all requests to this router will first hit this middleware
router.use((req: Request, res: Response, next: NextFunction) => {
  console.log('%s %s %s', req.method, req.url, req.path);
  next();
});


// this will only be invoked if the path starts with /bar from the mount point
router.use('/bar', (req: Request, res: Response, next: NextFunction) => {
  // ... maybe some additional /bar logging ...
  next();
});


// always invoked
router.use((req: Request, res: Response, next: NextFunction) => {
  res.send('Hello World');
});


app.use('/foo', router);


app.listen(3000);
```

The “mount” path is stripped and is *not* visible to the middleware function. The main effect of this feature is that a mounted middleware function may operate without code changes regardless of its “prefix” pathname.

The order in which you define middleware with `router.use()` is very important. They are invoked sequentially, thus the order defines middleware precedence. For example, usually a logger is the very first middleware you would use, so that every request gets logged.

index.cjs

```
const logger = require('morgan');


router.use(logger());
router.use(express.static(path.join(__dirname, 'public')));
router.use((req, res) => {
  res.send('Hello');
});
```

index.mjs

```
import logger from 'morgan';


router.use(logger());
router.use(express.static(path.join(__dirname, 'public')));
router.use((req, res) => {
  res.send('Hello');
});
```

index.ts

```
import logger from 'morgan';
import { type Request, type Response } from 'express';


router.use(logger());
router.use(express.static(path.join(__dirname, 'public')));
router.use((req: Request, res: Response) => {
  res.send('Hello');
});
```

Now suppose you wanted to ignore logging requests for static files, but to continue logging routes and middleware defined after `logger()`. You would simply move the call to `express.static()` to the top, before adding the logger middleware:

```
router.use(express.static(path.join(__dirname, 'public')));
router.use(logger());
router.use((req, res) => {
  res.send('Hello');
});
```

```
import { type Request, type Response } from 'express';


router.use(express.static(path.join(__dirname, 'public')));
router.use(logger());
router.use((req: Request, res: Response) => {
  res.send('Hello');
});
```

Another example is serving files from multiple directories, giving precedence to ”./public” over the others:

```
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'files')));
app.use(express.static(path.join(__dirname, 'uploads')));
```

The `router.use()` method also supports named parameters so that your mount points for other routers can benefit from preloading using named parameters.

### Note

Although these middleware functions are added via a particular router, *when* they run is defined by the path they are attached to (not the router). Therefore, middleware added via one router may run for other routers if its routes match.

For example, this code shows two different routers mounted on the same path:

```
const authRouter = express.Router();
const openRouter = express.Router();


authRouter.use(require('./authenticate').basic(usersdb));


authRouter.get('/:user_id/edit', (req, res, next) => {
  // ... Edit user UI ...
});
openRouter.get('/', (req, res, next) => {
  // ... List users ...
});
openRouter.get('/:user_id', (req, res, next) => {
  // ... View user ...
});


app.use('/users', authRouter);
app.use('/users', openRouter);
```

```
import express, { type Request, type Response, type NextFunction } from 'express';
import { basic } from './authenticate';


const authRouter = express.Router();
const openRouter = express.Router();


authRouter.use(basic(usersdb));


authRouter.get('/:user_id/edit', (req: Request, res: Response, next: NextFunction) => {
  // ... Edit user UI ...
});
openRouter.get('/', (req: Request, res: Response, next: NextFunction) => {
  // ... List users ...
});
openRouter.get('/:user_id', (req: Request, res: Response, next: NextFunction) => {
  // ... View user ...
});


app.use('/users', authRouter);
app.use('/users', openRouter);
```

Even though the authentication middleware was added via the `authRouter` it will run on the routes defined by the `openRouter` as well since both routers were mounted on `/users`. To avoid this behavior, use different paths for each router.