跳到主要内容

Koa路由系统详解

1. 路由系统概述

路由是Web应用的核心概念之一,它负责将HTTP请求映射到相应的处理函数。在Koa中,路由系统不是框架核心的一部分,而是通过第三方中间件如koa-router来实现的。本章将深入探讨Koa的路由系统,包括基本用法、高级特性和最佳实践。

1.1 路由的基本概念

路由(路由)是指根据URL和HTTP方法将请求映射到处理函数的机制。在Web应用中,路由通常由以下几个部分组成:

  • URL模式:用于匹配请求的URL
  • HTTP方法:如GET、POST、PUT、DELETE等
  • 处理函数:当请求匹配路由时执行的函数

1.2 Koa路由系统的特点

  • 轻量级:Koa本身不包含路由功能,需要使用第三方中间件
  • 灵活:支持命名路由、路由参数、路由前缀等高级特性
  • 可组合:支持路由嵌套和组合,便于组织大型应用的路由结构
  • 中间件集成:支持在路由级别使用中间件

2. koa-router中间件

2.1 安装与基本配置

koa-router是Koa最常用的路由中间件,提供了完整的路由功能。

npm install koa-router

基本使用:

const Koa = require('koa');
const Router = require('koa-router');

const app = new Koa();
const router = new Router();

// 定义路由
router.get('/', async ctx => {
ctx.body = 'Hello World';
});

// 应用路由中间件
app.use(router.routes());
app.use(router.allowedMethods());

app.listen(3000);

2.2 路由注册方法

koa-router支持以下HTTP方法的路由注册:

// HTTP方法路由
router.get('/path', handler);
router.post('/path', handler);
router.put('/path', handler);
router.delete('/path', handler);
router.patch('/path', handler);
router.head('/path', handler);
router.options('/path', handler);

// 支持多个HTTP方法
router.methods(['GET', 'POST'], '/path', handler);

// 匹配所有HTTP方法
router.all('/path', handler);

2.3 路由处理函数

路由处理函数是一个接收Koa上下文对象的async函数:

router.get('/users', async (ctx) => {
// 获取请求数据
const query = ctx.query;
const params = ctx.params;
const body = ctx.request.body;

// 处理业务逻辑
const users = await getUserList(query);

// 设置响应
ctx.status = 200;
ctx.body = {
code: 200,
message: 'Success',
data: users
};
});

3. 路由参数

3.1 路径参数

路由路径参数允许在URL中捕获动态值:

// 单个参数
router.get('/users/:id', async ctx => {
const id = ctx.params.id;
ctx.body = `用户ID: ${id}`;
});

// 多个参数
router.get('/users/:userId/posts/:postId', async ctx => {
const { userId, postId } = ctx.params;
ctx.body = `用户ID: ${userId}, 文章ID: ${postId}`;
});

// 可选参数(使用?)
router.get('/users/:id?', async ctx => {
const id = ctx.params.id || 'all';
ctx.body = `用户ID: ${id}`;
});

// 正则表达式参数
router.get('/files/:file(.*)', async ctx => {
const file = ctx.params.file;
ctx.body = `文件路径: ${file}`;
});

3.2 查询参数

查询参数是URL中?后面的键值对,Koa会自动解析它们:

router.get('/search', async ctx => {
// GET /search?keyword=koa&page=1
const { keyword, page } = ctx.query;
ctx.body = { keyword, page };
});

3.3 参数验证

对于路由参数的验证,可以使用第三方库如Joi、express-validator等:

const Joi = require('joi');

router.get('/users/:id', async ctx => {
// 验证ID参数
const schema = Joi.object({
id: Joi.number().integer().min(1).required()
});

try {
// 验证参数
await schema.validateAsync({ id: ctx.params.id });

// 处理业务逻辑
ctx.body = `用户ID: ${ctx.params.id}`;
} catch (error) {
ctx.status = 400;
ctx.body = {
code: 400,
message: error.details[0].message
};
}
});

4. 路由中间件

4.1 路由级中间件

可以为特定路由或路由组应用中间件:

// 单路由中间件
router.get('/users', authMiddleware, async ctx => {
ctx.body = '用户列表';
});

// 多个中间件
router.post('/users', validateMiddleware, authMiddleware, async ctx => {
ctx.body = '创建用户成功';
});

// 路由组中间件
router.use('/admin', adminMiddleware);
router.get('/admin/dashboard', async ctx => {
ctx.body = '管理面板';
});

4.2 路由前缀

