Hapi.js是用于构建Web应用程序的框架。 这篇文章包含了热启动的所有基本要素。 不幸的是,作者根本不是作家,因此会有很多代码和少量文字。
最有价值球员
放一堆依赖项:
npm i @hapi/hapi @hapi/boom filepaths hapi-boom-decorators
- hapi / hapi-实际上,我们的服务器
- hapi / boom-用于生成标准答案的模块
- hapi-boom-decorators- hapi /繁荣的助手
- filepaths-递归读取文件夹的实用程序
创建一个文件夹结构和一堆启动文件:

在./src/routes/中,我们添加了api端点的描述,即1个文件-1个端点:
./src/server.js-导出服务器本身的模块。
在./server.js中,我们要做的只是调用createServer()
#!/usr/bin/env node const createServer = require('./src/server'); createServer();
我们启动
node server.js
并检查:
curl http://127.0.0.1:3030/ {"result":"ok","message":"Hello World!"} curl http://127.0.0.1:3030/test {"statusCode":404,"error":"Not Found","message":"Not Found"}
在野外
至少在一个实际项目中,我们需要一个数据库,一个记录器,授权,错误处理等等。
添加续集
ORM sequelize作为模块连接:
... const Sequelize = require('sequelize'); ... await server.register([ ... { plugin: require('hapi-sequelizejs'), options: [ { name: config.db.database,
通过调用,该数据库在路由内部变得可用:
async function response(request) { const model = request.getModel('_', '_'); }
向请求中注入其他模块
有必要拦截“ onRequest”事件,在该事件中,我们将配置和记录器注入到请求对象中:
... const Logger = require('./libs/Logger'); ... async function createServer(logLVL=config.logLVL) { ... const logger = new Logger(logLVL, 'my-hapi-app'); ... server.ext({ type: 'onRequest', method: async function (request, h) { request.server.config = Object.assign({}, config); request.server.logger = logger; return h.continue; } }); ... }
之后,在请求处理程序内,我们将可以访问配置,记录器和数据库,而无需在模块主体中另外包含一些内容:
因此,输入处的请求处理程序将接收其处理所需的所有内容,并且不必每次都包含相同的模块。
登入
hapi中的授权以模块形式进行。
... const AuthBearer = require('hapi-auth-bearer-token'); ... async function createServer(logLVL=config.logLVL) { ... await server.register([ AuthBearer, ... ]); server.auth.strategy('token', 'bearer-access-token', {
并且在路由内,您需要指定要使用的授权类型:
module.exports = { method: 'GET', path: '/', auth: 'token',
如果使用了几种授权类型:
auth: { strategies: ['token1', 'token2', 'something_else'] },
错误处理
默认情况下,臂杆以标准方式生成错误,通常这些答案需要以自己的格式包装。
server.ext('onPreResponse', function (request, h) {
数据模式
这是一个很小但很重要的话题。 数据方案使您可以检查请求的有效性和响应的正确性。 您对这些方案的描述有多好,所以摇摇欲坠和自动测试将具有如此的质量。
所有数据方案均通过joi进行描述。 让我们以用户授权为例:
const Joi = require('@hapi/joi'); const Boom = require('boom'); async function response(request) {
测试:
curl -X GET "http://localhost:3030/auth?login=pupkin@gmail.com&password=12345"

现在发送而不是邮件,只需登录:
curl -X GET "http://localhost:3030/auth?login=pupkin&password=12345"

如果答案与响应方案不匹配,则服务器也将陷入500错误。
如果项目每小时开始处理超过1个请求,则可能有必要限制对响应的验证,因为 验证是一项资源密集型操作。 为此有一个参数:“样本”
module.exports = { method: 'GET', path: '/auth', options: { handler: response, validate: { query: requestScheme }, response: { sample: 50, schema: responseScheme } } };
这样,只有50%的请求将是经过验证的响应。
描述默认值和示例非常重要,将来它们将用于生成文档和自动测试。
Swagger / OpenAPI
我们需要一堆其他模块:
npm i hapi-swagger @hapi/inert @hapi/vision
我们将它们连接到server.js
... const Inert = require('@hapi/inert'); const Vision = require('@hapi/vision'); const HapiSwagger = require('hapi-swagger'); const Package = require('../package'); ... const swaggerOptions = { info: { title: Package.name + ' API Documentation', description: Package.description }, jsonPath: '/documentation.json', documentationPath: '/documentation', schemes: ['https', 'http'], host: config.swaggerHost, debug: true }; ... async function createServer(logLVL=config.logLVL) { ... await server.register([ ... Inert, Vision, { plugin: HapiSwagger, options: swaggerOptions }, ... ]); ... });
在每条路线中,您都需要添加标签“ api”:
module.exports = { method: 'GET', path: '/auth', options: { handler: response, tags: [ 'api' ],
现在,在http:// localhost:3030 / documentation上将提供一个带有文档的Web界面,在http:// localhost:3030 /documentation.json .json中提供了说明。

自动测试生成
如果我们定性地描述了请求和响应方案,并准备了与请求示例中描述的示例相对应的种子数据库,则根据众所周知的方案,您可以自动生成请求并检查服务器响应代码。
例如,在GET中:/ auth需要登录名和密码参数,我们将从图中指定的示例中获取它们:
const requestScheme =Joi.object({ login: Joi.string().email().required().example('pupkin@gmail.com'), password: Joi.string().required().example('12345') });
如果服务器以HTTP-200-OK响应,那么我们将假定测试已通过。
不幸的是,没有现成的合适模块;您必须多说一点:
不要忘记依赖项:
npm i request-promise mocha sync-request
关于package.json
... "scripts": { "test": "mocha", "dbinit": "node ./scripts/dbInit.js" }, ...
我们检查:
npm test

并且如果锁是某种数据方案,或者答案与方案不匹配:

并且不要忘记,测试迟早会对数据库中的数据变得敏感。 在运行测试之前,您至少需要擦除数据库。
全部来源