resource-router-middleware是一个提供restful API的Express中间件,由preact作者developit开发。 一个简单使用案例就是:
代码语言:javascript复制const resource = require('resource-router-middleware');
let users = [];
const huruji = {
id:12,
name: 'huruji',
age: 12,
sex: 'man'
};
const grey = {
id: 13,
name: 'grey',
age: 12,
sex: 'man'
};
users = [huruji, grey];
module.exports = resource({
mergeParams: true,
id: 'user',
load: function(res,id, callback) {
callback(null, huruji);
},
list: function(req, res) {
res.json(users);
},
create: function(req, res) {
var user = req.body;
users.push(user);
res.json(user);
},
read: function(req, res) {
res.json(req.user);
},
update: function(req, res) {
var id = req.params[this.id];
for(var i = users.length;i--;) {
if(users[i].id === id){
users[i] = req.body;
users[i].id = id;
return res.status(204).send('Accepted');
}
}
res.status(404).send('Not found');
},
delete: function(req, res) {
var id = req.params[this.id];
for(var i =users.length;i--;) {
if(users[i].id===id) {
users.splice(i,1);
return res.status(200);
}
}
res.status(404).send('Not found');
}
});
代码语言:javascript复制const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const userResource = require('./user');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/user',userResource);
app.listen(5000, function(err) {
if(err) {
return console.log(err);
}
console.log('server is listening port 5000')
});
可以学习的点主要是: 1、Express.Router可以提供一个对象参数
代码语言:javascript复制{
mergeParams: 是否保留父级路由的req.params,且父子的req.params冲突时,优先使用子级的
caseSensitive:路由的路径是否大小写敏感,默认为false
strict:是否启用严格模式,即/foo与/foo/区别对待
}
2、router.param的使用 3、取反运算,这个使用真的是相当巧妙 4、restful API的设计
代码语言:javascript复制var Router = require('express').Router;
var keyed = ['get', 'read', 'put', 'update', 'patch', 'modify', 'del', 'delete'],
map = { index:'get', list:'get', read:'get', create:'post', update:'put', modify:'patch' };
module.exports = function ResourceRouter(route) {
route.mergeParams = route.mergeParams ? true : false;
// Express.Router可以提供一个对象参数
/**
* @param {
* mergeParams: 是否保留父级路由的req.params,且父子的req.params冲突时,优先使用子级的
* caseSensitive:路由的路径是否大小写敏感,默认为false
* strict:是否启用严格模式,即/foo与/foo/区别对待
* }
*/
var router = Router({mergeParams: route.mergeParams}),
key, fn, url;
// 如果有中间件则装载中间价
if (route.middleware) router.use(route.middleware);
// router.param方法的回调函数的参数分别是req,res,next,params的值,params的key
// 使用这个我们可以为路由的params找到数据之后直接定义在req对象中,供后续处理
if (route.load) {
router.param(route.id, function(req, res, next, id) {
route.load(req, id, function(err, data) {
if (err) return res.status(404).send(err);
req[route.id] = data;
next();
});
});
}
for (key in route) {
// fn为对应的http method
fn = map[key] || key;
if (typeof router[fn]==='function') {
// ~取反位运算,这个很有意思,三目运算符只有在~keyed.indexOf(key)为0时运算'/',取反值与原值相加为-1的原则知原值keyed.indexOf(key)为-1,也就是说
// url = ~keyed.indexOf(key) ? ('/:' route.id) : '/'与url = (keyed.indexOf(key) > -1) ? ('/:' route.id) : '/';效果相同
// 意义在于如果用户是使用keyed数组里的元素来定义键的,则使用('/:' route.id)路由路径,否则使用'/'路由路径
url = ~keyed.indexOf(key) ? ('/:' route.id) : '/';
console.log(key);
console.log('url:' url)
router[fn](url, route[key]);
}
}
return router;
};
module.exports.keyed = keyed;