可以为一组路由设置统一的前缀:

// 创建带前缀的路由
const apiRouter = new Router({ prefix: '/api' });

// 这些路由将自动添加/api前缀
apiRouter.get('/users', async ctx => {
ctx.body = 'API用户列表';
});

apiRouter.post('/users', async ctx => {
ctx.body = '创建API用户';
});

// 应用路由
app.use(apiRouter.routes());

4.3 嵌套路由

路由可以嵌套,便于组织复杂的路由结构:

const Koa = require('koa');
const Router = require('koa-router');

const app = new Koa();
const router = new Router();
const userRouter = new Router();
const postRouter = new Router();

// 用户路由
userRouter.get('/', async ctx => {
ctx.body = '用户列表';
});

userRouter.get('/:id', async ctx => {
ctx.body = `用户 ${ctx.params.id}`;
});

// 文章路由
postRouter.get('/', async ctx => {
ctx.body = '文章列表';
});

postRouter.get('/:id', async ctx => {
ctx.body = `文章 ${ctx.params.id}`;
});

// 嵌套路由
router.use('/users', userRouter.routes(), userRouter.allowedMethods());
router.use('/posts', postRouter.routes(), postRouter.allowedMethods());

// 应用主路由
app.use(router.routes());
app.use(router.allowedMethods());

app.listen(3000);

5. 高级路由特性

5.1 命名路由

可以为路由指定名称,便于生成URL:

// 定义命名路由
router.get('user-detail', '/users/:id', async ctx => {
ctx.body = `用户 ${ctx.params.id}`;
});

// 生成URL
const url = router.url('user-detail', { id: 123 }); // /users/123

// 在路由处理函数中生成URL
router.get('/links', async ctx => {
const userUrl = ctx.router.url('user-detail', { id: 123 });
ctx.body = { userUrl };
});

5.2 路由重定向

可以使用路由重定向功能将一个路由重定向到另一个路由:

// 简单重定向
router.redirect('/login', '/auth/login');

// 带状态码的重定向(默认301)
router.redirect('/old', '/new', 302);

// 在路由处理函数中重定向
router.get('/home', async ctx => {
ctx.redirect('/dashboard');
});

5.3 路由参数预处理

可以对路由参数进行预处理:

// 注册参数预处理函数
router.param('id', async (id, ctx, next) => {
// 预处理ID参数
ctx.state.user = { id: parseInt(id) };
await next();
});

// 使用预处理后的参数
router.get('/users/:id', async ctx => {
ctx.body = `用户ID: ${ctx.state.user.id}`;
});

5.4 路由优先级

路由的定义顺序会影响匹配优先级,更具体的路由应该放在前面:

// 更具体的路由放在前面
router.get('/users/new', async ctx => {
ctx.body = '创建新用户';
});

// 更通用的路由放在后面
router.get('/users/:id', async ctx => {
ctx.body = `用户 ${ctx.params.id}`;
});

6. 路由模块化

在大型应用中,将路由模块化是一种良好的实践。

6.1 路由文件组织

推荐的路由文件组织结构:

app/
├── routes/
│ ├── index.js # 路由入口文件
│ ├── users.js # 用户相关路由
│ ├── posts.js # 文章相关路由
│ └── admin.js # 管理相关路由
├── controllers/ # 控制器文件
└── app.js # 应用入口文件

6.2 路由模块化实现

用户路由 (routes/users.js):

const Router = require('koa-router');
const router = new Router({ prefix: '/users' });

// 引入控制器
const userController = require('../controllers/userController');

// 定义路由
router.get('/', userController.getAllUsers);
router.get('/:id', userController.getUserById);
router.post('/', userController.createUser);
router.put('/:id', userController.updateUser);
router.delete('/:id', userController.deleteUser);

module.exports = router;

文章路由 (routes/posts.js):

const Router = require('koa-router');
const router = new Router({ prefix: '/posts' });

// 引入控制器
const postController = require('../controllers/postController');

// 定义路由
router.get('/', postController.getAllPosts);
router.get('/:id', postController.getPostById);
router.post('/', postController.createPost);
router.put('/:id', postController.updatePost);
router.delete('/:id', postController.deletePost);

module.exports = router;

路由入口文件 (routes/index.js):

const Router = require('koa-router');
const router = new Router();

// 引入各模块路由
const userRoutes = require('./users');
const postRoutes = require('./posts');

// 挂载子路由
router.use(userRoutes.routes(), userRoutes.allowedMethods());
router.use(postRoutes.routes(), postRoutes.allowedMethods());

