Skip to main content

Middlewares configuration

🤓 Different types of middlewares

In Strapi, 2 middleware concepts coexist:

  • Strapi middlewares are configured and enabled as global middlewares for the entire Strapi server application. The present documentation describes how to configure Strapi middlewares.
    Strapi also offers the ability to implement your own custom middlewares (see middlewares customization documentation).

  • Route middlewares have a more limited scope and are configured and used as middlewares at the route level. They are described in the route middlewares documentation.

The ./config/middlewares.js file is used to define all the Strapi middlewares that should be applied by the Strapi server.

Only the middlewares present in ./config/middlewares.js are applied. Loading middlewares happens in a specific loading order, with some naming conventions and an optional configuration for each middleware.

Strapi pre-populates the ./config/middlewares.js file with built-in, internal middlewares that all have their own configuration options.

Loading order

The ./config/middlewares.js file exports an array, where order matters and controls the execution order of the middleware stack:

./config/middlewares.js

module.exports = [
// The array is pre-populated with internal, built-in middlewares, prefixed by `strapi::`
'strapi::errors',
'strapi::security',
'strapi::cors',

// custom middleware that does not require any configuration
'my-custom-node-module',

// custom name to find a package or a path
{
name: 'my-custom-node-module',
config: {
foo: 'bar',
},
},

// custom resolve to find a package or a path
{
resolve: '../some-dir/custom-middleware',
config: {
foo: 'bar',
},
},

// custom configuration for internal middleware
{
name: 'strapi::poweredBy',
config: {
poweredBy: 'Some awesome company',
},
},

// remaining internal & built-in middlewares
'strapi::logger',
'strapi::query',
'strapi::body',
'strapi::session',
'strapi::favicon',
'strapi::public',
];
tip

If you aren't sure where to place a middleware in the stack, add it to the end of the list.

Naming conventions

Strapi middlewares can be classified into different types depending on their origin, which defines the following naming conventions:

Middleware typeOriginNaming convention
InternalBuilt-in middlewares (i.e. included with Strapi), automatically loadedstrapi::middleware-name
Application-levelLoaded from the ./src/middlewares folderglobal::middleware-name
API-levelLoaded from the ./src/api/[api-name]/middlewares folderapi::api-name.middleware-name
PluginExported from strapi-server.js in the middlewares property of the plugin interfaceplugin::plugin-name.middleware-name
ExternalCan be:
  • either node modules installed with npm
  • or local middlewares (i.e. custom middlewares created locally and configured in ./config/middlewares.js.)
-

As they are directly configured and resolved from the configuration file, they have no naming convention.

Optional configuration

Middlewares can have an optional configuration with the following parameters:

ParameterDescriptionType
configUsed to define or override the middleware configurationObject
resolvePath to the middleware's folder (useful for external middlewares)String

Internal middlewares configuration reference

Strapi's core includes the following internal middlewares, mostly used for performances, security and error handling:

MiddlewareAdded by DefaultRequired
bodyYesYes
compressionNoNo
corsYesYes
errorsYesYes
faviconYesYes
ipNoNo
loggerYesNo
poweredByYesNo
queryYesYes
response-timeNoNo
responsesYesYes
publicYesYes
securityYesYes
sessionYesNo

body

The body middleware is based on koa-body. It accepts the following options:

OptionDescriptionTypeDefault
multipartParse multipart bodiesBooleantrue
patchKoaPatch request body to Koa's ctx.requestBooleantrue
jsonLimitThe byte (if integer) limit of the JSON bodyString or Integer1mb
formLimitThe byte (if integer) limit of the form bodyString or Integer56kb
textLimitThe byte (if integer) limit of the text bodyString or Integer56kb
encodingSets encoding for incoming form fieldsStringutf-8
formidableOptions to pass to the formidable multipart parser (see node-formidable documentation).Objectundefined

For a full list of available options for koa-body, check the koa-body documentation.

Example: Custom configuration for the body middleware
./config/middlewares.js

module.exports = [
// ...
{
name: 'strapi::body',
config: {
jsonLimit: '3mb',
formLimit: '10mb',
textLimit: '256kb',
encoding: 'gbk',
},
},
// ...
]

compression

The compression middleware is based on koa-compress. It accepts the following options:

