使用 Hapi 开发 RESTful APIs

栏目: 编程工具 · 发布时间: 6年前

内容简介:搜了国内的文章 使用RESTful API: REST -- REpresentational State Transfer,英语的直译就是“表现层状态转移”可以参考下面理解:

搜了国内的文章 使用 Hapi 开发 RESTful API 的很少很少,一些 社区介绍的部分在新版本中已经不在适用,新版本中有很多变化

什么是 RESTful API

RESTful API: REST -- REpresentational State Transfer,英语的直译就是“表现层状态转移”

可以参考下面理解:

  • 理解本身的 REST 架构风格:http://www.infoq.com/cn/articles/understanding-restful-style/

  • 理解 RESTful 架构:http://www.ruanyifeng.com/blog/2011/09/restful.html

  • Restful API 设计指南:http://www.ruanyifeng.com/blog/2014/05/restful_api.html

Hapi

Hapi 是一个 Node.js 的 web 框架,即一个构建应用程序和服务丰富的框架。 目前 Hapi v17 仅支持 node v8.9.0 及以上版本

Hapi 特性

  • 认证和授权:内置的验证和授权方案
  • 缓存:提供客户端和服务端缓存, catbox
  • 路由: 内置路由
  • 验证:使用 Joi
  • Cookies:提供了配置选项处理 cookie
  • 日志:置的日志记录
  • 错误处理: boom
  • 进程监控:hapi 插件 good

使用 Hapi 的必要条件

  • 安装 Node.js v8.9.0 及以上
  • 安装 MongoDB
  • 熟悉数据库概念和 JavaScript 的应用知识

Hapi v17 新的变化

  • server.connection 方法移除,现在使用

    const server = new Hapi.Server({
        host: 'localhost',
        port: 3000
    })
    复制代码
  • 开启关闭服务方法 完全异步,没有回调

    try {
        await server.start()
    }
    catch (err) {
        console.log(err)
    }
      
    try {
        await server.stop()
    }
    catch (err) {
        console.log(err)
    }
    复制代码
  • reply() 回调方法移除,response.hold() 和 response.resume() 方法不在可用

    // 以前
    const handler = function (request, reply) {
      return reply('ok');
    };
    
    // 现在
    
    const handler = function (request, h) {
      return 'ok';
    };
    复制代码

    更多使用 h 的示例如下:

    const handler = (request, h) => {
      // return a string
      return 'ok'
    
      // return an object and hapi creates JSON out of it
      return { name: 'Authentication Library', library: true }
    
      // redirect to 404
      return h.redirect('/404')
    
      // return a view
      return h.view('index', { name: 'Authentication Library' })
    
      // use the "h" response toolkit to create a response
      return h
       .response(thisHTML)
        .type('text/html')
        .header('X-Custom', 'my-value')
        .code(201)
    }
    复制代码
  • 三个请求事件类型 request, request-interval, request-error 合并成一个单一的 request 事件

  • 触发的方法 像 server.on, request.on, response.on 被替换,使用server.events.on(), request.events.on(), response.events.on() 替代

  • 新的请求扩展:

    server.ext('onPreAuth', (request, h) => { … })
    server.ext('onCredentials', (request, h) => { … })
    server.ext('onPostAuth', (request, h) => { … }) ]
    复制代码
  • 在路由定义的时候 替换 config 为 options

    server.route({
      method: 'POST',
      path: '/',
      options: { … }
    })
    复制代码
  • 插件 目前使用

    exports.plugin = { register, name, version, multiple, dependencies, once, pkg }
    复制代码

更多变化详见 GitHub 完整的更新日志

正题:使用 Hapi 构建一个简单的 api

在这个示例中提供 CURD 操作

  • Get all demos - GET /demos
  • Get one demo - GET /demo/11
  • Create a demo - POST /demos
  • Edit a demo - PUT /demos/11
  • Delete a demo - DELETE /demos/11

A demo 有下面的属性:

  • name
  • age

1 创建项目目录 demo,最后结构如下:

demo
├── package.json
├── server.js 
├── .gitignore (可选)
└── src
    ├
    ├── controller
    |   └── test.js
    └─── models
        └── test.js
   
