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