Restful接口规范
Rest,即Resources Representational State Transfer(资源表现层状态转化)。
·资源(Resources),网络上的一个实体,每种资源对应一个特定的URI(统一资源标识符)
·表现层(Representational),资源呈现的形式,比如:json
·状态转化(State Transfer),http协议里,四个表示操作方式的基本操作
Restful API设计规范
·使用http协议
·url中只有名词,如add、delete等动词不应出现
·不同操作由动词来区分:get,post(新建),put(更新,客户端需提供改变后的完整资源),patch(更新,客户端只需提供资源改变的属性),delete(删除)
·查询字符串中指定过滤条件
结果
· GET /collection:返回资源对象的列表(数组)
· GET /collection/id:返回单个资源对象
· POST /collection:返回新生成的资源对象
· PUT /collection/id:返回完整的资源对象
· PATCH /collection/id:返回更新后的完整资源对象
· DELETE /collection/id:返回一个空资源
restfulAPI.js
var express = require('express');
var app = express();
var path = require('path');
var bodyParser = require('body-parser');
app.set('view engine','ejs');
//path.resolve 取当前目录的绝对路径
app.set('views',path.resolve());
app.use(bodyParser.urlencoded({extended:true}));
/*app.use(bodyParser.raw({
type:'application/!*'
}));
app.use(bodyParser.text({
type:'text/!*'
}));*/
app.use(function(req,res,next){
console.log('body',req.body);
next();
});
app.use(function(err,req,res,next){
console.error(err);
next();
});
/*app.post('/raw',function(req,res){
res.send(req.body);
});*/
var users = [{id: 1, name: 'zfpx1',mny:100}, {id: 2, name: 'zfpx2',mny:100}];
/**
* 1. 获取所有的用户 curl -v -H 'accept:text/html' http://localhost:8080/users
* 2.
*/
//1.获取所有的用户
app.get('/users', function (req, res) {
//Accept:text/html,application/xml;q=0.9,image/webp,*/*;q=0.8。获取请求中accept权重最高的格式
var accept = req.headers['accept'];
var acceptType = accept.split(',').map(function (item) {
var values = item.split(';');
return {
type: values[0],//需要的文件类型
q: values[1] ? values[1].split('=')[1] : 1 //权重 默认是1
}
//用优先级进行排序,取排名最高那个
}).sort(function (a, b) {
return b.q - a.q;
})[0].type;
console.log(acceptType);
if(acceptType == 'text/plain'){
res.setHeader('Content-Type',acceptType);
res.send(users);
}else if(acceptType == 'text/html'){
//设置响应类型
res.setHeader('Content-Type',acceptType);
//渲染模板
res.render('users.ejs',{
users:users
});
}else{
res.send(users);
}
});
//返回某个用户信息 路径参数
//curl http://localhost:8080/users/1 使用函数过滤器过滤
app.get('/users/:id', function (req, res) {
var id = req.params.id;
var filteredUsers = users.filter(function(user){
return user.id == id;
});
res.send(filteredUsers.length>0?filteredUsers[0]:'此用户不存在');
});
//新增加用户
// -X 指定请求方法 --data 指定请求体的数据
//curl -X POST --data "name=zfpx3" http://localhost:8080/users 用body-parser获取请求体
app.post('/users', function (req, res) {
var addedUser = req.body;
if(addedUser){
//为增加的用户赋一个最大的ID
addedUser.id = users[users.length-1].id+1;
users.push(addedUser);
//当新增加一个资源的时候要返回新生成的资源完整对象
res.send(addedUser);
}else{
res.send({msg:'增加资源失败'});
}
});
//整体更新全部属性
// curl -X PUT --data "id=2&name=zfpx20" http://localhost:8080/users/2
app.put('/users/:id',function(req,res){
var putUser = req.body;
if(putUser){
for(var i=0;i<users.length;i++){
//判断当前用户和用户传进来要更新的用户ID是否一致
if(users[i].id == req.params.id){
users[i] = putUser;//把老的对象整体替换成新的对象
break;
}
}
res.send(putUser);
}else{
res.send({msg:'更新资源失败'});
}
});
//局部更新 请求体里只传要更新的字段
//curl -X PATCH --data "name=zfpx200" http://localhost:8080/users/2
app.patch('/users/:id',function(req,res){
var updatedFields = req.body;
if(updatedFields){
for(var i=0;i<users.length;i++){
//判断当前用户和用户传进来要更新的用户ID是否一致
if(users[i].id == req.params.id){
for(var attr in updatedFields){
//用新的值替换旧的值
if(updatedFields.hasOwnProperty(attr))
users[i][attr] = updatedFields[attr];
}
res.send(users[i]);
break;
}
}
}else{
res.send({msg:'更新资源失败'});
}
});
//删除
//curl -X DELETE http://localhost:8080/users/2 end不能接收对象参数,send可以接收
app.delete('/users/:id',function(req,res){
/*for(var i=0;i<users.length;i++){
if(users[i].id == req.params.id){
users.splice(i,1);
res.send({});
return;
}
}*/
users = users.filter(function(user){
return user.id != req.params.id;
});
res.send({msg:'删除失败'});
});
//以资源为中间 URL里不要包含动词 比如从id 1转账到 id 2,此时不是简单的restful形式,可以灵活变化 但定义url时避免使用动词
app.post('/transaction/:fromId/:toId',function(){
var money = req.body.money;
});
app.listen(8080);
tips:
/**
* map 替换所有的元素
* filter 过滤数组中的元素
* reduce 聚合
* reduceRight 从右往左聚合
* some 有一个满足就可以
* every 全部满足条件
* indexOf 第一个索引
* lastIndexOf 最后索引
*/
var nums = [1,2,3,1,6,4];
/**
* 会依次把数组中的每一元素传入next
* 每次返回值会传入下一次的current
* 最后得到一个最终值
* 获取元素最大值
*/
var s = nums.reduce(function(current,next){
return current>next?current:next;
},0);
console.log(s);