Strapi中API版本化配置咨询:如何实现v1/v2/v3多版本API及路由设置
实现Strapi API版本化的几种实用方案
我之前在做Strapi项目时刚好遇到过这个API版本化的需求,确实Strapi默认没有直接暴露指向api文件夹的全局路由配置,但有几种实用的方案可以实现,我给你一步步拆解:
方案一:全局路由前缀(适合单版本快速切换)
如果你的需求只是给所有API统一加上版本前缀(比如只运行v1或v2版本),可以通过Strapi的全局配置快速实现:
- 找到项目根目录下的
config/api.js(Strapi v4版本,v3版本则是config/environments/[环境名]/server.js) - 在
rest配置中添加prefix字段,指定版本前缀:
module.exports = { rest: { defaultLimit: 25, maxLimit: 100, withCount: true, prefix: '/api/v1' // 所有API都会带上/api/v1前缀 }, };
这样默认生成的所有API路由都会自动加上/api/v1前缀,比如原来的/posts会变成/api/v1/posts。如果后续要切换到v2,直接修改这个prefix值即可。
方案二:多版本API目录+自定义路由(支持同时运行多版本)
如果需要同时维护v1、v2等多个版本的API,这个方案更灵活:
- 在项目
src目录下创建版本化的API文件夹,比如api-v1、api-v2,和默认的api文件夹结构完全一致(包含controllers、services、routes、models等子文件夹) - 给每个版本的路由文件手动添加版本前缀,比如
src/api-v1/posts/routes/posts.js:
module.exports = { routes: [ { method: 'GET', path: '/v1/posts', // 明确指定v1版本的路由路径 handler: 'posts.find', config: { policies: [], }, }, // 其他CRUD路由同理修改路径前缀 ], };
- 告诉Strapi扫描这些自定义的API目录,修改
config/api.js添加apiDirs配置:
module.exports = { rest: { defaultLimit: 25, maxLimit: 100, withCount: true, }, apiDirs: ['./src/api', './src/api-v1', './src/api-v2'], // 让Strapi加载多个版本的API目录 };
这样Strapi会自动扫描并注册所有版本的API,你可以同时访问/v1/posts和/v2/posts两个版本的接口。
方案三:自定义中间件实现动态版本切换(更灵活的版本逻辑)
如果想要根据请求头、URL参数等动态切换版本(比如通过Accept-Version请求头指定版本),可以写一个自定义中间件:
- 在
src/middlewares目录下创建version-router.js文件:
module.exports = (config, { strapi }) => { return async (ctx, next) => { // 示例1:从URL路径提取版本(比如/api/v1/posts) const pathVersionMatch = ctx.path.match(/^\/api\/v(\d+)/); // 示例2:从请求头提取版本(比如Accept-Version: v1) const headerVersion = ctx.request.headers['accept-version']; // 优先用请求头的版本,没有则用URL路径的版本 const targetVersion = headerVersion || (pathVersionMatch ? `v${pathVersionMatch[1]}` : 'v1'); // 将版本信息存入ctx.state,供后续控制器使用 ctx.state.apiVersion = targetVersion; await next(); }; };
- 在
config/middlewares.js中注册这个中间件,确保放在strapi::router之前:
module.exports = [ 'strapi::errors', 'strapi::security', 'strapi::cors', 'strapi::poweredBy', 'strapi::logger', 'strapi::query', 'strapi::body', 'strapi::session', 'strapi::favicon', 'strapi::public', './middlewares/version-router', // 注册自定义版本中间件 'strapi::router', ];
- 在控制器中根据
ctx.state.apiVersion执行不同版本的业务逻辑,比如:
// src/api/posts/controllers/posts.js module.exports = { async find(ctx) { const { apiVersion } = ctx.state; if (apiVersion === 'v1') { // v1版本返回简化字段 return strapi.db.query('api::post.post').findMany({ select: ['id', 'title', 'content'] }); } else if (apiVersion === 'v2') { // v2版本返回更多字段 return strapi.db.query('api::post.post').findMany({ select: ['id', 'title', 'content', 'createdAt', 'updatedAt'], populate: ['category'] }); } } };
额外注意事项
- 模型版本化:如果不同版本的API需要不同的数据结构,建议给每个版本创建独立的模型文件(比如
api-v1/posts/models/posts.js),避免互相干扰。 - 文档管理:Strapi自动生成的API文档会包含所有版本的路由,你可以手动调整文档配置,或者给不同版本的API添加标签区分。
内容的提问来源于stack exchange,提问作者user14709104
相关产品推荐
相关产品推荐

