服务端 API:路由(Routes)

页面摘要: 服务端 API 从服务端入口文件导出一个 routes 值来暴露插件端点。仅用于隐式 admin 路由时使用数组格式,使用命名路由器格式来分隔 admin 和 Content API 路由,或者在需要动态路由配置时使用工厂回调格式。

路由暴露你插件的 HTTP 端点,并将传入请求映射到控制器操作。它们作为 routes 值从 服务端入口文件 导出。

WARNING

在深入阅读本页概念之前,请确保你已经:

路由声明格式

我应该使用哪种格式?
  • 数组格式: 只需要具有默认注册行为的 admin 路由的简单插件
  • 命名路由器格式: 同时暴露 admin 和 Content API 路由,或需要显式类型控制的插件。大多数情况下推荐使用。
  • 工厂回调格式: 路由配置依赖于 strapi 实例(例如读取插件配置)的高级场景。

数组格式

数组格式是最基础的格式:它直接导出一个路由对象数组。Strapi 默认将这些对象注册为 admin 路由,并以插件名作为前缀。

TIP

要暴露 Content API 路由,请使用带有 type: 'content-api' 的 命名路由器格式。

JavaScript

'use strict';

module.exports = [
  {
    method: 'GET',
    path: '/articles',
    handler: 'article.find',
    config: {
      policies: [],
    },
  },
  {
    method: 'POST',
    path: '/articles',
    handler: 'article.create',
    config: {
      policies: [],
    },
  },
];

TypeScript

export default [
  {
    method: 'GET',
    path: '/articles',
    handler: 'article.find',
    config: {
      policies: [],
    },
  },
  {
    method: 'POST',
    path: '/articles',
    handler: 'article.create',
    config: {
      policies: [],
    },
  },
];

命名路由器格式

使用命名路由器格式时,使用一个带有具名键(admin、content-api 或任何自定义名称)的对象来声明独立的路由器组。每个组是一个带有 type、可选 prefix 和 routes 数组的路由器对象。当你的插件同时暴露 admin 和 Content API 路由时,请使用此格式。

JavaScript

'use strict';

const adminRoutes = require('./admin');
const contentApiRoutes = require('./content-api');

module.exports = {
  // highlight-start
  admin: adminRoutes,
  'content-api': contentApiRoutes,
  // highlight-end
};
'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: [],
      },
    },
  ],
};

TypeScript

import adminRoutes from './admin';
import contentApiRoutes from './content-api';

export default {
  // highlight-start
  admin: adminRoutes,
  'content-api': contentApiRoutes,
  // highlight-end
};
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: [],
      },
    },
  ],
};

工厂回调格式

对于需要在路由配置时访问 strapi 实例的高级场景(例如,构建动态路径,或根据配置有条件地包含路由),可以导出一个工厂回调。

NOTE

工厂回调必须附加到具名路由条目(例如 admin 或 content-api),而不能作为 routes/index 的根导出。

在根级别使用 module.exports = ({ strapi }) => ({ ... }) 不是有效的格式。

JavaScript

'use strict';

module.exports = {
  'content-api': ({ strapi }) => ({
    type: 'content-api',
    routes: [
      {
        method: 'GET',
        path: '/articles',
        handler: 'article.find',
        config: {
          // highlight-next-line
          auth: strapi.plugin('my-plugin').config('publicRead') ? false : {},
        },
      },
    ],
  }),
};

TypeScript

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: {
          // highlight-next-line
          auth: strapi.plugin('my-plugin').config('publicRead') ? false : {},
        },
      },
    ],
  }),
};

export default routes;

有关 Strapi 在注册时自动添加的内容的详细信息,请参阅 Strapi 应用的默认值。

Strapi 应用的默认值

当 Strapi 注册插件路由时,它会自动应用以下默认值:

