路由方法 #
一、HTTP方法概述 #
1.1 支持的方法 #
Hapi支持以下HTTP方法:
| 方法 | 说明 | 用途 |
|---|---|---|
| GET | 获取资源 | 查询数据 |
| POST | 创建资源 | 提交数据 |
| PUT | 更新资源(完整) | 替换数据 |
| PATCH | 更新资源(部分) | 修改数据 |
| DELETE | 删除资源 | 删除数据 |
| OPTIONS | 获取支持的方法 | CORS预检 |
| HEAD | 获取响应头 | 检查资源 |
| * | 匹配所有方法 | 通用处理 |
1.2 方法定义 #
javascript
server.route({
method: 'GET',
path: '/users',
handler: (request, h) => {
return 'GET Request';
}
});
二、GET请求 #
2.1 基本GET请求 #
javascript
server.route({
method: 'GET',
path: '/users',
handler: (request, h) => {
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
return users;
}
});
2.2 带路径参数的GET #
javascript
server.route({
method: 'GET',
path: '/users/{id}',
options: {
validate: {
params: Joi.object({
id: Joi.number().required()
})
}
},
handler: (request, h) => {
const user = { id: request.params.id, name: 'User' };
return user;
}
});
2.3 带查询参数的GET #
javascript
server.route({
method: 'GET',
path: '/users',
options: {
validate: {
query: Joi.object({
name: Joi.string(),
page: Joi.number().default(1),
limit: Joi.number().default(10)
})
}
},
handler: async (request, h) => {
const { name, page, limit } = request.query;
const users = await User.find({ name }, { page, limit });
return users;
}
});
三、POST请求 #
3.1 基本POST请求 #
javascript
server.route({
method: 'POST',
path: '/users',
handler: (request, h) => {
const user = request.payload;
return h.response(user).code(201);
}
});
3.2 带验证的POST #
javascript
server.route({
method: 'POST',
path: '/users',
options: {
validate: {
payload: Joi.object({
name: Joi.string().min(2).max(50).required(),
email: Joi.string().email().required(),
password: Joi.string().min(6).required()
})
}
},
handler: async (request, h) => {
const user = await UserService.create(request.payload);
return h.response(user).code(201);
}
});
3.3 文件上传POST #
javascript
server.route({
method: 'POST',
path: '/upload',
options: {
payload: {
output: 'file',
parse: true,
maxBytes: 10 * 1024 * 1024
}
},
handler: (request, h) => {
const file = request.payload.file;
return {
filename: file.filename,
headers: file.headers
};
}
});
四、PUT请求 #
4.1 基本PUT请求 #
javascript
server.route({
method: 'PUT',
path: '/users/{id}',
options: {
validate: {
params: Joi.object({
id: Joi.number().required()
}),
payload: Joi.object({
name: Joi.string().required(),
email: Joi.string().email().required()
})
}
},
handler: async (request, h) => {
const { id } = request.params;
const userData = request.payload;
const user = await UserService.update(id, userData);
return user;
}
});
4.2 完整更新示例 #
javascript
server.route({
method: 'PUT',
path: '/articles/{id}',
options: {
validate: {
params: Joi.object({
id: Joi.string().required()
}),
payload: Joi.object({
title: Joi.string().required(),
content: Joi.string().required(),
author: Joi.string().required(),
tags: Joi.array().items(Joi.string())
})
}
},
handler: async (request, h) => {
const article = await Article.update(
request.params.id,
request.payload
);
return article;
}
});
五、PATCH请求 #
5.1 基本PATCH请求 #
javascript
server.route({
method: 'PATCH',
path: '/users/{id}',
options: {
validate: {
params: Joi.object({
id: Joi.number().required()
}),
payload: Joi.object({
name: Joi.string(),
email: Joi.string().email(),
age: Joi.number()
}).min(1)
}
},
handler: async (request, h) => {
const user = await UserService.patch(
request.params.id,
request.payload
);
return user;
}
});
5.2 部分更新示例 #
javascript
server.route({
method: 'PATCH',
path: '/articles/{id}/status',
options: {
validate: {
params: Joi.object({
id: Joi.string().required()
}),
payload: Joi.object({
status: Joi.string().valid('draft', 'published', 'archived')
})
}
},
handler: async (request, h) => {
const article = await Article.updateStatus(
request.params.id,
request.payload.status
);
return article;
}
});
六、DELETE请求 #
6.1 基本DELETE请求 #
javascript
server.route({
method: 'DELETE',
path: '/users/{id}',
options: {
validate: {
params: Joi.object({
id: Joi.number().required()
})
}
},
handler: async (request, h) => {
await UserService.delete(request.params.id);
return h.response().code(204);
}
});
6.2 带确认的DELETE #
javascript
server.route({
method: 'DELETE',
path: '/articles/{id}',
options: {
validate: {
params: Joi.object({
id: Joi.string().required()
}),
query: Joi.object({
confirm: Joi.boolean().truthy('true').required()
})
}
},
handler: async (request, h) => {
if (!request.query.confirm) {
return h.response({ message: '请确认删除' }).code(400);
}
await Article.delete(request.params.id);
return h.response().code(204);
}
});
七、OPTIONS请求 #
7.1 CORS预检 #
Hapi自动处理OPTIONS请求,但可以自定义:
javascript
server.route({
method: 'OPTIONS',
path: '/api/{path*}',
options: {
cors: {
origin: ['https://example.com'],
headers: ['Accept', 'Content-Type', 'Authorization'],
methods: ['GET', 'POST', 'PUT', 'DELETE']
}
},
handler: (request, h) => {
return h.response().code(204);
}
});
八、HEAD请求 #
8.1 HEAD请求处理 #
javascript
server.route({
method: 'HEAD',
path: '/resources/{id}',
handler: (request, h) => {
return h.response()
.header('Content-Length', '1234')
.header('Content-Type', 'application/json')
.header('Last-Modified', new Date().toUTCString());
}
});
九、通配方法 #
9.1 匹配所有方法 #
javascript
server.route({
method: '*',
path: '/api/{path*}',
handler: (request, h) => {
return {
method: request.method,
path: request.params.path
};
}
});
9.2 代理转发 #
javascript
const Wreck = require('@hapi/wreck');
server.route({
method: '*',
path: '/proxy/{path*}',
handler: async (request, h) => {
const { method, params, payload } = request;
const targetUrl = `https://api.example.com/${params.path}`;
const { payload: response } = await Wreck.request(
method,
targetUrl,
{ payload }
);
return response;
}
});
十、方法组合 #
10.1 RESTful资源路由 #
javascript
const userHandlers = require('../handlers/users');
server.route([
{
method: 'GET',
path: '/users',
handler: userHandlers.getAll
},
{
method: 'GET',
path: '/users/{id}',
handler: userHandlers.getById
},
{
method: 'POST',
path: '/users',
handler: userHandlers.create
},
{
method: 'PUT',
path: '/users/{id}',
handler: userHandlers.update
},
{
method: 'PATCH',
path: '/users/{id}',
handler: userHandlers.patch
},
{
method: 'DELETE',
path: '/users/{id}',
handler: userHandlers.remove
}
]);
10.2 资源嵌套路由 #
javascript
server.route([
{
method: 'GET',
path: '/users/{userId}/posts',
handler: getUserPosts
},
{
method: 'POST',
path: '/users/{userId}/posts',
handler: createUserPost
},
{
method: 'GET',
path: '/users/{userId}/posts/{postId}',
handler: getUserPost
},
{
method: 'DELETE',
path: '/users/{userId}/posts/{postId}',
handler: deleteUserPost
}
]);
十一、方法限制 #
11.1 允许的方法 #
javascript
server.route({
method: 'GET',
path: '/resource',
options: {
response: {
failAction: 'log'
}
},
handler: (request, h) => {
return { data: 'value' };
}
});
11.2 方法验证 #
javascript
server.route({
method: 'POST',
path: '/data',
options: {
validate: {
method: (value, request) => {
if (request.method !== 'post') {
throw new Error('Only POST allowed');
}
return value;
}
}
},
handler: (request, h) => {
return request.payload;
}
});
十二、最佳实践 #
12.1 RESTful设计 #
javascript
server.route([
{
method: 'GET',
path: '/products',
options: {
description: '获取产品列表',
tags: ['api']
},
handler: getProducts
},
{
method: 'GET',
path: '/products/{id}',
options: {
description: '获取单个产品',
tags: ['api']
},
handler: getProduct
},
{
method: 'POST',
path: '/products',
options: {
description: '创建产品',
tags: ['api']
},
handler: createProduct
},
{
method: 'PUT',
path: '/products/{id}',
options: {
description: '更新产品',
tags: ['api']
},
handler: updateProduct
},
{
method: 'DELETE',
path: '/products/{id}',
options: {
description: '删除产品',
tags: ['api']
},
handler: deleteProduct
}
]);
12.2 状态码规范 #
| 方法 | 成功状态码 | 说明 |
|---|---|---|
| GET | 200 | 成功获取 |
| POST | 201 | 创建成功 |
| PUT | 200 | 更新成功 |
| PATCH | 200 | 部分更新成功 |
| DELETE | 204 | 删除成功(无内容) |
javascript
server.route({
method: 'POST',
path: '/users',
handler: async (request, h) => {
const user = await createUser(request.payload);
return h.response(user).code(201);
}
});
server.route({
method: 'DELETE',
path: '/users/{id}',
handler: async (request, h) => {
await deleteUser(request.params.id);
return h.response().code(204);
}
});
十三、总结 #
路由方法要点:
| 方法 | 用途 | 状态码 |
|---|---|---|
| GET | 获取资源 | 200 |
| POST | 创建资源 | 201 |
| PUT | 完整更新 | 200 |
| PATCH | 部分更新 | 200 |
| DELETE | 删除资源 | 204 |
| * | 通配方法 | - |
下一步,让我们深入学习路由参数!
最后更新:2026-03-28