路由方法 #

一、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