PropertyDefault valueNotes
type'admin'在使用数组格式时应用,或在命名格式中路由器对象省略 type 时应用
prefix'/<plugin-name>'在使用数组格式时应用,或在路由器对象省略 prefix 时应用
config.auth.scope['plugin::<plugin-name>.<handler>']仅为字符串 handler 自动生成,使用 defaultsDeep,因此现有值不会被覆盖

以下 2 种声明是等价的。Strapi 会自动应用上表中的默认值:

JavaScript

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: {
            // highlight-next-line
            scope: ['plugin::my-plugin.article.find'], // auto-generated from handler string
          },
        },
      },
    ],
  },
};

TypeScript

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: {
            // highlight-next-line
            scope: ['plugin::my-plugin.article.find'], // auto-generated from handler string
          },
        },
      },
    ],
  },
};

路由配置参考

每个路由接受一个具有以下属性的可选 config 对象:

policies

类型: Array<string | PolicyHandler | { name: string; options?: object }>

在控制器操作之前运行的策略。每个条目可以是策略名称字符串、内联函数,或带有必需 name 和可选 options 的对象。

options 对象按原样传递给策略函数的第二个参数(策略签名中的 config)。该对象的形态取决于策略。

插件策略引用为 plugin::my-plugin.policy-name。

middlewares

类型: Array<string | MiddlewareHandler | { name: string; options?: object }>

应用于此路由的中间件。每个条目是中间件名称字符串、内联函数,或具有如下属性的对象:

  • name:已注册的中间件名称,
  • options(可选):中间件选项。
路由中间件 vs. 全局服务端中间件

在路由验证时,Strapi 对中间件/策略对象验证 { name: string; options?: object } 形态(参见 services/server/routing.ts)。

中间件解析器(services/server/middleware.ts)仍然包含对 { resolve, config } 对象的运行时支持,但对于标准插件路由声明,该形态会在解析前被路由验证拒绝。

为与验证兼容,请在路由配置中使用 { name, options }。

auth

类型: false | { scope: string[]; strategies?: string[] }

设为 false 以使路由公开。传入一个对象以定义 auth 范围,并可选择自定义 auth 策略。

在运行时,当 auth 是一个对象时,scope 必须存在。

NOTE

对于 字符串 handler(例如 handler: 'article.find'),Strapi 会自动注入默认的 config.auth.scope 值,因此诸如 auth: {} 这样的模式仍然可以工作。

对于 非字符串 handler(内联函数),请勿假设会自动注入 scope。当 auth 是对象时,请显式定义 config.auth.scope。

WARNING

在 admin 路由上设置 auth: false 几乎从来都不是有意为之:它会将端点暴露给未经验证的请求。

通用后端自定义示例

有关包含策略、公开路由、动态 URL 参数以及路径中的正则表达式的配置示例,请参阅 Routes。

最佳实践

  • 当同时暴露 admin 和 Content API 端点时,使用命名路由器格式。 它使每个路由的意图明确,并避免依赖可能令人意外的 type 默认值。

  • 保持 handler 为字符串。 字符串 handler 会自动生成 auth 范围,函数 handler 则不会。除非设置 config.auth: false,否则身份验证对字符串和函数 handler 都会运行,但只有字符串 handler 会获得自动的 config.auth.scope。如果你使用函数 handler 并需要路由级权限范围,请显式定义 config.auth.scope。

  • 将策略作用域限定在其命名空间内。 在路由中引用插件策略时,请使用完整的 plugin::my-plugin.policy-name 形式。这可以避免如果应用程序其他地方存在相同短名称的策略时产生歧义。

  • 不要在 admin 路由上禁用 auth。 admin 路由默认需要 admin 身份验证。在 admin 路由上禁用 auth 会将其暴露给未经验证的请求,这几乎从来都不是有意为之。

  • 将相关路由分组在专用文件中。 随着插件增长,单个路由 index 文件会变得难以浏览。按资源拆分(例如 routes/article.js、routes/comment.js)并从 routes/index.js 重新导出。