module.exports = router;

应用入口文件 (app.js):

const Koa = require('koa');
const bodyParser = require('koa-bodyparser');

// 引入路由
const routes = require('./routes');

const app = new Koa();

// 应用中间件
app.use(bodyParser());

// 应用路由
app.use(routes.routes());
app.use(routes.allowedMethods());

app.listen(3000);

7. 路由与控制器

在MVC架构中,路由负责请求的分发,而控制器负责具体的业务逻辑处理。

7.1 控制器模式

控制器是处理请求、执行业务逻辑并返回响应的组件。

用户控制器 (controllers/userController.js):

// 引入服务层
const userService = require('../services/userService');

const userController = {
// 获取所有用户
getAllUsers: async (ctx) => {
try {
const users = await userService.getAllUsers();
ctx.status = 200;
ctx.body = {
code: 200,
message: 'Success',
data: users
};
} catch (error) {
ctx.status = 500;
ctx.body = {
code: 500,
message: error.message
};
}
},

// 获取单个用户
getUserById: async (ctx) => {
try {
const user = await userService.getUserById(ctx.params.id);
if (!user) {
ctx.status = 404;
ctx.body = {
code: 404,
message: 'User not found'
};
return;
}
ctx.status = 200;
ctx.body = {
code: 200,
message: 'Success',
data: user
};
} catch (error) {
ctx.status = 500;
ctx.body = {
code: 500,
message: error.message
};
}
},

// 创建用户
createUser: async (ctx) => {
try {
const newUser = await userService.createUser(ctx.request.body);
ctx.status = 201;
ctx.body = {
code: 201,
message: 'User created',
data: newUser
};
} catch (error) {
ctx.status = 400;
ctx.body = {
code: 400,
message: error.message
};
}
},

// 更新用户
updateUser: async (ctx) => {
try {
const updatedUser = await userService.updateUser(ctx.params.id, ctx.request.body);
if (!updatedUser) {
ctx.status = 404;
ctx.body = {
code: 404,
message: 'User not found'
};
return;
}
ctx.status = 200;
ctx.body = {
code: 200,
message: 'User updated',
data: updatedUser
};
} catch (error) {
ctx.status = 400;
ctx.body = {
code: 400,
message: error.message
};
}
},

// 删除用户
deleteUser: async (ctx) => {
try {
const deletedUser = await userService.deleteUser(ctx.params.id);
if (!deletedUser) {
ctx.status = 404;
ctx.body = {
code: 404,
message: 'User not found'
};
return;
}
ctx.status = 200;
ctx.body = {
code: 200,
message: 'User deleted'
};
} catch (error) {
ctx.status = 500;
ctx.body = {
code: 500,
message: error.message
};
}
}
};

module.exports = userController;

7.2 服务层

服务层包含业务逻辑,与数据访问层交互:

用户服务 (services/userService.js):

// 引入数据访问层
const userModel = require('../models/userModel');

const userService = {
// 获取所有用户
getAllUsers: async () => {
return await userModel.findAll();
},

// 获取单个用户
getUserById: async (id) => {
return await userModel.findById(id);
},

// 创建用户
createUser: async (userData) => {
// 验证用户数据
if (!userData.name || !userData.email) {
throw new Error('Name and email are required');
}

// 检查邮箱是否已存在
const existingUser = await userModel.findByEmail(userData.email);
if (existingUser) {
throw new Error('Email already exists');
}

// 创建用户
return await userModel.create(userData);
},

// 更新用户
updateUser: async (id, userData) => {
// 检查用户是否存在
const existingUser = await userModel.findById(id);
if (!existingUser) {
return null;
}

// 验证更新数据
if (userData.email) {
// 检查新邮箱是否已被使用
const emailUser = await userModel.findByEmail(userData.email);
if (emailUser && emailUser.id !== id) {
throw new Error('Email already exists');
}
}

// 更新用户
return await userModel.update(id, userData);
},

// 删除用户
deleteUser: async (id) => {
// 检查用户是否存在
const existingUser = await userModel.findById(id);
if (!existingUser) {
return null;
}

// 删除用户
return await userModel.delete(id);
}
};

module.exports = userService;

8. RESTful API设计

8.1 RESTful API概念

REST (Representational State Transfer) 是一种软件架构风格,用于设计网络应用程序。RESTful API 是符合REST原则的API设计。

8.2 RESTful路由设计

RESTful API通常使用以下路由模式:

HTTP方法路由描述
GET/resources获取资源列表
GET/resources/:id获取单个资源
POST/resources创建新资源
PUT/resources/:id更新资源
DELETE/resources/:id删除资源

8.3 Koa实现RESTful API

const Koa = require('koa');
const Router = require('koa-router');
const bodyParser = require('koa-bodyparser');

const app = new Koa();
const router = new Router({ prefix: '/api' });

// 模拟数据
let users = [
{ id: 1, name: '张三', email: 'zhangsan@example.com' },
{ id: 2, name: '李四', email: 'lisi@example.com' }
];

// 获取所有用户
router.get('/users', async ctx => {
ctx.body = {
code: 200,
message: 'Success',
data: users
};
});

// 获取单个用户
router.get('/users/:id', async ctx => {
const id = parseInt(ctx.params.id);
const user = users.find(u => u.id === id);

if (!user) {
ctx.status = 404;
ctx.body = {
code: 404,
message: 'User not found'
};
return;
}

ctx.body = {
code: 200,
message: 'Success',
data: user
};
});

// 创建用户
router.post('/users', async ctx => {
const { name, email } = ctx.request.body;

if (!name || !email) {
ctx.status = 400;
ctx.body = {
code: 400,
message: 'Name and email are required'
};
return;
}

// 检查邮箱是否已存在
if (users.some(u => u.email === email)) {
ctx.status = 400;
ctx.body = {
code: 400,
message: 'Email already exists'
};
return;
}

// 创建新用户
const newUser = {
id: users.length + 1,
name,
email
};

users.push(newUser);

ctx.status = 201;
ctx.body = {
code: 201,
message: 'User created',
data: newUser
};
});

// 更新用户
router.put('/users/:id', async ctx => {
const id = parseInt(ctx.params.id);
const { name, email } = ctx.request.body;

const userIndex = users.findIndex(u => u.id === id);

if (userIndex === -1) {
ctx.status = 404;
ctx.body = {
code: 404,
message: 'User not found'
};
return;
}

// 检查邮箱是否已被其他用户使用
if (email && users.some(u => u.email === email && u.id !== id)) {
ctx.status = 400;
ctx.body = {
code: 400,
message: 'Email already exists'
};
return;
}

// 更新用户
users[userIndex] = {
...users[userIndex],
...(name && { name }),
...(email && { email })
};

ctx.body = {
code: 200,
message: 'User updated',
data: users[userIndex]
};
});

// 删除用户
router.delete('/users/:id', async ctx => {
const id = parseInt(ctx.params.id);
const userIndex = users.findIndex(u => u.id === id);

if (userIndex === -1) {
ctx.status = 404;
ctx.body = {
code: 404,
message: 'User not found'
};
return;
}

// 删除用户
users.splice(userIndex, 1);

ctx.body = {
code: 200,
message: 'User deleted'
};
});

// 应用中间件
app.use(bodyParser());
app.use(router.routes());
app.use(router.allowedMethods());

app.listen(3000);

9. 路由安全

9.1 输入验证

对所有用户输入进行验证是防止安全漏洞的重要措施:

const Joi = require('joi');

// 定义验证中间件
const validate = (schema) => {
return async (ctx, next) => {
try {
await schema.validateAsync(ctx.request.body);
await next();
} catch (error) {
ctx.status = 400;
ctx.body = {
code: 400,
message: error.details[0].message
};
}
};
};

// 用户创建验证规则
const userSchema = Joi.object({
name: Joi.string().min(3).max(30).required(),
email: Joi.string().email().required(),
password: Joi.string().min(6).required()
});

// 应用验证中间件
router.post('/users', validate(userSchema), async ctx => {
// 处理创建用户的逻辑
});

9.2 路径遍历防护

防止路径遍历攻击:

const path = require('path');

router.get('/files/:file*', async ctx => {
// 获取请求的文件路径
let filePath = ctx.params.file || '';

// 规范化路径
const normalizedPath = path.normalize(filePath);

// 检查是否存在路径遍历尝试
if (normalizedPath.includes('..')) {
ctx.status = 403;
ctx.body = {
code: 403,
message: 'Forbidden'
};
return;
}

// 处理文件请求
// ...
});

9.3 速率限制

使用速率限制中间件防止暴力攻击:

npm install koa-ratelimit
const ratelimit = require('koa-ratelimit');
const Redis = require('ioredis');
const redis = new Redis();

