中间件配置
🌐 Middlewares configuration
Page summary:
/config/middlewares下达全局中间件,启用自定义名称或解析,并公开内置配置选项。
在 Strapi 中,3 个中间件概念共存:
🌐 In Strapi, 3 middleware concepts coexist:
- 全局中间件 是为整个 Strapi 服务器应用配置和启用的。这些中间件可以应用于应用级别或 API 级别。
本指南描述了如何实现它们。
插件也可以添加全局中间件(参见服务器 API 文档)。 - 路由中间件 的作用范围更有限,并且作为路由级别的中间件进行配置和使用。它们在 路由文档 中有描述。
- 文档服务中间件 适用于文档服务 API,并且有其自己的 实现 和相关的 生命周期钩子。
./config/middlewares.js 文件用于定义 Strapi 服务器应该应用的所有全局中间件。
🌐 The ./config/middlewares.js file is used to define all the global middlewares that should be applied by the Strapi server.
只有存在于 ./config/middlewares.js 的中间件会被应用。中间件的加载遵循特定的 加载顺序,每个中间件都有一些 命名约定 和 可选配置。
🌐 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 会使用内置的内部中间件预先填充 ./config/middlewares.js 文件,每个中间件都有自己的 配置选项。
🌐 Strapi pre-populates the ./config/middlewares.js file with built-in, internal middlewares that all have their own configuration options.
加载顺序
🌐 Loading order
./config/middlewares.js 文件导出一个数组,其中顺序很重要,并控制中间件堆栈的执行顺序:
🌐 The ./config/middlewares.js file exports an array, where order matters and controls the execution order of the middleware stack:
- JavaScript
- TypeScript
module.exports = [
// The array is pre-populated with internal, built-in middlewares, prefixed by `strapi::`
'strapi::logger',
'strapi::errors',
'strapi::security',
'strapi::cors',
// custom middleware that does not require any configuration
'global::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::query',
'strapi::body',
'strapi::session',
'strapi::favicon',
'strapi::public',
];
export default [
// The array is pre-populated with internal, built-in middlewares, prefixed by `strapi::`
'strapi::logger',
'strapi::cors',
'strapi::body',
'strapi::errors',
// ...
'my-custom-node-module', // custom middleware that does not require any configuration
{
// 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',
},
},
];
如果你不确定将中间件放置在堆栈中的位置,请将其添加到列表的末尾。
🌐 If you aren't sure where to place a middleware in the stack, add it to the end of the list.
命名规范
🌐 Naming conventions
全局中间件根据其来源可以分为不同类型,定义了以下命名约定:
🌐 Global middlewares can be classified into different types depending on their origin, which defines the following naming conventions:
| 中间件类型 | 来源 | 命名约定 |
|---|---|---|
| 内部 | 内置中间件(即随 Strapi 提供),自动加载 | strapi::middleware-name |
| 应用级别 | 从 ./src/middlewares 文件夹加载 | global::middleware-name |
| API级别 | 从 ./src/api/[api-name]/middlewares 文件夹加载 | api::api-name.middleware-name |
| 插件 | 从 middlewares 插件接口的属性 中的 strapi-server.js 导出 | plugin::plugin-name.middleware-name |
| 外部 | 可以是:
| - 由于它们是直接从配置文件中配置和解析的,因此没有命名约定。 |
可选配置
🌐 Optional configuration
中间件可以有一个带有以下参数的可选配置:
🌐 Middlewares can have an optional configuration with the following parameters:
| 参数 | 描述 | 类型 ||------|-------------------------------------------------------------------|----------|| config | 用于定义或覆盖中间件配置 | Object || resolve | 中间件文件夹的路径(对于外部中间件很有用) | String |
内部中间件配置参考
🌐 Internal middlewares configuration reference
Strapi 的核心包括以下内部中间件,主要用于性能、安全性和错误处理:
🌐 Strapi's core includes the following internal middlewares, mostly used for performances, security and error handling: | 中间件 | 默认添加 | 是否必需 ||--------------------------------------------------------------------|------------------|----------|| body | 是 | 是 || compression | 否 | 否 || cors | 是 | 是 || errors | 是 | 是 || favicon | 是 | 是 || ip | 否 | 否 || logger | 是 | 否 || poweredBy | 是 | 否 || query | 是 | 是 || response-time | 否 | 否 || responses | 是 | 是 || public | 是 | 是 || security | 是 | 是 || session | 是 | 否 |
body
body 中间件基于 koa-body。它使用 `node-formidable` 库来处理文件。body 接受以下选项:
| 选项 | 描述 | 类型 | 默认值 ||--------------|-----------------------------------------------------------------------------------------------------------------------------------------|-----------------------|-------------|| multipart | 解析多部分请求体 | Boolean | true || patchKoa | 将请求体修补到 Koa 的 ctx.request | Boolean | true || jsonLimit | JSON 请求体的字节(如果为整数)限制 | String 或 Integer | 1mb || formLimit | 表单请求体的字节(如果为整数)限制 | String 或 Integer | 56kb || textLimit | 文本请求体的字节(如果为整数)限制 | String 或 Integer | 56kb || encoding | 设置传入表单字段的编码 | String | utf-8 || formidable | 传递给 formidable 多部分解析器的选项(参见 node-formidable documentation)。 | Object | undefined |
有关 koa-body 的所有可用选项的完整列表,请查看 koa-body documentation。
示例:用于主体中间件的自定义配置
- JavaScript
- TypeScript
module.exports = [
// ...
{
name: 'strapi::body',
config: {
jsonLimit: '3mb',
formLimit: '10mb',
textLimit: '256kb',
encoding: 'gbk',
},
},
// ...
]
export default [
// ...
{
name: 'strapi::body',
config: {
jsonLimit: '3mb',
formLimit: '10mb',
textLimit: '256kb',
encoding: 'gbk',
},
},
// ...
]
compression
compression 中间件基于 koa-compress。它接受以下选项:
| 选项 | 描述 | 类型 | 默认值 ||-------------------|----------------------------------------------------------------------------|-----------------------|------------|| threshold | 压缩的最小响应大小(字节) | String 或 Integer | 1kb || br | 切换 Brotli 压缩 | Boolean | true || gzip | 切换 gzip 压缩 | Boolean | false || deflate | 切换 deflate 压缩 | Boolean | false || defaultEncoding | 指定在请求中没有 Accept-Encoding 头时使用哪些编码器 | String | identity |
示例:压缩中间件的自定义配置
- JavaScript
- TypeScript
module.exports = [
// ...
{
name: 'strapi::compression',
config: {
br: false
},
},
// ...
]
export default [
// ...
{
name: 'strapi::compression',
config: {
br: false
},
},
// ...
]
cors
这个安全中间件涉及跨源资源共享(CORS),并基于 @koa/cors。它接受以下选项:
🌐 This security middleware is about cross-origin resource sharing (CORS) and is based on @koa/cors. It accepts the following options:
| 选项 | 类型 | 描述 | 默认值 ||---------------------|-----------------------------------------------------------|----------------------|------------------------------------------------------------|| origin | 配置 Access-Control-Allow-Origin 头 | String 或 Array 或 Function | '*' || maxAge | 配置 Access-Control-Max-Age 头,以秒为单位 | String 或 Number | 31536000 || credentials | 配置 Access-Control-Allow-Credentials 头 | Boolean | true || methods | 配置 Access-Control-Allow-Methods 头 | Array 或 String | ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'] || headers | 配置 Access-Control-Allow-Headers 头 | Array 或 String | 请求头通过 Access-Control-Request-Headers 传递 || keepHeaderOnError | 如果抛出错误,向 err.header 添加设置的头 | Boolean | false |
示例:cors 中间件的自定义配置
- JavaScript
- TypeScript
module.exports = [
// ...
{
name: 'strapi::cors',
config: {
origin: ['https://example.com', 'https://subdomain.example.com', 'https://someotherwebsite.org'],
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
headers: ['Content-Type', 'Authorization', 'Origin', 'Accept'],
keepHeaderOnError: true,
},
},
// ...
]
export default [
// ...
{
name: 'strapi::cors',
config: {
origin: ['https://example.com', 'https://subdomain.example.com', 'https://someotherwebsite.org'],
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
headers: ['Content-Type', 'Authorization', 'Origin', 'Accept'],
keepHeaderOnError: true,
},
},
// ...
]
示例:作为参数在函数中为cors中间件自定义配置
origin 可以接收一个符合此签名的函数作为参数
export default [
// ...
{
name: 'strapi::cors',
config: {
origin: (ctx): string | string[] => {
const origin = ctx.request.header.origin;
if (origin === 'http://localhost:3000') {
return origin; // The returns will be part of the Access-Control-Allow-Origin header
}
return ''; // Fail cors check
}
},
},
// ...
]
errors
错误中间件处理代码抛出的错误。根据错误的类型,它会为响应设置适当的HTTP状态。默认情况下,任何不应向终端用户暴露的错误都会导致500 HTTP响应。
🌐 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
favicon 中间件用于提供网站图标,并基于 koa-favicon。它接受以下选项:
| 选项 | 描述 | 类型 | 默认值 ||----------|--------------------------------------------------|-----------|-----------------|| path | favicon 文件的路径 | String | 'favicon.ico' || maxAge | 缓存控制最大存活时间指令,以毫秒为单位 | Integer | 86400000 |
示例:favicon 中间件的自定义配置
- JavaScript
- TypeScript
module.exports = [
// ...
{
name: 'strapi::favicon',
config: {
path: './public/uploads/custom-fav-abc123.ico'
},
},
// ...
]
export default [
// ...
{
name: 'strapi::favicon',
config: {
path: './public/uploads/custom-fav-abc123.ico'
},
},
// ...
]
ip
ip 中间件是基于 koa-ip 的 IP 过滤中间件。它接受以下选项:
| 选项 | 描述 | 类型 | 默认值 ||-------------|-----------------|---------|---------------|| whitelist | 白名单 IP | Array | [] || blacklist | 黑名单 IP | Array | [] |
whitelist 和 blacklist 选项支持通配符(例如 whitelist: ['192.168.0.*', '127.0.0.*'])和展开(例如 whitelist: ['192.168.*.[3-10]'])。
🌐 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]']).
示例:ip 中间件的自定义配置
- JavaScript
- TypeScript
module.exports = [
// ...
{
name: 'strapi::ip',
config: {
whitelist: ['192.168.0.*', '192.168.1.*', '123.123.123.123'],
blacklist: ['1.116.*.*', '103.54.*.*'],
},
},
// ...
]
export default [
// ...
{
name: 'strapi::ip',
config: {
whitelist: ['192.168.0.*', '192.168.1.*', '123.123.123.123'],
blacklist: ['1.116.*.*', '103.54.*.*'],
},
},
// ...
]
logger
logger 中间件用于记录请求。
🌐 The logger middleware is used to log requests.
要为 logger 中间件定义自定义配置,请创建一个专用的配置文件(./config/logger.js)。它应导出一个对象,该对象必须是完整或部分的 winstonjs 日志配置。该对象将在服务器启动时与 Strapi 的默认日志配置合并。
示例:日志器中间件的自定义配置
- JavaScript
- TypeScript
'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' })
),
}),
],
};
'use strict';
const {
winston,
formats: { prettyPrint, levelFilter },
} = require('@strapi/logger');
export default {
transports: [
new winston.transports.Console({
level: 'http',
format: winston.format.combine(
levelFilter('http'),
prettyPrint({ timestamps: 'YYYY-MM-DD hh:mm:ss.SSS' })
),
}),
],
};
poweredBy
poweredBy 中间件向响应头添加了一个 X-Powered-By 参数。它接受以下选项:
🌐 The poweredBy middleware adds a X-Powered-By parameter to the response header. It accepts the following options:
| 选项 | 描述 | 类型 | 默认值 ||-------------|------------------------------------|----------|------------------------|| poweredBy | X-Powered-By 头的值 | String | 'Strapi <strapi.io>' |
详情 示例:poweredBy 中间件的自定义配置
- JavaScript
- TypeScript
module.exports = [
// ...
{
name: 'strapi::poweredBy',
config: {
poweredBy: 'Some Awesome Company <example.com>'
},
},
// ...
]
export default [
// ...
{
name: 'strapi::poweredBy',
config: {
poweredBy: 'Some Awesome Company <example.com>'
},
},
// ...
]
query
query 中间件是基于 qs 的查询解析器。它接受以下选项:
| 选项 | 描述 | 类型 | 默认值 ||----------------------|----------------------------------------------------------------------------------------------------------------------------------|-----------|---------------|| strictNullHandling | 区分空值和空字符串(参见 qs documentation) | Boolean | true || arrayLimit | 解析数组时的最大索引限制(参见 qs documentation) | Number | 100 || depth | 解析对象时嵌套对象的最大深度(参见 qs documentation) | Number | 20 |
查询字符串中的括号样式数组(populate、fields、filters 和嵌套键)使用 arrayLimit 通过 qs 进行解析。当列表超出该限制时,qs 可能会返回对象形状的值而不是数组。Strapi 可能会因此拒绝查询或返回与此设置无关的错误。当需要更长列表时,请增加 arrayLimit。更大的值允许更长的查询字符串,并增加每个请求的解析工作量。
🌐 Bracket-style arrays in the query string (populate, fields, filters, and nested keys) are parsed with qs using arrayLimit. When a list grows past that limit, qs can yield object-shaped values instead of arrays. Strapi may then reject the query or return errors that do not point to this setting. Increase arrayLimit when you need longer lists. Larger values allow longer query strings and increase parsing work on each request.
示例:查询中间件的自定义配置
- JavaScript
- TypeScript
module.exports = [
// ...
{
name: 'strapi::query',
config: {
arrayLimit: 50,
depth: 10,
},
},
// ...
]
export default [
// ...
{
name: 'strapi::query',
config: {
arrayLimit: 50,
depth: 10,
},
},
// ...
]
示例:针对长 REST 查询列表提高 arrayLimit
使用适合你最长括号编码列表的值(例如许多 populate[n] 条目)。根据你的需求和可接受的解析成本调整这个数字。
🌐 Use a value that fits your longest bracket-encoded lists (for example many populate[n] entries). Adjust the number based on your needs and acceptable parsing cost.
- JavaScript
- TypeScript
module.exports = [
// ...
{
name: 'strapi::query',
config: {
arrayLimit: 200,
},
},
// ...
]
export default [
// ...
{
name: 'strapi::query',
config: {
arrayLimit: 200,
},
},
// ...
]
response-time
response-time 中间件启用响应头的 X-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
public 中间件是一个静态文件服务中间件,基于 koa-static。它接受以下选项:
| 选项 | 描述 | 类型 | 默认值 ||----------------|-----------------------------------------------------|-----------|---------------|| maxAge | 缓存控制最大年龄指令,单位为毫秒 | Integer | 60000 |
你可以通过编辑 服务器配置文件 来自定义公共文件夹的路径。
🌐 You can customize the path of the public folder by editing the server configuration file.
示例:公共中间件的自定义配置
- JavaScript
- TypeScript
module.exports = [
// ...
{
name: 'strapi::public',
config: {
defer: true,
index: env('INDEX_PATH', 'index-dev.html')
},
},
// ...
]
export default [
// ...
{
name: 'strapi::public',
config: {
defer: true,
index: env('INDEX_PATH', 'index-dev.html')
},
},
// ...
]
security
安全中间件基于 koa-helmet。它接受以下选项:
| 选项 | 描述 | 类型 | 默认值 |
|---|---|---|---|
crossOriginEmbedderPolicy | 将 Cross-Origin-Embedder-Policy 头设置为 require-corp | Boolean | false |
crossOriginOpenerPolicy | 设置 Cross-Origin-Opener-Policy 头 | Boolean | false |
crossOriginResourcePolicy | 设置 Cross-Origin-Resource-Policy 头部 | Boolean | false |
originAgentCluster | 设置 Origin-Agent-Cluster 头部 | Boolean | false |
contentSecurityPolicy | 设置 Content-Security-Policy 头部 | Object | - |
xssFilter | 通过将 X-XSS-Protection 头设置为 0 来禁用浏览器的跨站脚本过滤器 | Boolean | false |
hsts | 设置 HTTP 严格传输安全 (HSTS) 策略的选项。 | Object | - |
hsts.maxAge | HSTS 生效的秒数 | Integer | 31536000 |
hsts.includeSubDomains | 对主机的所有子域应用 HSTS | Boolean | true |
frameguard | 设置 X-Frame-Options 头以帮助减轻点击劫持攻击,设置为 false 以禁用 | Boolean 或 Object | - |
frameguard.action | 值必须是 deny 或 sameorigin | String | sameorigin |
在使用任何第三方上传提供商时,通常需要在此处设置自定义配置。请参阅提供商文档以了解哪些配置选项是必需的。
🌐 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.
默认指令包括一个 market-assets.strapi.io 值。此值已为 应用内市场 设置,并且保持不变是安全的。
🌐 The default directives include a market-assets.strapi.io value. This value is set for the in-app market and is safe to keep.
示例:用于使用 AWS-S3 提供程序的安全中间件的自定义配置
- JavaScript
- TypeScript
module.exports = [
// ...
{
name: 'strapi::security',
config: {
contentSecurityPolicy: {
useDefaults: true,
directives: {
'connect-src': ["'self'", 'https:'],
'img-src': [
"'self'",
'data:',
'blob:',
'market-assets.strapi.io',
'yourBucketName.s3.yourRegion.amazonaws.com',
],
'media-src': [
"'self'",
'data:',
'blob:',
'market-assets.strapi.io',
'yourBucketName.s3.yourRegion.amazonaws.com',
],
upgradeInsecureRequests: null,
},
},
},
},
// ...
]
export default [
// ...
{
name: 'strapi::security',
config: {
contentSecurityPolicy: {
useDefaults: true,
directives: {
'connect-src': ["'self'", 'https:'],
'img-src': [
"'self'",
'data:',
'blob:',
'market-assets.strapi.io',
'yourBucketName.s3.yourRegion.amazonaws.com',
],
'media-src': [
"'self'",
'data:',
'blob:',
'market-assets.strapi.io',
'yourBucketName.s3.yourRegion.amazonaws.com',
],
upgradeInsecureRequests: null,
},
},
},
},
// ...
]
session
session 中间件允许使用基于 cookie 的会话,基于 koa-session。它接受以下选项:
| 选项 | 描述 | 类型 | 默认值 |
|---|---|---|---|
key | Cookie 键 | String | 'koa.sess' |
maxAge | Cookie 的最大有效期,单位为毫秒。使用 'session' 将在会话关闭时使 cookie 过期。 | Integer 或 'session' | 86400000 |
autoCommit | 自动提交标题 | Boolean | true |
overwrite | 是否可以覆盖 | Boolean | true |
httpOnly | 是否是 httpOnly。使用 httpOnly 有助于缓解跨站脚本(XSS)攻击。 | Boolean | true |
signed | 签署 cookies | Boolean | true |
rolling | 强制在每个响应中设置会话标识符 cookie。 | Boolean | false |
renew | 当会话即将过期时续订会话,以便用户保持登录状态。 | Boolean | false |
secure | 强制使用 HTTPS | Boolean | 在生产环境中为 true,否则为 false |
sameSite | 将 Cookie 限制为第一方或同站点上下文 | String | null |
示例:会话中间件的自定义配置
- JavaScript
- TypeScript
module.exports = [
// ...
{
name: 'strapi::session',
config: {
rolling: true,
renew: true
},
},
// ...
]
export default [
// ...
{
name: 'strapi::session',
config: {
rolling: true,
renew: true
},
},
// ...
]