复制代码

2 编写 model

src/models/test.js
'use strict';

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const demoModel = new Schema({
  name: { type: String, required: true, index: { unique: true } },
  age: { type: Number, required: true }
});

module.exports = mongoose.model('Demo', demoModel, 'demos'); 
复制代码

编写 controllers

src/controllers/test.js

var Demo =  require('../models/test');

/**
 * List Demos
 */
exports.list = (req, h) => {
  return Demo.find({}).exec().then((demo) => {

    return { demos: demo };

  }).catch((err) => {

    return { err: err };

  });
}

/**
 * Get Demo by ID
 */
exports.get = (req, h) => {

  return Demo.findById(req.params.id).exec().then((demo) => {

    if(!demo) return { message: 'Demo not Found' };

    return { demos: demo };

  }).catch((err) => {

    return { err: err };

  });
}


/**
 * POST a Demo
 */
exports.create = (req, h) => {

  const demoData = {
    name: req.payload.name,
    age: req.payload.age
  };

  return Demo.create(demoData).then((demo) => {

     return { message: "Demo created successfully", demo: demo };

  }).catch((err) => {

    return { err: err };

  });
}

/**
 * PUT | Update Demo by ID
 */
exports.update = (req, h) => {

  return Demo.findById(req.params.id).exec().then((demo) => {

    if (!demo) return { err: 'Demo not found' };

    demo.name = req.payload.name;
    demo.breed = req.payload.breed;
    demo.age = req.payload.age;
    demo.image = req.payload.image;

    demo.save(dogData);

  }).then((data) => {

      return { message: "Demo data updated successfully" };

  }).catch((err) => {

      return { err: err };

  });
}

/**
 * Delete Demo by ID
 */
exports.remove = (req, h) => {

  return Demo.findById(req.params.id).exec(function (err, demo) {

    if (err) return { dberror: err };
    if (!demo) return { message: 'Demo not found' };

    demo.remove(function (err) {
      if (err) return { dberror: err };

      return { success: true };
    });
  });
}
复制代码

编写 server.js

'use strict';

const Hapi = require('hapi');
const mongoose = require('mongoose');
const DemoController =  require('./src/controllers/test');
const MongoDBUrl = 'mongodb://localhost:27017/demoapi';

const server = new Hapi.Server({
  port: 3000,
  host: 'localhost'
});

server.route({
  method: 'GET',
  path: '/demos',
  handler: DemoController.list
});

server.route({
  method: 'GET',
  path: '/demos/{id}',
  handler: DemoController.get
});
server.route({
  method: 'POST',
  path: '/demos',
  handler: DemoController.create
});

server.route({
  method: 'PUT',
  path: '/demos/{id}',
  handler: DemoController.update
});

server.route({
  method: 'DELETE',
  path: '/demos/{id}',
  handler: DemoController.remove
});

(async () => {
  try {  
    await server.start();
    // Once started, connect to Mongo through Mongoose
    mongoose.connect(MongoDBUrl, {}).then(() => { console.log(`Connected to Mongo server`) }, err => { console.log(err) });
    console.log(`Server running at: ${server.info.uri}`);
  }
  catch (err) {  
    console.log(err)
  }
})();
复制代码

测试 API

使用 postman 测试 http://localhost:3000/demos


以上所述就是小编给大家介绍的《使用 Hapi 开发 RESTful APIs》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

算法概论

算法概论

Sanjoy Dasgupta、Christos Papadimitriou、Umesh Vazirani / 钱枫 注、邹恒明 注 / 机械工业出版社 / 2009-1 / 55.00元

《算法概论(注释版)》源自加州大学伯克利分校和加州大学圣迭戈分校本科生的算法课讲义,以独特的视角展现了算法设计的精巧技术及魅力。在表达每一种技术时,强调每个算法背后的简洁数学思想,分析其时间和空间效率,运用与其他技术类比的方法来说明特征,并提供了大量实例。《算法概论(注释版)》以人类最古老的算法(算术运算)为起点,将各种算法中优美而有代表性的内容囊括书中,并以最前沿的理论(量子算法)结束,构成了较......一起来看看 《算法概论》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具