常用插件 #

一、核心插件 #

1.1 @hapi/inert #

静态文件服务插件:

bash
npm install @hapi/inert
javascript
const Inert = require('@hapi/inert');

await server.register(Inert);

server.route({
    method: 'GET',
    path: '/static/{param*}',
    handler: {
        directory: {
            path: './public',
            listing: true
        }
    }
});

server.route({
    method: 'GET',
    path: '/download',
    handler: (request, h) => {
        return h.file('./files/document.pdf', {
            mode: 'attachment'
        });
    }
});

1.2 @hapi/vision #

模板引擎支持插件:

bash
npm install @hapi/vision ejs
javascript
const Vision = require('@hapi/vision');

await server.register(Vision);

server.views({
    engines: {
        ejs: require('ejs')
    },
    path: './views',
    layout: true
});

server.route({
    method: 'GET',
    path: '/page',
    handler: (request, h) => {
        return h.view('index', {
            title: 'Hello',
            message: 'Welcome!'
        });
    }
});

1.3 @hapi/cookie #

Cookie认证插件:

bash
npm install @hapi/cookie
javascript
const Cookie = require('@hapi/cookie');

await server.register(Cookie);

server.auth.strategy('session', 'cookie', {
    cookie: {
        name: 'session',
        password: 'password-should-be-32-characters',
        isSecure: false
    },
    redirectTo: '/login',
    validateFunc: async (request, session) => {
        const user = await User.findById(session.id);
        if (!user) {
            return { valid: false };
        }
        return { valid: true, credentials: user };
    }
});

server.auth.default('session');

1.4 @hapi/jwt #

JWT认证插件:

bash
npm install @hapi/jwt
javascript
const Jwt = require('@hapi/jwt');

await server.register(Jwt);

server.auth.strategy('jwt', 'jwt', {
    keys: 'your-secret-key',
    verify: {
        aud: 'urn:audience:test',
        iss: 'urn:issuer:test',
        sub: false,
        nbf: true,
        exp: true,
        maxAgeSec: 14400
    },
    validate: (artifacts, request, h) => {
        return {
            isValid: true,
            credentials: { user: artifacts.decoded.payload.user }
        };
    }
});

server.auth.default('jwt');

二、开发插件 #

2.1 @hapi/good #

日志插件:

bash
npm install @hapi/good @hapi/good-console @hapi/good-squeeze
javascript
const Good = require('@hapi/good');

await server.register({
    plugin: Good,
    options: {
        ops: {
            interval: 1000
        },
        reporters: {
            console: [
                {
                    module: '@hapi/good-squeeze',
                    name: 'Squeeze',
                    args: [{ log: '*', response: '*' }]
                },
                {
                    module: '@hapi/good-console'
                },
                'stdout'
            ]
        }
    }
});

2.2 @hapi/bell #

第三方OAuth认证插件:

bash
npm install @hapi/bell
javascript
const Bell = require('@hapi/bell');

await server.register(Bell);

server.auth.strategy('github', 'bell', {
    provider: 'github',
    password: 'cookie-encryption-password',
    clientId: 'your-github-client-id',
    clientSecret: 'your-github-client-secret',
    isSecure: false
});

server.route({
    method: ['GET', 'POST'],
    path: '/login/github',
    options: {
        auth: 'github',
        handler: (request, h) => {
            if (!request.auth.isAuthenticated) {
                return 'Authentication failed';
            }
            return request.auth.credentials;
        }
    }
});

2.3 @hapi/swagger #

API文档插件:

bash
npm install @hapi/swagger @hapi/inert @hapi/vision
javascript
const Inert = require('@hapi/inert');
const Vision = require('@hapi/vision');
const HapiSwagger = require('hapi-swagger');

const swaggerOptions = {
    info: {
        title: 'API Documentation',
        version: '1.0.0'
    }
};

await server.register([
    Inert,
    Vision,
    {
        plugin: HapiSwagger,
        options: swaggerOptions
    }
]);

server.route({
    method: 'GET',
    path: '/users',
    options: {
        description: 'Get all users',
        tags: ['api'],
        handler: (request, h) => {
            return { users: [] };
        }
    }
});

三、安全插件 #

3.1 @hapi/crumb #

CSRF防护插件:

bash
npm install @hapi/crumb
javascript
const Crumb = require('@hapi/crumb');

await server.register({
    plugin: Crumb,
    options: {
        cookieOptions: {
            isSecure: false
        }
    }
});

server.route({
    method: 'POST',
    path: '/form',
    options: {
        plugins: {
            crumb: true
        }
    },
    handler: (request, h) => {
        return { message: 'Form submitted' };
    }
});

3.2 @hapi/scooter #

User Agent解析插件:

bash
npm install @hapi/scooter
javascript
const Scooter = require('@hapi/scooter');

await server.register(Scooter);

server.route({
    method: 'GET',
    path: '/browser',
    handler: (request, h) => {
        return {
            browser: request.plugins.scooter.browser,
            os: request.plugins.scooter.os
        };
    }
});

四、数据库插件 #

4.1 hapi-mongodb #

MongoDB集成插件:

bash
npm install hapi-mongodb
javascript
await server.register({
    plugin: require('hapi-mongodb'),
    options: {
        url: 'mongodb://localhost:27017/mydb',
        settings: {
            poolSize: 10
        },
        decorate: true
    }
});

