http模块实现API路由
// /getUser /getOneUser /removeUser /addUser /updateUser
//统一收拢为 /user,通过method区分
//method:GET获取 POST增加 PUT更新 DELETE删除 OPTIONS(试探性请求)
// /getUser /user get
// /getOneUser /user?id=1 get
// /removeUser /user?id=1 delete
// /addUser /user post {username:xxx,password:xxx}
// /updateUser /user
// RESTFUL 接口风格,不是标准,通过http请求method动词区分:
//查询某一个用户返回查询到的一项{username:xxx}
//查询所有,返回的是数组类型
//添加返回添加的那一项
//修改,返回修改的那一项
//删除 返回控对象
/*
req.headers 请求头,都是小写的
{ host: 'localhost:3002',
connection: 'keep-alive',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36',
accept: '*/*',
referer: 'http://localhost:3002/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9'
}
req.url 请求的路径,需要用url.parse处理成对象
req.method 请求的方式,都是大写的,GET获取 POST增加 PUT更新 DELETE删除 OPTIONS(试探性请求)
post接收参数,是读取req可读流的方式接收,req是可读流,on('data') on('end')
*/
//通过动态匹配,实现用户的增删改查api
let http = require('http');
let port = 3002;
let path = require('path');
let url = require('url')
let mime = require('mime');
let users = [{username:'小明',password:'1231',id:1},{username:'小u',password:'1231',id:2}]
http.createServer((req,res)=>{
let {pathname,query} = url.parse(req.url,true);
if(pathname =='/user'){
let id = query.id;
switch(req.method){
case "GET":
res.setHeader('Content-Type',"application/javascript;charset=utf-8")
if(!id){//获取所有
res.end(JSON.stringify(users))
}else{//获取单个
let user = users.find(item=>item.id==id)
if(typeof user !='undefined'){
res.end(JSON.stringify(user))
}else{
res.end(JSON.stringify({}))
}
}
break;
case "POST"://添加用户
res.setHeader("Content-Type","application/json;charset=utf-8");
//post接收参数,req是可读流,用事件接收。
let str = "";
req.on('data',chunk=>{
str += chunk;//chunk是buffer,字符串拼接,会自动调用toString(),这种可能出现乱码,目前不用考虑,因为每次默认读取的都是64k,不会出现断码。
})
req.on('end',()=>{
let user = JSON.parse(str)
user.id = users.length ? users[users.length-1].id + 1 : 1;
users.push(user)
res.end(JSON.stringify(user))
})
break;
case "DELETE"://删除某个
if(id){
users = users.filter((item)=>item.id!=id);
res.end(JSON.stringify({}))
}
break;
}
return ;
}
})
复制代码
跨域处理
//jsonp就是利用script 的src 不受同源策略影响,动态向页面插入script标签,实现请求。
//注意:需要和后端协商好callback的key是啥。
前端页面js:
function setData(data){
console.log(data);//获取到数据
}
let script = document.createElement('script');
script.src = "http://localhost:3002/jsonp?cb=setData"
document.body.appendChild(script);
后端api:
let http = require('http');
let port = 3002;
let fs = require('fs');
let path = require('path')
let url = require('url')
let mime = require('mime');
http.createServer((req, res) => {
let {pathname, query} = url.parse(req.url, true);
if (pathname == '/jsonp') {
let school = JSON.stringify({name:'zfpx'});
// res.end(`var a = ${school}`) //在前端的全局作用域就可以获取到 变量a
res.end(`${query.cb}(${school})`)//返回一个全局方法执行
return ;
}
})
}).listen(port, () => {
console.log(`${port} 服务器启动`)
});
复制代码
let http = require('http');
let port = 3002;
let fs = require('fs');
let path = require('path')
let url = require('url')
let mime = require('mime');
let users = [{username: '乔石', password: 'admin', id: 1}, {username: 'zfpx', password: 'admin', id: 2}];
http.createServer((req, res) => {
let {pathname, query} = url.parse(req.url, true);
res.setHeader('Access-Control-Allow-Origin',"*");
res.setHeader('Access-Control-Allow-Methods','GET,POST,PUT,DELETE,OPTIONS');
if(req.method =='OPTIONS'){
res.end('ok')
return;
}
if(pathname == '/clock'){
res.end('2017.11.19');
return;
}
fs.stat(`.${pathname}`, (err, stats) => {
if (err) {
res.statusCode = 404;
res.end(`${pathname} is not found`);
return;
}
if (stats.isFile()) {
mime.getType(pathname)
res.setHeader('Content-Type', mime.getType(pathname) + ';charset=utf-8');
fs.createReadStream(`.${pathname}`).pipe(res);
}
if (stats.isDirectory()) {
res.setHeader('Content-Type', 'text/html;charset=utf-8');
let p = path.join(`.${pathname}`, './index.html');
fs.createReadStream(p).pipe(res)
}
})
}).listen(port, () => {
console.log(`${port} 服务器启动`)
});
复制代码