在编写接口时,往往会用到POST请求,但凡是带参数的请求,都少不了参数的合法性验证,比如是否包含参数字段,或者参数是否在合法范围内。
这些验证是常见的,且可复用的,所以今天编写一个中间件来验证POST请求的参数。
在验证POST字段之前,我们首先得获取POST请求的请求体对象(即键值对们),才能进行合法性判断。所以我们引入body-parser包,获取POST请求。
使用node的包管理工具npm可以快速安装body-parser
npm install body-parser
如果报错找不到body-parser,那么请在要运行的js文件的目录下,使用link命令:
npm link body-parser
在处理请求的中间件注册之前,注册body-parser即可
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false })); // 解析POST
app.use(bodyParser.json()); // 变成json对象
然后我们可以在req.body[键名称]
中获取对应的值,以完成对post请求的解析。下面是body-parser的示例代码,我们接收并回显POST请求的键值对们:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var middleware = function(req, res, next) {
var ret = "";
for(key in req.body) {
ret += key + " - " + req.body[key] + "\n";
}
res.end(ret);
};
app.post('/', middleware);
app.listen(8888);
console.log("开始运行于 localhost:8888");
上文介绍了如何获取POST参数,接下来我们对参数进行验证,验证主要从三个方面入手:
假设我们知道参数的
那么我们可以编写以下的函数,实现过滤功能:
function(req, res, next) {
var param = "name";
var legalList = ["zhang3", "lee4", "wang5"];
var defaultValue = null; // 为null则必填
// 如果未填参数
if(req.body[param] === undefined) {
// 参数如果必填
if(defaultValue == null) {
res.end(JSON.stringify({
"state": 777,
"message": "参数错误 必填参数 " + param + " 缺失"
}));
return;
}
// 选填则帮忙填上
req.body[param] = defaultValue;
}
// 如果有参数范围 检验参数是否合法
if(legalList && !legalList.includes(req.body[param])) {
res.end(JSON.stringify({
"state": 888,
"message": "参数错误 参数 " + param + " 值非法"
}));
return;
}
next(); // 校验正确则next
}
但是这么做不方便代码的复用,因为除了参数名,合法范围,默认值
以外,其他的代码都是相同的,那么我们可以定制一个函数,传入参数名,合法范围,默认值
,返回定制的过滤函数。
利用JavaScript闭包的特性,定制的中间件函数可以访问传入的参数名,合法范围,默认值
,从而返回定制的中间件函数即可。
function checker(param, legalList, defaultValue) {
return function(req, res, next) {
// 如果未填参数
if(req.body[param] === undefined) {
// 参数如果必填
if(defaultValue == null) {
res.end(JSON.stringify({
"state": 777,
"message": "参数错误 必填参数 " + param + " 缺失"
}));
return;
}
// 选填则帮忙填上
req.body[param] = defaultValue;
}
// 如果有参数范围 检验参数是否合法
if(legalList && !legalList.includes(req.body[param])) {
res.end(JSON.stringify({
"state": 888,
"message": "参数错误 参数 " + param + " 值非法"
}));
return;
}
next(); // 校验正确则next
}
}
使用刚刚编写的定制函数,我们需要传入三个变量:
其中param为必填,legalList和defaultVaule如果为null,表示参数范围不限 / 参数必填
假设必填参数为name,合法范围为["zhang3", "lee4", "wang5"]
,因为是必填,所以没有默认值,我们defaultValue填null即可。
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
function checker() {
checker函数上文有 就不重复粘贴了
}
// 参数验证
app.post('/', checker("name", ["zhang3", "lee4", "wang5"], null));
app.listen(8888);
postman测试:我们没填name字段,就报错了
我们填一个非法的值试一下,可以看到只要不再范围内,就报错。
选填参数我们传入默认值不为null即可,默认值为zhang3
,这里我们还是:选填参数为name,合法范围为["zhang3", "lee4", "wang5"]
。然后我们返回name参数的值,看看默认值是不是我们预想的那样
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
function checker() {
checker函数上文有 就不重复粘贴了
}
// 参数默认值验证
app.post('/', checker("name", ["zhang3", "lee4", "wang5"], "zhang3"));
app.post('/', function(req, res, next) {
res.end(req.body["name"]);
});
app.listen(8888);
中间件避免了代码的重复使用,因为同样是过滤POST请求,只需要很少的改动,就能适应不同的参数,那么我们传入少量的变量就可以定制一个中间件了。
下面总结一下定制函数的形参如果为null,那么他们表示的意义:
形参名 | 为 null 时的解释 |
---|---|
legalList | 参数没有范围限制(比如用户名参数) |
defaultValue | 参数为必填 |