第四章 入参和验证入参
之前我们写了一个接口,把所有的书本数据都提供给了api,现在我们再写一个接口,通过丰富之前的代码,用于搜索书本。
搜索功能,我们知道,大约是在输入框中填入某些内容,然后接口返回与内容相关的数据,那么这里就涉及到一个内容,就是通过api请求传入服务端的内容,我们称之为入参。入参在进入服务端之前,我们需要验证它们的格式是否符合我们设定的要求,不符合我们要求的入参规则的请求我们就可以直接返回报错,不需要处理它们了。
那么验证入参是否合格我们就需要用到一个新的包:Joi
npm install joi --save
tips: Joi 文档
src/router.js
const Router = require('koa-router');
const router = new Router();
// 这是一个用于验证入参是否正确的包
const Joi = require('joi');
// 创建一个函数用于验证入参是否正确
const { validatorInterceptor } = require('./lib');
const { BookController } = require('./controllers/book-controller');
router.get('/', ctx => ctx.body = 'Web API Running Successfully.');
router.get('/api/books', BookController.get);
// 用于验证入参
const bookSearchSchema = {
query: Joi.object().keys({
// 这里要求入参可以有名为search_text的参数,且必须是字符串
text: Joi.string(),
}),
};
// 第一个参数依旧是路由地址,第二个参数我们验证入参是否合格的函数放在这里,第三个参数是controller执行层
router.get('/api/book/search', validatorInterceptor(bookSearchSchema), BookController.get);
module.exports = router;
上面我们创建了一个用于验证入参是否合格的函数,由于这个函数为公用方法,那么我们创建一个lib文件夹,并把它写在index.js里面
src/index.js
// 这是一个在node中非常常用且好用的包,用于处理各种数据(如json,数组等)重组,使用npm install lodash安装
const _ = require('lodash');
// 这个函数同样要使用到Joi,所以依然引入它
const Joi = require('joi');
exports.validatorInterceptor = async (schemas, options) => {
// 这里我们给validatorInterceptor返回一个函数
return async (ctx, next) => {
try {
// 将传入的schemas的key全部取出,并循环它们
for (const key of _.keys(schemas)) {
// 使用validate方法验证每一个key是否符合要求
await Joi.validate(_.get(ctx.request, key), _.get(schemas, key), options || {});
}
}
// 如果不符合要求,则直接报400错误
catch (err) {
ctx.throw(400, `validation failed on: ${err.message}`);
}
// 如果没有问题,则下一步
await next();
};
}
tips: lodash 文档
刚才可以发现,搜索api我们使用的还是get方法,那么现在我们就来改装一下这个方法
src/controllers/book-controller.js
const { BookService } = require('../services/book-service');
class BookController {
static async get(ctx) {
// 我们将入参从ctx.request.query中取出
const searchText = ctx.request.query.text;
const bookService = new BookService();
// 传入service方法中使用
const res = await bookService.get(searchText);
ctx.body = res;
}
}
module.exports = { BookController };
接着修改service方法
src/services/book-services.js
const bookModel = require('../schemas/book-schema');
class BookService {
// 这个函数的入参为刚才controller层传入的搜索内容
async get(searchText) {
// 我们设置一个默认的内容,就是当接口什么搜索内容都没有传入的时候,我们默认返回所有书本给接口
const query = {};
// 当有搜索内容传入的时候
if (searchText) {
// 我们希望数据库无论是书本名称还是作者,有相关的文字内容就可以将其搜索出来
// 这里的$or和后面的内容写法都是mongo搜索时的写法,有不了解的同学可以查看mongo相关文档学习
query.$or = [{name: new RegExp(searchText)}, {author: new RegExp(searchText)}];
}
// 和之前一样,查询数据,然后将结果返回
const res = await bookModel.find(query);
return res;
}
}
module.exports = { BookService };
接下来,启动程序,开始验证我们的代码编写成果
node src/server.js
打开浏览器
首先无任何参数,我们希望返回所有的书本数据:http://localhost:3000/api/book/search
图片当参数错误时:http://localhost:3000/api/book/search?aaa=111
图片搜索书本名称,三体:http://localhost:3000/api/book/search?text=三体
图片搜索作者名称,村上春树:http://localhost:3000/api/book/search?text=村上春树
图片搜索不完全的书本名称,挪威:http://localhost:3000/api/book/search?text=挪威
图片全部成功,我们的搜索接口,就是这么简单 __
本文已完成电子书《Node零基础入门到服务端程序》电子书(含教程内项目代码)/ 10元,购买链接:https://mianbaoduo.com/o/bread/mbd-Z5WZk5o=
ps:前九章(本书共计十三章)内容会在这里陆续更新。
网友评论