OptionDescriptionTypeDefault
thresholdMinimum response size in bytes to compressString or Integer1kb
brToggle Brotli compressionBooleantrue
gzipToggle gzip compressionBooleanfalse
deflateToggle deflate compressionBooleanfalse
defaultEncodingSpecifies what encoders to use for requests without Accept-Encoding headerStringidentity
Example: Custom configuration for the compression middleware
./config/middlewares.js

module.exports = [
// ...
{
name: 'strapi::compression',
config: {
br: false
},
},
// ...
]

cors

This security middleware is about cross-origin resource sharing (CORS) and is based on @koa/cors. It accepts the following options:

OptionTypeDescriptionDefault value
originConfigure the Access-Control-Allow-Origin headerString or Array'*'
maxAgeConfigure the Access-Control-Max-Age header, in secondsString or Number31536000
credentialsConfigure the Access-Control-Allow-Credentials headerBooleantrue
methodsConfigure the Access-Control-Allow-Methods headerArray or String['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS']
headersConfigure the Access-Control-Allow-Headers headerArray or StringRequest headers passed in Access-Control-Request-Headers
keepHeaderOnErrorAdd set headers to err.header if an error is thrownBooleanfalse
Example: Custom configuration for the cors middleware
./config/middlewares.js

module.exports = [
// ...
{
name: 'strapi::cors',
config: {
origin: ['example.com', 'subdomain.example.com', 'someotherwebsite.org'],
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
headers: ['Content-Type', 'Authorization', 'Origin', 'Accept'],
keepHeaderOnError: true,
},
},
// ...
]

errors

The errors middleware handles errors thrown by the code. Based on the type of error it sets the appropriate HTTP status to the response. By default, any error not supposed to be exposed to the end user will result in a 500 HTTP response.

The middleware doesn't have any configuration options.

favicon

The favicon middleware serves the favicon and is based on koa-favicon. It accepts the following options:

OptionDescriptionTypeDefault value
pathPath to the favicon fileString'favicon.ico'
maxAgeCache-control max-age directive, in millisecondsInteger86400000
Example: Custom configuration for the favicon middleware
./config/middlewares.js

module.exports = [
// ...
{
name: 'strapi::favicon',
config: {
path: './public/uploads/custom-fav-abc123.ico'
},
},
// ...
]

ip

The ip middleware is an IP filter middleware based on koa-ip. It accepts the following options:

OptionDescriptionTypeDefault value
whitelistWhitelisted IPsArray[]
blacklistBlacklisted IPsArray[]
tip

The whitelist and blacklist options support wildcards (e.g. whitelist: ['192.168.0.*', '127.0.0.*']) and spreads (e.g. whitelist: ['192.168.*.[3-10]']).

Example: Custom configuration for the ip middleware
./config/middlewares.js

module.exports = [
// ...
{
name: 'strapi::ip',
config: {
whitelist: ['192.168.0.*', '192.168.1.*', '123.123.123.123'],
blacklist: ['1.116.*.*', '103.54.*.*'],
},
},
// ...
]

logger

The logger middleware is used to log requests.

To define a custom configuration for the logger middleware, create a dedicated configuration file (./config/logger.js). It should export an object that must be a complete or partial winstonjs logger configuration. The object will be merged with Strapi's default logger configuration on server start.

Example: Custom configuration for the logger middleware
./config/logger.js

'use strict';

const {
winston,
formats: { prettyPrint, levelFilter },
} = require('@strapi/logger');

module.exports = [
transports: [
new winston.transports.Console({
level: 'http',
format: winston.format.combine(
levelFilter('http'),
prettyPrint({ timestamps: 'YYYY-MM-DD hh:mm:ss.SSS' })
),
}),
],
];

poweredBy

The poweredBy middleware adds a X-Powered-By parameter to the response header. It accepts the following options:

OptionDescriptionTypeDefault value
poweredByValue of the X-Powered-By headerString'Strapi <strapi.io>'
details Example: Custom configuration for the poweredBy middleware
./config/middlewares.js

module.exports = [
// ...
{
name: 'strapi::poweredBy',
config: {
poweredBy: 'Some Awesome Company <example.com>'
},
},
// ...
]

query

The query middleware is a query parser based on qs. It accepts the following options:

OptionDescriptionTypeDefault value
strictNullHandlingDistinguish between null values and empty strings (see qs documentation)Booleantrue
arrayLimitMaximum index limit when parsing arrays (see qs documentation)Number100
depthMaximum depth of nested objects when parsing objects (see qs documentation)Number20
Example: Custom configuration for the query middleware
./config/middlewares.js

module.exports = [
// ...
{
name: 'strapi::query',
config: {
arrayLimit: 50,
depth: 10,
},
},
// ...
]

response-time

The response-time middleware enables the X-Response-Time (in milliseconds) for the response header.

The middleware doesn't have any configuration options.

public

The public middleware is a static file serving middleware, based on koa-static. It accepts the following options:

OptionDescriptionTypeDefault value
maxAgeCache-control max-age directive, in millisecondsInteger60000
hiddenAllow transfer of hidden filesBooleanfalse
deferIf true, serves after return next(), allowing any downstream middleware to respond firstBooleanfalse
indexDefault file nameStringindex.html
defaultIndexDisplay default index page at / and /index.htmlBooleantrue
tip

You can customize the path of the public folder by editing the server configuration file.

Example: Custom configuration for the public middleware
./config/middlewares.js

module.exports = [
// ...
{
name: 'strapi::public',
config: {
defer: true,
index: env('INDEX_PATH', 'index-dev.html')
},
},
// ...
]

security

The security middleware is based on koa-helmet. It accepts the following options:

OptionDescriptionTypeDefault value
crossOriginEmbedderPolicySet the Cross-Origin-Embedder-Policy header to require-corpBooleanfalse
crossOriginOpenerPolicySet the Cross-Origin-Opener-Policy headerBooleanfalse
crossOriginResourcePolicySet the Cross-Origin-Resource-Policy headerBooleanfalse
originAgentClusterSet the Origin-Agent-Cluster headerBooleanfalse
contentSecurityPolicySet the Content-Security-Policy headerObject-
xssFilterDisable browsers' cross-site scripting filter by setting the X-XSS-Protection header to 0Booleanfalse
hstsSet options for the HTTP Strict Transport Security (HSTS) policy.Object-
hsts.maxAgeNumber of seconds HSTS is in effectInteger31536000
hsts.includeSubDomainsApplies HSTS to all subdomains of the hostBooleantrue
frameguardSet X-Frame-Options header to help mitigate clickjacking attacks, set to false to disableBoolean or Object-
frameguard.actionValue must be either deny or sameoriginStringsameorigin
tip

When using any 3rd party upload provider, generally it's required to set a custom configuration here. Please see the provider documentation for which configuration options are required.

note

The default directives include a dl.airtable.com value. This value is set for the in-app market and is safe to keep.

Example: Custom configuration for the security middleware for using the AWS-S3 provider
./config/middlewares.js

module.exports = [
// ...
{
name: 'strapi::security',
config: {
contentSecurityPolicy: {
useDefaults: true,
directives: {
'connect-src': ["'self'", 'https:'],
'img-src': [
"'self'",
'data:',
'blob:',
'dl.airtable.com',
'yourBucketName.s3.yourRegion.amazonaws.com',
],
'media-src': [
"'self'",
'data:',
'blob:',
'dl.airtable.com',
'yourBucketName.s3.yourRegion.amazonaws.com',
],
upgradeInsecureRequests: null,
},
},
},
},
// ...
]

session

The session middleware allows the use of cookie-based sessions, based on koa-session. It accepts the following options:

OptionDescriptionTypeDefault value
keyCookie keyString'koa.sess'
maxAgeMaximum lifetime of the cookies, in milliseconds. Using 'session' will expire the cookie when the session is closed.Integer or 'session'86400000
autoCommitAutomatically commit headersBooleantrue
overwriteCan overwrite or notBooleantrue
httpOnlyIs httpOnly or not. Using httpOnly helps mitigate cross-site scripting (XSS) attacks.Booleantrue
signedSign the cookiesBooleantrue
rollingForce a session identifier cookie to be set on every response.Booleanfalse
renewRenew the session when the session is nearly expired, so the user keeps being logged in.Booleanfalse
secureForce the use of HTTPSBooleantrue in production, false otherwise
sameSiteRestrict the cookies to a first-party or same-site contextStringnull
Example: Custom configuration for the session middleware
./config/middlewares.js

module.exports = [
// ...
{
name: 'strapi::session',
config: {
rolling: true
renew: true
},
},
// ...
]