服务器 API:路由
🌐 Server API: Routes
Page summary:服务器 API 从服务器入口文件导出一个
routes值以公开插件端点。仅对隐式管理路由使用数组格式,使用命名路由格式分离管理和内容 API 路由,或使用工厂回调格式进行动态路由配置。
路由会公开你的插件的 HTTP 端点,并将传入请求映射到控制器操作。它们从 服务器入口文件 导出,作为一个 routes 值。
🌐 Routes expose your plugin's HTTP endpoints and map incoming requests to controller actions. They are exported from the server entry file as a routes value.
在深入了解本页的概念之前,请确保你已经:
🌐 Before diving deeper into the concepts on this page, please ensure you have:
- 创建了一个 Strapi 插件,
- 已阅读并理解了服务器 API的基础知识
路由声明格式
🌐 Route declaration formats
数组格式
🌐 Array format
数组格式是最基本的格式:它直接导出路由对象的数组。Strapi 默认将这些对象注册为管理路由,插件名称作为前缀。
🌐 The array format is the most basic format: it exports an array of route objects directly. Strapi registers these objects as admin routes by default, with the plugin name as prefix.
要公开内容 API 路由,请使用带有 type: 'content-api' 的命名路由格式。
🌐 To expose Content API routes, use the named router format with type: 'content-api'.
- JavaScript
- TypeScript
'use strict';
module.exports = [
{
method: 'GET',
path: '/articles',
handler: 'article.find',
config: {
policies: [],
},
},
{
method: 'POST',
path: '/articles',
handler: 'article.create',
config: {
policies: [],
},
},
];
export default [
{
method: 'GET',
path: '/articles',
handler: 'article.find',
config: {
policies: [],
},
},
{
method: 'POST',
path: '/articles',
handler: 'article.create',
config: {
policies: [],
},
},
];
命名路由格式
🌐 Named router format
使用命名路由格式时,使用具有命名键(admin、content-api 或任何自定义名称)的对象来声明单独的路由组。每个组都是一个路由对象,包含 type、可选的 prefix 和一个 routes 数组。当你的插件同时暴露管理和内容 API 路由时使用此格式。
🌐 With the named router format, use an object with named keys (admin, content-api, or any custom name) to declare separate router groups. Each group is a router object with a type, optional prefix, and a routes array. Use this format when your plugin exposes both admin and Content API routes.
- JavaScript
- TypeScript
'use strict';
const adminRoutes = require('./admin');
const contentApiRoutes = require('./content-api');
module.exports = {
admin: adminRoutes,
'content-api': contentApiRoutes,
};
'use strict';
module.exports = {
type: 'admin',
routes: [
{
method: 'GET',
path: '/articles',
handler: 'article.find',
config: {
policies: ['admin::isAuthenticatedAdmin'],
},
},
],
};
'use strict';
module.exports = {
type: 'content-api',
routes: [
{
method: 'GET',
path: '/articles',
handler: 'article.find',
config: {
policies: [],
},
},
],
};
import adminRoutes from './admin';
import contentApiRoutes from './content-api';
export default {
admin: adminRoutes,
'content-api': contentApiRoutes,
};
export default {
type: 'admin' as const,
routes: [
{
method: 'GET' as const,
path: '/articles',
handler: 'article.find',
config: {
policies: ['admin::isAuthenticatedAdmin'],
},
},
],
};
export default {
type: 'content-api' as const,
routes: [
{
method: 'GET' as const,
path: '/articles',
handler: 'article.find',
config: {
policies: [],
},
},
],
};
工厂回调格式
🌐 Factory callback format
对于需要在路由配置时访问 strapi 实例的高级情况(例如,用于构建动态路径或根据配置有条件地包含路由),你可以导出一个工厂回调。
🌐 For advanced cases where you need access to the strapi instance at route configuration time (for example, to build dynamic paths or conditionally include routes based on configuration), you can export a factory callback.
工厂回调必须附加到命名路由条目(例如 admin 或 content-api),而不是作为 routes/index 的根导出。
🌐 The factory callback must be attached to a named route entry (such as admin or content-api), not exported as the root of routes/index.
module.exports = ({ strapi }) => ({ ... }) 在根级别不是有效的格式。
- JavaScript
- TypeScript
'use strict';
module.exports = {
'content-api': ({ strapi }) => ({
type: 'content-api',
routes: [
{
method: 'GET',
path: '/articles',
handler: 'article.find',
config: {
auth: strapi.plugin('my-plugin').config('publicRead') ? false : {},
},
},
],
}),
};
import type { Core } from '@strapi/strapi';
const routes: Record<
string,
Core.RouterConfig | ((args: { strapi: Core.Strapi }) => Core.RouterConfig)
> = {
'content-api': ({ strapi }) => ({
type: 'content-api',
routes: [
{
method: 'GET',
path: '/articles',
handler: 'article.find',
config: {
auth: strapi.plugin('my-plugin').config('publicRead') ? false : {},
},
},
],
}),
};
export default routes;
有关 Strapi 在注册时自动添加的内容的详细信息,请参见 Strapi 应用的默认值。
🌐 For details on what Strapi adds automatically at registration time, see Defaults applied by Strapi.
Strapi 应用的默认设置
🌐 Defaults applied by Strapi
当 Strapi 注册插件路由时,它会自动应用以下默认设置:
🌐 When Strapi registers plugin routes, it applies the following defaults automatically:
| 属性 | 默认值 | 说明 |
|---|---|---|
type | 'admin' | 在使用数组格式时应用,或者在命名格式中路由对象省略 type 时应用 |
prefix | '/<plugin-name>' | 在使用数组格式时应用,或者在路由对象中省略 prefix 时应用 |
config.auth.scope | ['plugin::<plugin-name>.<handler>'] | 仅对字符串处理器自动生成,使用 defaultsDeep,以避免覆盖现有值 |
以下两条声明是等效的。Strapi 会自动应用上表中的默认值:
🌐 The following 2 declarations are equivalent. Strapi applies the defaults from the table above automatically:
- JavaScript
- TypeScript
module.exports = [
{
method: 'GET',
path: '/articles',
handler: 'article.find',
},
];
module.exports = {
admin: {
type: 'admin',
prefix: '/my-plugin',
routes: [
{
method: 'GET',
path: '/articles',
handler: 'article.find',
config: {
auth: {
scope: ['plugin::my-plugin.article.find'], // auto-generated from handler string
},
},
},
],
},
};
export default [
{
method: 'GET' as const,
path: '/articles',
handler: 'article.find',
},
];
export default {
admin: {
type: 'admin' as const,
prefix: '/my-plugin',
routes: [
{
method: 'GET' as const,
path: '/articles',
handler: 'article.find',
config: {
auth: {
scope: ['plugin::my-plugin.article.find'], // auto-generated from handler string
},
},
},
],
},
};
路由配置参考
🌐 Route configuration reference
每条路由都可以接受一个可选的 config 对象,该对象具有以下属性:
🌐 Each route accepts an optional config object with the following properties:
policies
类型: Array<string | PolicyHandler | { name: string; options?: object }>
在控制器动作之前运行的策略。每一项要么是策略名称字符串,要么是内联函数,或者是包含必需的 name 和可选的 options 的对象。
🌐 Policies to run before the controller action. Each item is either a policy name string, an inline function, or an object with required name and optional options.
options 对象将原样传递给策略函数的第二个参数(策略签名中的 config)。该对象的形状取决于策略。
🌐 The options object is passed as-is to the policy function's second argument (config in policy signatures). The shape of this object depends on the policy.
插件 政策被引用为 plugin::my-plugin.policy-name。
🌐 Plugin policies are referenced as plugin::my-plugin.policy-name.
middlewares
类型: Array<string | MiddlewareHandler | { name: string; options?: object }>
要应用到此路由的中间件。每个项目可以是中间件名称字符串、内联函数或具有以下属性的对象:
🌐 Middlewares to apply to this route. Each item is a middleware name string, an inline function, or an object with:
name:已注册的中间件名称,options(可选):中间件选项。
在路由验证时,Strapi 会根据 { name: string; options?: object } 验证中间件/策略对象(参见 services/server/routing.ts)。
🌐 At route validation time, Strapi validates middleware/policy objects against { name: string; options?: object } (see services/server/routing.ts).
中间件解析器(services/server/middleware.ts)仍然包含对 { resolve, config } 对象的运行时支持,但在标准插件路由声明解析之前,此形状会被路由验证拒绝。
🌐 The middleware resolver (services/server/middleware.ts) still contains runtime support for { resolve, config } objects, but this shape is rejected by route validation before resolution for standard plugin route declarations.
在路由配置中使用 { name, options } 以 兼容验证。
🌐 Use { name, options } in route configs for compatibility with validation.
auth
类型: false | { scope: string[]; strategies?: string[] }
设置为 false 以使路由公开。传递一个对象以定义认证范围,并可选择自定义认证策略。
🌐 Set to false to make the route public. Pass an object to define the auth scope and, optionally, custom auth strategies.
在运行时,当 auth 是对象时,必须存在 scope。
🌐 At runtime, scope must be present when auth is an object.
对于字符串处理器(例如,handler: 'article.find'),Strapi 会自动注入一个默认的 config.auth.scope 值,因此像 auth: {} 这样的模式仍然可以工作。
🌐 For string handlers (for example, handler: 'article.find'), Strapi auto-injects a default config.auth.scope value, so patterns such as auth: {} can still work.
对于非字符串处理器(内联函数),不要假设自动作用域注入。当 auth 是对象时,必须显式定义 config.auth.scope。
🌐 For non-string handlers (inline functions), do not assume auto-scope injection. Define config.auth.scope explicitly when auth is an object.
在管理员路由上设置 auth: false 几乎从来不是故意的:它会使该端点暴露给未认证的请求。
🌐 Setting auth: false on an admin route is almost never intentional: it exposes the endpoint to unauthenticated requests.
有关包含策略、公共路由、动态 URL 参数和路径中正则表达式的配置示例,请参见 Routes。
🌐 For configuration examples including policies, public routes, dynamic URL parameters, and regular expressions in paths, see Routes.
最佳实践
🌐 Best practices
- 在同时公开管理和内容 API 端点时,请使用命名路由格式。 这样可以明确每个路由的意图,避免依赖可能令人意外的
type默认值。 - 保持
handler为字符串。 字符串处理程序会自动生成授权范围,而函数处理程序不会。除非你设置了config.auth: false,否则身份验证仍会针对字符串和函数处理程序运行,但只有字符串处理程序会自动获得config.auth.scope。如果你使用函数处理程序并且需要路由级权限范围,请显式定义config.auth.scope。 - 将策略的作用范围限定到其命名空间。 在路由中引用插件策略时,请使用 完整的
plugin::my-plugin.policy-name形式。如果应用中其他地方存在同名的短名策略,这可以避免歧义。 - 不要在管理路由上禁用身份验证。 管理路由默认需要管理员身份验证。在管理路由上禁用身份验证会使其暴露给未经过身份验证的请求,这几乎从来都不是有意为之。
- 将相关的路由分组到专用文件中。 随着插件的增长,单个路由索引文件变得难以导航。按资源拆分(例如,
routes/article.js、routes/comment.js),并从routes/index.js重新导出。