Response对象 #
一、Response概述 #
1.1 创建响应 #
使用 h.response() 创建响应对象:
javascript
server.route({
method: 'GET',
path: '/hello',
handler: (request, h) => {
return h.response({ message: 'Hello!' });
}
});
1.2 直接返回值 #
处理函数可以直接返回值,Hapi会自动包装:
javascript
server.route({
method: 'GET',
path: '/simple',
handler: (request, h) => {
return { message: 'Simple response' };
}
});
二、响应类型 #
2.1 JSON响应 #
javascript
server.route({
method: 'GET',
path: '/json',
handler: (request, h) => {
return {
success: true,
data: {
id: 1,
name: 'Test'
}
};
}
});
2.2 文本响应 #
javascript
server.route({
method: 'GET',
path: '/text',
handler: (request, h) => {
return h.response('Plain text response')
.type('text/plain');
}
});
2.3 HTML响应 #
javascript
server.route({
method: 'GET',
path: '/html',
handler: (request, h) => {
return h.response('<h1>Hello World</h1>')
.type('text/html');
}
});
2.4 文件响应 #
javascript
server.route({
method: 'GET',
path: '/download',
handler: (request, h) => {
return h.file('./files/document.pdf', {
mode: 'attachment',
filename: 'document.pdf'
});
}
});
2.5 流响应 #
javascript
const fs = require('fs');
server.route({
method: 'GET',
path: '/stream',
handler: (request, h) => {
const stream = fs.createReadStream('./files/data.txt');
return h.response(stream)
.type('text/plain');
}
});
2.6 视图响应 #
javascript
server.route({
method: 'GET',
path: '/page',
handler: (request, h) => {
return h.view('index', {
title: 'Hello',
message: 'Welcome!'
});
}
});
三、状态码 #
3.1 设置状态码 #
javascript
server.route({
method: 'POST',
path: '/create',
handler: (request, h) => {
return h.response({ id: 1 })
.code(201);
}
});
3.2 常用状态码 #
javascript
server.route([
{
method: 'POST',
path: '/created',
handler: (request, h) => {
return h.response({ message: 'Created' }).code(201);
}
},
{
method: 'DELETE',
path: '/delete',
handler: (request, h) => {
return h.response().code(204);
}
},
{
method: 'GET',
path: '/redirect',
handler: (request, h) => {
return h.redirect('/new-location');
}
}
]);
3.3 状态消息 #
javascript
server.route({
method: 'GET',
path: '/message',
handler: (request, h) => {
return h.response({ data: 'value' })
.code(200)
.message('Success');
}
});
四、响应头 #
4.1 设置单个响应头 #
javascript
server.route({
method: 'GET',
path: '/header',
handler: (request, h) => {
return h.response({ message: 'Hello' })
.header('X-Custom-Header', 'value');
}
});
4.2 设置多个响应头 #
javascript
server.route({
method: 'GET',
path: '/headers',
handler: (request, h) => {
return h.response('Response')
.header('X-API-Version', '1.0')
.header('X-Request-Id', '12345')
.header('Cache-Control', 'no-cache');
}
});
4.3 常用响应头 #
javascript
server.route({
method: 'GET',
path: '/api/data',
handler: (request, h) => {
return h.response({ data: [] })
.header('Content-Type', 'application/json')
.header('Cache-Control', 'max-age=3600')
.header('X-RateLimit-Limit', 100)
.header('X-RateLimit-Remaining', 99);
}
});
4.4 追加响应头 #
javascript
server.route({
method: 'GET',
path: '/append',
handler: (request, h) => {
return h.response('Response')
.header('Set-Cookie', 'a=1')
.header('Set-Cookie', 'b=2', { append: true });
}
});
五、Content-Type #
5.1 设置Content-Type #
javascript
server.route({
method: 'GET',
path: '/type',
handler: (request, h) => {
return h.response('<h1>HTML</h1>')
.type('text/html');
}
});
5.2 设置字符集 #
javascript
server.route({
method: 'GET',
path: '/charset',
handler: (request, h) => {
return h.response('中文内容')
.type('text/plain')
.charset('utf-8');
}
});
5.3 常见Content-Type #
javascript
server.route([
{
method: 'GET',
path: '/json-type',
handler: (request, h) => {
return h.response({ data: 'value' })
.type('application/json');
}
},
{
method: 'GET',
path: '/xml-type',
handler: (request, h) => {
return h.response('<root><item>value</item></root>')
.type('application/xml');
}
},
{
method: 'GET',
path: '/pdf-type',
handler: (request, h) => {
return h.file('./document.pdf')
.type('application/pdf');
}
}
]);
六、重定向 #
6.1 基本重定向 #
javascript
server.route({
method: 'GET',
path: '/redirect',
handler: (request, h) => {
return h.redirect('/target');
}
});
6.2 永久重定向 #
javascript
server.route({
method: 'GET',
path: '/permanent',
handler: (request, h) => {
return h.redirect('/new-url').permanent(true);
}
});
6.3 临时重定向 #
javascript
server.route({
method: 'GET',
path: '/temporary',
handler: (request, h) => {
return h.redirect('/target').temporary(true);
}
});
6.4 重写URL #
javascript
server.route({
method: 'GET',
path: '/rewrite',
handler: (request, h) => {
return h.redirect('/target').rewritable(false);
}
});
七、Cookie操作 #
7.1 设置Cookie #
javascript
server.route({
method: 'POST',
path: '/login',
handler: (request, h) => {
return h.response({ message: 'Logged in' })
.state('sessionId', 'abc123', {
ttl: 24 * 60 * 60 * 1000,
isSecure: true,
isHttpOnly: true,
path: '/'
});
}
});
7.2 设置多个Cookie #
javascript
server.route({
method: 'GET',
path: '/cookies',
handler: (request, h) => {
return h.response({ message: 'Cookies set' })
.state('user', 'john')
.state('theme', 'dark');
}
});
7.3 清除Cookie #
javascript
server.route({
method: 'POST',
path: '/logout',
handler: (request, h) => {
return h.response({ message: 'Logged out' })
.unstate('sessionId')
.unstate('user');
}
});
八、响应压缩 #
8.1 启用压缩 #
javascript
const server = Hapi.server({
port: 3000,
compression: {
minBytes: 1024
}
});
8.2 禁用压缩 #
javascript
server.route({
method: 'GET',
path: '/no-compress',
handler: (request, h) => {
return h.response(largeData)
.compression(false);
}
});
九、响应缓存 #
9.1 设置缓存头 #
javascript
server.route({
method: 'GET',
path: '/cached',
handler: (request, h) => {
return h.response({ data: 'value' })
.header('Cache-Control', 'max-age=3600, public')
.header('ETag', 'abc123');
}
});
9.2 服务器缓存 #
javascript
server.method('getData', async () => {
return await fetchData();
}, {
cache: {
expiresIn: 60 * 1000,
generateTimeout: 100
}
});
server.route({
method: 'GET',
path: '/data',
handler: async (request, h) => {
return await server.methods.getData();
}
});
十、响应验证 #
10.1 响应Schema验证 #
javascript
server.route({
method: 'GET',
path: '/users/{id}',
options: {
response: {
schema: Joi.object({
id: Joi.number().required(),
name: Joi.string().required(),
email: Joi.string().email().required()
})
}
},
handler: async (request, h) => {
return await getUser(request.params.id);
}
});
10.2 响应修改 #
javascript
server.route({
method: 'GET',
path: '/users',
options: {
response: {
modify: true,
options: {
stripUnknown: true
}
}
},
handler: (request, h) => {
return { id: 1, name: 'Test', password: 'secret' };
}
});
十一、响应方法链 #
11.1 链式调用 #
javascript
server.route({
method: 'POST',
path: '/create',
handler: (request, h) => {
return h.response({ id: 1, name: 'Test' })
.code(201)
.message('Created successfully')
.type('application/json')
.header('X-Request-Id', '12345')
.header('X-Created-At', new Date().toISOString())
.state('lastAction', 'create');
}
});
十二、错误响应 #
12.1 使用Boom #
javascript
const Boom = require('@hapi/boom');
server.route({
method: 'GET',
path: '/users/{id}',
handler: async (request, h) => {
const user = await getUser(request.params.id);
if (!user) {
throw Boom.notFound('User not found');
}
if (!user.active) {
throw Boom.forbidden('User is inactive');
}
return user;
}
});
12.2 自定义错误响应 #
javascript
server.ext('onPreResponse', (request, h) => {
const response = request.response;
if (response.isBoom) {
const error = response;
return h.response({
success: false,
error: {
code: error.output.statusCode,
message: error.message,
details: error.data
}
}).code(error.output.statusCode);
}
return h.continue;
});
十三、完整示例 #
13.1 API响应封装 #
javascript
server.decorate('server', 'apiResponse', function (data, options = {}) {
return h.response({
success: true,
data: data,
timestamp: new Date().toISOString()
})
.code(options.code || 200)
.header('X-API-Version', '1.0');
});
server.decorate('server', 'apiError', function (message, code = 400) {
return h.response({
success: false,
error: {
message: message,
code: code
},
timestamp: new Date().toISOString()
})
.code(code);
});
server.route({
method: 'GET',
path: '/users',
handler: async (request, h) => {
const users = await getUsers();
return server.apiResponse(users);
}
});
十四、总结 #
Response对象要点:
| 方法 | 说明 |
|---|---|
| h.response() | 创建响应 |
| code() | 设置状态码 |
| header() | 设置响应头 |
| type() | 设置Content-Type |
| redirect() | 重定向 |
| state() | 设置Cookie |
| unstate() | 清除Cookie |
下一步,让我们学习数据验证!
最后更新:2026-03-28