server.route({
    method: 'GET',
    path: '/users',
    handler: async (request, h) => {
        const db = request.mongo.db;
        const users = await db.collection('users').find({}).toArray();
        return users;
    }
});

4.2 hapi-sequelizejs #

Sequelize ORM插件:

bash
npm install hapi-sequelizejs sequelize pg
javascript
await server.register({
    plugin: require('hapi-sequelizejs'),
    options: [
        {
            name: 'mydb',
            models: ['./models/**/*.js'],
            sequelize: new Sequelize('mydb', 'user', 'pass', {
                dialect: 'postgres'
            })
        }
    ]
});

server.route({
    method: 'GET',
    path: '/users',
    handler: async (request, h) => {
        const { User } = request.server.models().mydb;
        return await User.findAll();
    }
});

五、缓存插件 #

5.1 @hapi/catbox-redis #

Redis缓存插件:

bash
npm install @hapi/catbox-redis
javascript
const CatboxRedis = require('@hapi/catbox-redis');

const server = Hapi.server({
    port: 3000,
    cache: [
        {
            name: 'redis-cache',
            provider: {
                constructor: CatboxRedis,
                options: {
                    partition: 'my-app',
                    host: 'localhost',
                    port: 6379
                }
            }
        }
    ]
});

server.method('getUser', async (id) => {
    return await User.findById(id);
}, {
    cache: {
        cache: 'redis-cache',
        expiresIn: 60 * 1000,
        generateTimeout: 100
    }
});

六、验证插件 #

6.1 @hapi/joi #

数据验证库:

bash
npm install @hapi/joi
javascript
const Joi = require('@hapi/joi');

server.route({
    method: 'POST',
    path: '/users',
    options: {
        validate: {
            payload: Joi.object({
                name: Joi.string().min(2).max(50).required(),
                email: Joi.string().email().required(),
                age: Joi.number().integer().min(0).max(120)
            })
        }
    },
    handler: (request, h) => {
        return request.payload;
    }
});

七、错误处理插件 #

7.1 @hapi/boom #

HTTP错误处理:

bash
npm install @hapi/boom
javascript
const Boom = require('@hapi/boom');

server.route({
    method: 'GET',
    path: '/users/{id}',
    handler: async (request, h) => {
        const user = await User.findById(request.params.id);
        
        if (!user) {
            throw Boom.notFound('User not found');
        }
        
        if (!user.active) {
            throw Boom.forbidden('User is inactive');
        }
        
        return user;
    }
});

八、HTTP客户端插件 #

8.1 @hapi/wreck #

HTTP客户端:

bash
npm install @hapi/wreck
javascript
const Wreck = require('@hapi/wreck');

server.route({
    method: 'GET',
    path: '/proxy',
    handler: async (request, h) => {
        const { payload } = await Wreck.get('https://api.example.com/data');
        return payload;
    }
});

server.route({
    method: 'POST',
    path: '/forward',
    handler: async (request, h) => {
        const { payload } = await Wreck.post('https://api.example.com/data', {
            payload: request.payload
        });
        return payload;
    }
});

九、文件上传插件 #

9.1 hapi-payload #

处理文件上传:

javascript
server.route({
    method: 'POST',
    path: '/upload',
    options: {
        payload: {
            output: 'file',
            parse: true,
            maxBytes: 10 * 1024 * 1024,
            multipart: true
        }
    },
    handler: (request, h) => {
        const file = request.payload.file;
        return {
            filename: file.filename,
            headers: file.headers,
            bytes: file.bytes
        };
    }
});

十、插件组合示例 #

10.1 完整配置 #

javascript
const Hapi = require('@hapi/hapi');
const Inert = require('@hapi/inert');
const Vision = require('@hapi/vision');
const Jwt = require('@hapi/jwt');
const Boom = require('@hapi/boom');
const Joi = require('@hapi/joi');

const init = async () => {
    const server = Hapi.server({ port: 3000 });
    
    await server.register([
        Inert,
        Vision,
        Jwt
    ]);
    
    server.auth.strategy('jwt', 'jwt', {
        keys: process.env.JWT_SECRET,
        verify: {
            aud: false,
            iss: false,
            sub: false,
            nbf: true,
            exp: true
        },
        validate: (artifacts, request, h) => {
            return {
                isValid: true,
                credentials: artifacts.decoded.payload
            };
        }
    });
    
    server.route([
        {
            method: 'GET',
            path: '/static/{param*}',
            handler: {
                directory: {
                    path: './public'
                }
            }
        },
        {
            method: 'GET',
            path: '/profile',
            options: {
                auth: 'jwt'
            },
            handler: (request, h) => {
                return request.auth.credentials;
            }
        }
    ]);
    
    await server.start();
    console.log('Server running on %s', server.info.uri);
};

init();

十一、总结 #

常用插件列表:

插件 用途
@hapi/inert 静态文件服务
@hapi/vision 模板引擎
@hapi/cookie Cookie认证
@hapi/jwt JWT认证
@hapi/good 日志记录
@hapi/bell OAuth认证
@hapi/joi 数据验证
@hapi/boom 错误处理
@hapi/wreck HTTP客户端

下一步,让我们深入学习请求与响应!

最后更新:2026-03-28