// 速率限制配置
const limiter = ratelimit({
db: redis,
duration: 60000, // 60秒
max: 100, // 最多100个请求
id: (ctx) => ctx.ip, // 使用IP作为标识符
errorMessage: 'Too many requests',
});

// 应用速率限制中间件
router.use('/api', limiter);

10. 路由测试

10.1 单元测试

使用Jest等测试框架测试路由处理函数:

npm install --save-dev jest supertest

测试文件 (test/routes.test.js):

const request = require('supertest');
const Koa = require('koa');
const Router = require('koa-router');
const bodyParser = require('koa-bodyparser');

// 创建测试应用
function createTestApp() {
const app = new Koa();
const router = new Router();

// 定义测试路由
router.get('/users', async ctx => {
ctx.body = {
code: 200,
data: [{ id: 1, name: 'Test User' }]
};
});

router.post('/users', async ctx => {
const { name } = ctx.request.body;
ctx.status = 201;
ctx.body = {
code: 201,
data: { id: 1, name }
};
});

// 应用中间件
app.use(bodyParser());
app.use(router.routes());
app.use(router.allowedMethods());

return app.callback();
}

// 测试路由
describe('Routes', () => {
const app = createTestApp();

test('GET /users should return users', async () => {
const response = await request(app).get('/users');
expect(response.status).toBe(200);
expect(response.body.code).toBe(200);
expect(response.body.data).toHaveLength(1);
});

test('POST /users should create user', async () => {
const response = await request(app)
.post('/users')
.send({ name: 'New User' });
expect(response.status).toBe(201);
expect(response.body.code).toBe(201);
expect(response.body.data.name).toBe('New User');
});
});

10.2 集成测试

测试路由与控制器、服务层的集成:

const request = require('supertest');
const Koa = require('koa');
const Router = require('koa-router');
const bodyParser = require('koa-bodyparser');

// 模拟服务层
jest.mock('../services/userService', () => ({
getAllUsers: jest.fn().mockResolvedValue([{ id: 1, name: 'Mock User' }]),
createUser: jest.fn().mockImplementation(data =>
Promise.resolve({ id: 1, ...data })
)
}));

// 创建应用
function createApp() {
const app = new Koa();
const router = new Router();

// 引入控制器
const userController = require('../controllers/userController');

// 定义路由
router.get('/users', userController.getAllUsers);
router.post('/users', userController.createUser);

// 应用中间件
app.use(bodyParser());
app.use(router.routes());
app.use(router.allowedMethods());

return app.callback();
}

// 集成测试
describe('Integration Tests', () => {
const app = createApp();

test('GET /users should return users from service', async () => {
const response = await request(app).get('/users');
expect(response.status).toBe(200);
expect(response.body.data).toHaveLength(1);
});

test('POST /users should create user through service', async () => {
const response = await request(app)
.post('/users')
.send({ name: 'Test', email: 'test@example.com' });
expect(response.status).toBe(201);
});
});

11. 实战案例:构建博客API

11.1 项目概述

在这个实战案例中,我们将构建一个完整的博客API,包含用户、文章、评论等功能模块。

11.2 技术栈

  • Koa 2.x
  • koa-router
  • koa-bodyparser
  • koa-session
  • Joi (数据验证)
  • 内存存储(实际项目中可替换为数据库)

11.3 项目结构

blog-api/
├── app.js
├── package.json
├── config/
│ └── index.js
├── middlewares/
│ ├── auth.js
│ ├── errorHandler.js
│ └── validator.js
├── controllers/
│ ├── userController.js
│ ├── postController.js
│ └── commentController.js
├── services/
│ ├── userService.js
│ ├── postService.js
│ └── commentService.js
├── models/
│ ├── userModel.js
│ ├── postModel.js
│ └── commentModel.js
└── routes/
├── index.js
├── userRoutes.js
├── postRoutes.js
└── commentRoutes.js

11.4 实现核心功能

1. 错误处理中间件 (middlewares/errorHandler.js)

module.exports = async (ctx, next) => {
try {
await next();
// 处理404错误
if (ctx.status === 404 && !ctx.body) {
ctx.status = 404;
ctx.body = {
code: 404,
message: 'Not Found'
};
}
} catch (err) {
console.error('Error:', err);
ctx.status = err.status || 500;
ctx.body = {
code: err.code || ctx.status,
message: err.message || 'Internal Server Error'
};
ctx.app.emit('error', err, ctx);
}
};

2. 身份验证中间件 (middlewares/auth.js)

