node-http实现服务(静态+动态)
http服务端有两种功能:
1. 提供静态服务 html /css 等
2. 提供动态数据服务
1. 浏览器请求示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<!--服务器端不识别相对路径'../',默认/1.css-->
<link href="../1.css" rel="stylesheet" />
</head>
<body>
<script>
// 在5000端口下启动
const xhr = new XMLHttpRequest();
//PUT非简单请求;会发送OPTIONS请求
xhr.open('PUT', 'http://localhost:3000/userList', true);
document.cookie = "token=20190993339"
xhr.withCredentials = true; //跨域携带cookie
xhr.responseType = 'application/json';// 非简单请求
xhr.onreadystatechange = function() {
if(xhr.status === 200 && xhr.readyState === 4) {
console.log(JSON.parse(xhr.response));
}
}
xhr.send();
</script>
</body>
</html>
2. 回调函数实现服务
let http = require('http');
let url = require('url');
let fs = require('fs');
let path = require('path');
// 上面都是核心内置模块
let mime = require('mime'); //第三方模块
// 回调函数实现服务
let server = http.createServer(function(req, res) {
const { pathname } = url.parse(req.url);
const method = req.method.toLowerCase();
//处理动态数据
switch(pathname) {
case '/userList':
if(method === 'get') {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({name: 'lyra'}));
return;
}
}
// 判断路径对应的是文件还是文件夹
let absolutePath = path.join(__dirname, pathname);
fs.stat(absolutePath, function(err, statObj) {
if(err) {
res.statusCode = 404;
res.end('Not Found');
return;// 结束
}
if (statObj.isFile()) {// 是文件则直接读取返回对应路径下文件
const rs = fs.createReadStream(absolutePath);
// 设置返回的响应头Content-Type
res.setHeader('Content-Type', mime.getType(absolutePath)+";charset=utf-8");
rs.pipe(res); //包含 res.end(...)逻辑
} else {// 是文件夹;默认查找index.html
const indexPath = path.join(absolutePath, 'index.html');
fs.access(indexPath, function(err) {
if(err) {
res.statusCode = 404;
res.end('Not Found');
return;// 结束
}
res.setHeader('Content-Type', 'text/html;charset=utf-8');// utf-8中间要有间隔符,IE兼容
fs.createReadStream(indexPath).pipe(res);
})
}
})
});
server.listen(3000);
3. aysnc...await封装
使用第三方的mz/fs模块,该模块下文件处理Promise化。
let http = require('http');
let url = require('url');
let fs = require('mz/fs');
let path = require('path');
// 上面都是核心内置模块
let mime = require('mime'); //第三方模块
class Server {
constructor() {
this.handleRequest = this.handleRequest.bind(this);
}
async handleRequest(req, res) {
const { pathname } = url.parse(req.url, true);
//处理动态数据
this.handleDataRequest(pathname,req, res);
const absPath = path.join(__dirname, pathname);
try {
// 处理静态文件
let statObj = await fs.stat(absPath);
if (statObj.isFile()) {
this.sendFile(res, absPath);
} else {
const realpath = path.join(absPath, 'index.html');
await fs.access(realpath);
this.sendFile(res, realpath);
}
} catch(e) {
console.log(e);
this.sendError(res);
}
}
handleDataRequest(dataPath,req, res) {
const method = req.method.toLowerCase();
/*************************跨域的通用解决方案***********************************/
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5000');
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET,OPTIONS,HEAD');
res.setHeader('Access-Control-Allow-Headers', "Content-Type");
res.setHeader('Access-Control-Max-Age', 10000); //s
// options请求不做处理
if(method === 'options') {
res.end();// 可访问
}
/****************************************************************************/
//处理动态数据
switch(dataPath) {
case '/userList':
if(method === 'get') {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({name: 'lyra'}));
}
if(method === 'put') {
}
}
}
sendFile(res, realpath) {
res.setHeader('Content-Type', mime.getType(realpath)+";charset=utf-8")
fs.createReadStream(realpath).pipe(res);
}
sendError(res) {
res.statusCode = 404;
res.end('Not Found');
return;
}
start(port) {
let server = http.createServer(this.handleRequest);
server.listen(port);
}
}
let server = new Server();
server.start(3000);

浙公网安备 33010602011771号