静态服务器
let http = require('http');
let url = require('url'); // pathname,query
let path = require('path');
let fs = require('fs');
let util = require('util');
let stat = util.promisify(fs.stat);
let mime = require('mime');
let server = http.createServer(async function (req,res) {
let { pathname } = url.parse(req.url);
let realPath = path.join(__dirname, pathname); // 拼接真实文件的路径
try{
let statObj = await stat(realPath); // 判断文件是否存在
if (statObj.isFile()){ // 是文件 返回文件
res.setHeader('Content-Type', mime.getType(realPath)+';charset=utf-8');
fs.createReadStream(realPath).pipe(res);
}else{
let url = path.join(realPath,'index.html'); // 目录找html
res.setHeader('Content-Type','text/html;charset=utf-8');
fs.createReadStream(url).pipe(res);
}
}catch(e){ // 不存在返回404
res.statusCode = 404;
res.end('Not found');
}
});
server.listen(3000,function () {
console.log(`server start 3000`);
})
多语言(req.headers['accept-language'];)
let http = require('http');
let url = require('url');
let path = require('path');
let fs = require('fs');
let obj = {
'zh-CN':{
data:'你好,世界'
},
en:{
data:'hello,world'
},
ja:{
data:'こんにちは、世界'
}
}
let defaultLanguage = 'en';
let server = http.createServer(async function (req,res) {
// 多语言 (语言包)
// 1) 根据路径不同返回不同的语言
// 2) 可以前端配置多语言
// 3) 服务端配置多语言
// Accept-Language: zh-CN;q=0.3,zh;q=0.9,en;q=1 请求头
// [zh-CN, zh;q=0.9, en;q=0.8]
//
let lan = req.headers['accept-language'];
res.setHeader('Content-Type', 'text/plain;charset=utf8');
if(lan){
let lans = lan.split(',').map(l=>{ // 按照,分割
let [name, q = 1] = l.split(';'); // 并且把数据转化成[{name:'zh-cn',q:1},{name:'zh';q:0.9}]格式
return {
name,
q: q===1?1:Number(q.split('=')[1])
}
}).sort((a,b)=>b.q - a.q); // 根据权重排序
for(let i = 0; i<lans.length;i++){ // 找到对应的语言返回
let lanName = lans[i].name;
console.log(lanName)
if(obj[lanName]){
return res.end(obj[lanName].data);
}
}
res.end(obj[defaultLanguage].data); // 找不到默认语言
}else{
res.end(obj[defaultLanguage].data);
}
});
server.listen(3000,function () {
console.log(`server start 3000`);
})
缓存
强制缓存
- cache-control (设置的时间秒)
- expires (设置绝对时间)
// 304 走浏览器的缓存
// 缓存的类型 有两种 强制缓存 + 对比缓存
let http = require('http');
let url = require('url'); // pathname,query
let path = require('path');
let fs = require('fs');
let util = require('util');
let stat = util.promisify(fs.stat);
let mime = require('mime');
// 页面 可能内部引用了一个css 我希望把css缓存
http.createServer(async function (req,res) {
console.log(req.url);
// 告诉浏览器十秒内别再找我了 (index.html) 不会的
res.setHeader('Cache-Control','max-age=10'); // http 1.1
// 废弃了
res.setHeader('Exipres', new Date(Date.now() + 10 * 1000).toLocaleString()); // 绝对时间
let { pathname } = url.parse(req.url);
let realPath = path.join(__dirname, pathname); // 拼接真实文件的路径
try {
let statObj = await stat(realPath); // 判断文件是否存在
if (statObj.isFile()) { // 是文件 返回文件
res.setHeader('Content-Type', mime.getType(realPath) + ';charset=utf-8');
fs.createReadStream(realPath).pipe(res);
} else {
let url = path.join(realPath, 'index.html'); // 目录找html
res.setHeader('Content-Type', 'text/html;charset=utf-8');
fs.createReadStream(url).pipe(res);
}
} catch (e) { // 不存在返回404
res.statusCode = 404;
res.end('Not found');
}
}).listen(4000);
协商缓存
- Last-modified(res) 和 If-Modified-Since(req)(通过判断文件的修改时间来判断是否缓存)
http.createServer(async function (req,res) {
// 告诉浏览器十秒内别再找我了 (index.html) 不会的
res.setHeader('Cache-Control','no-cache'); // http 1.1
// 废弃了
res.setHeader('Exipres', new Date(Date.now() + 10 * 1000).toLocaleString()); // 绝对时间
// 第一次访问的时候 要给浏览器加一个头 last-modified
// 第二请求的时候 会自动带一个头 if-modified-since
// 如果当前带过来的头和文件当前的状态有出入 说明文件被更改了(时间变了但是内容没更改 会出现再次访问文件的问题)
let { pathname } = url.parse(req.url);
let realPath = path.join(__dirname, pathname); // 拼接真实文件的路径
try {
let statObj = await stat(realPath); // 判断文件是否存在
if (statObj.isFile()) { // 是文件 返回文件'
let prev = req.headers['if-modified-since'];
let current = statObj.ctime.toGMTString();
if (prev === current){ // 当前文件没有更改 去找缓存把
res.statusCode = 304;
res.end();
}else{
res.setHeader('Last-Modified', statObj.ctime.toGMTString());
res.setHeader('Content-Type', mime.getType(realPath) + ';charset=utf-8');
fs.createReadStream(realPath).pipe(res);
}
} else {
let url = path.join(realPath, 'index.html'); // 目录找html
res.setHeader('Content-Type', 'text/html;charset=utf-8');
fs.createReadStream(url).pipe(res);
}
} catch (e) { // 不存在返回404
res.statusCode = 404;
res.end('Not found');
}
}).listen(4000);
- Etag(res) 和 If-none-match(req)(将文件md5加密,判断每次文件内容是否变化来进行缓存)
try {
let statObj = await stat(realPath); // 判断文件是否存在
if (statObj.isFile()) { // 是文件 返回文件'
let content = await readFile(realPath);
let sign = crypto.createHash('md5').update(content).digest('base64');
let ifNoneMatch = req.headers['if-none-match'];
if(ifNoneMatch === sign){
res.statusCode = 304;
res.end();
}else{
res.setHeader('Etag', sign);
res.setHeader('Content-Type', mime.getType(realPath) + ';charset=utf-8');
res.end(content);
}
} else {
let url = path.join(realPath, 'index.html'); // 目录找html
res.setHeader('Content-Type', 'text/html;charset=utf-8');
fs.createReadStream(url).pipe(res);
}
} catch (e) { // 不存在返回404
res.statusCode = 404;
res.end('Not found');
}
Cryto 加密
// crypto 加密 md5( 摘要算法 )
// MD5的特点 不可逆
// 不同的内容加密长度是一样的
// 如果内容不相同 那么摘要的结果肯定也是不相同的
let crypto = require('crypto');
// let r = crypto.createHash('md5').update('123456777777').digest('base64');
// console.log(r);
// r = crypto.createHash('md5').update('4QrcOUm6Wau+VuBX8g+IPg==').digest('base64');
// console.log(r);
// 加盐算法
// 弄一个密码 根据我的密码进行加密 加密cookie
let fs = require('fs');
let s = fs.readFileSync('./rsa_private_key.pem','utf8');
let r = crypto.createHmac('sha1', s).update('123456').digest('base64');
// 非对称 对称
console.log(r);