module.exports = async (ctx, next) => {
// 检查是否已登录
if (!ctx.session.user) {
ctx.status = 401;
ctx.body = {
code: 401,
message: 'Unauthorized'
};
return;
}

// 将用户信息保存到上下文
ctx.user = ctx.session.user;
await next();
};

3. 用户路由 (routes/userRoutes.js)

const Router = require('koa-router');
const router = new Router({ prefix: '/api/users' });
const userController = require('../controllers/userController');
const auth = require('../middlewares/auth');

// 公共路由
router.post('/register', userController.register);
router.post('/login', userController.login);
router.post('/logout', userController.logout);

// 需要身份验证的路由
router.get('/profile', auth, userController.getProfile);
router.put('/profile', auth, userController.updateProfile);

module.exports = router;

4. 文章路由 (routes/postRoutes.js)

const Router = require('koa-router');
const router = new Router({ prefix: '/api/posts' });
const postController = require('../controllers/postController');
const auth = require('../middlewares/auth');

// 公共路由
router.get('/', postController.getAllPosts);
router.get('/:id', postController.getPostById);

// 需要身份验证的路由
router.post('/', auth, postController.createPost);
router.put('/:id', auth, postController.updatePost);
router.delete('/:id', auth, postController.deletePost);

module.exports = router;

5. 评论路由 (routes/commentRoutes.js)

const Router = require('koa-router');
const router = new Router({ prefix: '/api/comments' });
const commentController = require('../controllers/commentController');
const auth = require('../middlewares/auth');

// 公共路由
router.get('/post/:postId', commentController.getCommentsByPostId);

// 需要身份验证的路由
router.post('/', auth, commentController.createComment);
router.put('/:id', auth, commentController.updateComment);
router.delete('/:id', auth, commentController.deleteComment);

module.exports = router;

6. 路由整合 (routes/index.js)

const Router = require('koa-router');
const router = new Router();

// 引入各模块路由
const userRoutes = require('./userRoutes');
const postRoutes = require('./postRoutes');
const commentRoutes = require('./commentRoutes');

// 挂载路由
router.use(userRoutes.routes(), userRoutes.allowedMethods());
router.use(postRoutes.routes(), postRoutes.allowedMethods());
router.use(commentRoutes.routes(), commentRoutes.allowedMethods());

module.exports = router;

7. 应用入口 (app.js)

const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const session = require('koa-session');

// 中间件
const errorHandler = require('./middlewares/errorHandler');

// 路由
const routes = require('./routes');

// 创建应用
const app = new Koa();
const PORT = 3000;

// 配置
app.keys = ['blog-api-secret-key'];

// 应用中间件
app.use(errorHandler);
app.use(session({
key: 'blog:sess',
maxAge: 86400000,
httpOnly: true,
signed: true
}, app));
app.use(bodyParser());

// 应用路由
app.use(routes.routes());
app.use(routes.allowedMethods());

// 启动服务器
app.listen(PORT, () => {
console.log(`Blog API running on http://localhost:${PORT}`);
});

11.5 测试博客API

使用curl或Postman测试以下API端点:

  1. 用户相关

    • POST /api/users/register - 注册用户
    • POST /api/users/login - 用户登录
    • POST /api/users/logout - 用户登出
    • GET /api/users/profile - 获取用户信息
    • PUT /api/users/profile - 更新用户信息
  2. 文章相关

    • GET /api/posts - 获取所有文章
    • GET /api/posts/:id - 获取单篇文章
    • POST /api/posts - 创建文章(需要登录)
    • PUT /api/posts/:id - 更新文章(需要登录)
    • DELETE /api/posts/:id - 删除文章(需要登录)
  3. 评论相关

    • GET /api/comments/post/:postId - 获取文章评论
    • POST /api/comments - 创建评论(需要登录)
    • PUT /api/comments/:id - 更新评论(需要登录)
    • DELETE /api/comments/:id - 删除评论(需要登录)

12. 总结与进阶建议

通过本章节的学习,你应该已经掌握了Koa路由系统的核心概念、基本用法和高级特性。路由是Web应用的重要组成部分,合理的路由设计和组织对于构建可维护、可扩展的应用至关重要。

进阶学习建议

  • 学习更多高级路由技术,如路由缓存、路由预热等
  • 探索其他路由中间件,如koa-route、koa-compose等
  • 深入理解RESTful API设计原则和最佳实践
  • 学习API文档生成工具,如Swagger、API Blueprint等
  • 了解API版本控制策略

在下一章节,我们将深入学习Koa的错误处理机制,了解如何构建健壮的错误处理系统。