Accept-LanguageAccept-Language通常用于实现多种语言:Accept-Language:Accept-Language:*//多种类型,以质量值加权fr-CH,fr;q=0.9,en;q=0.8,de;q=0.7,*;q=0.5;q=(q-factorweighting)表示优先顺序,以相对质量值表示,也称为作为权重。简单实现:consthttp=require("http")constlanguages={zh:"Hello",en:"hello",jp:"こんニちは",}constserver=http.createServer((req,res)=>{res.setHeader("Content-Type","text/plain;charset=utf-8")letlang=req.headers["accept-language"]//zh-CN,zh;q=0.9,en;q=0.8if(!lang)returnres.end("")lang=lang.split(",").filter((t)=>t.includes(";")).map((t)=>{let[name,q]=t.split(";")return{name,q:q.slice(2)*1,}}).sort((a,b)=>a.q>b.q)对于(leti=0;iconsole.log(`Servingon:\r\nhttp://localhost:3000`))Accept-RangesHTTP请求范围HTTP协议范围请求允许服务器仅向客户端发送消息的HTTP部分。传输大型媒体文件或与恢复文件下载结合使用时,范围请求很有用。范围请求响应状态:206PartialContent服务请求成功416RequestedRangeNotSatisfiable请求范围越界(范围值超出资源大小)200OK不支持范围请求,返回整个资源。分段下载时,首先要判断Range请求头:Range:bytes=start-endRange:bytes=10-:第10个字节和最后一个字节的数据Range:bytes=40-100:第40个之间的数据字节和第100个字节。注意这里的意思是[start,end],其中包括了请求头的起始字节和结束字节,所以下一个请求应该是上一个请求的[end+1,nextEnd]Content-Range响应头//server响应数据的前(0-10)个字节,资源的总大小为(3103)个字节。Content-Range:bytes0-10/3103;//服务器响应了11个字节的数据(0-10)Content-Length:11;代码实现服务器根据范围下载constpath=require("path")consthttp=require("http")constfs=require("fs")constDOWNLOAD_FILE=path.resolve(__dirname,"./server_download.txt")constTOTAL=fs.statSync(DOWNLOAD_FILE).size;http.createServer((req,res)=>{res.setHeader("Content-Type","text/plain;charset=utf-8")//curlhttp://www.example.com-i-H"Range:bytes=0-50"constrange=req.headers["range"]//直接返回没有范围的文件if(!range)returnfs.createReadStream(DOWNLOAD_FILE).pipe(res)//截取范围值,还有其他种类Let[,start,end]=range.match(/(\d*)-(\d*)/)start=start?start*1:0end=end?end*1:TOTAL//范围请求成功状态代码206部分内容res.statusCode=206//设置响应头res.setHeader("Content-Range",`bytes${start}-${end}/${TOTAL}`)//返回范围数据fs.createReadStream(DOWNLOAD_FILE,{start,end}).pipe(res)}).listen(3000,()=>console.log(`Servingon3000`))客户端下载constpath=require("path")consthttp=require("http")constfs=require("fs")constDOWNLOAD_FILE=path.resolve(__dirname,"./client_download.txt")constws=fs.createWriteStream(DOWNLOAD_FILE)letstart=0letmode="start"//下载模式"start"|“暂停”下载()函数下载(){constdownloadConfig={主机名:“localhost”,端口:3000,编码:“utf-8”,标题:{范围:`bytes=${start}-${start+100}`,},}constrequest=(res)=>{lettotal=res.标头[“内容范围”]。split("/")[1]*1res.on("data",(chunk)=>{ws.write(chunk)if(start<=total){start+=101//打印下载进度console.clear();console.log(`下载进度:${Math.min(parseInt((start/total)*100),100)}%\r\n按p键并回车暂停`)setTimeout(()=>{//模式为开始模式,继续下载模式==="开始"?download():console.log("暂停下载,按任意键进入下载")},1000)}else{ws.end()}})res.on("end",()=>{if(total>start)return;console.log("下载完成")process.exit(1)})}http.get(downloadConfig,request)}process.stdin.on("data",(chunk)=>{if(chunk.toString().includes("p")){//键盘p暂停下载mode="pause"}else{mode="start"download()}})User-AgentUser-Agent头包含一个特征字符串,用于允许网络协议的对等端识别发起请求的用户代理软件的应用程序类型、操作系统、软件开发商和版本号。User-Agent判断是否移动端,重定向到新地址:require("http").createServer((req,res)=>{constua=req.headers["user-agent"];constisMobile=/(iPhone|iPad|iPod|iOS|Android)/i.test(ua);constredirectUrl=isMobile?"https://m.58.com/gz":"https://gz.58.com";res.statusCode=302;res.setHeader("Location",redirectUrl)res.end()}).listen(3000,()=>console.log(`服务于:\r\nhttp://localhost:3000`))RefererReferer请求头包含如果指定了当前请求页面的源页面地址,则表示当前页面是通过源页面中的链接进入的。服务器端一般使用Referer请求头来标识访问源,可用于统计分析、日志记录、缓存优化等。ExampleReferer:https://developer.mozilla.org/en-US/docs/Web/JavaScript在以下两种情况下,不会发送Referer:源页面使用的协议是“文件”或“数据”代表一个本地文件”URI当前请求页面使用非安全协议,而源页面使用安全协议(HTTPS)来确定盗链示例:consturl=require("url");consthttp=require("http");http.createServer((req,res)=>{letreferer=req.headers["referer"];if(referer){letrefererHost=url.parse(referer).hostlethost=req.headers["host"];if(refererHost!==host){//盗链}}}).listen(3000,()=>console.log(`服务于:\r\nhttp://localhost:3000`))Content-EncodingContent-Encoding是一个实体消息头,用于压缩特定媒体类型的数据,当这个头出现时,它的值表示对消息体进行了什么样的内容编码转换,这个消息头用于告知客户端如何解码得到Content-Type中标记的媒体类型的内容。一般建议尽量压缩数据,所以才会出现这个消息头。但是,对于某些类型的文件,例如jpeg图像文件,它们已经被压缩了。有时再次施加额外的压缩无助于减少负载量,但可能会增加负载量。使用gzip方式进行压缩。服务端配置Content-Encoding字段:Content-Encoding:gzip客户端使用Accept-Encoding字段描述接收方式:Accept-Encoding:gzip,deflate代码实现constfs=require("fs");constzlib=require("zlib")consthttp=require("http");http.createServer((req,res)=>{letencoding=req.headers["accept-encoding"]if(!encoding)返回fs.createWriteStream("./test.html").pipe(res);if(/\bgzip\b/.test(encoding)){res.setHeader("Content-Encoding","gzip");返回fs.createWriteStream("./test.html").pipe(zlib.createGzip()).pipe(res)}if(/\bdeflate\b/.test(encoding)){res.setHeader("内容编码","bdeflate")returnfs.createWriteStream("./test.html").pipe(zlib.createDeflate()).pipe(res)}}).listen(3000,()=>console.log(`Servingon:\r\nhttp://localhost:3000`))注意事项根据HTTP规范,HTTP消息头的字段名不区分大小写。3.2.标题字段每个标题字段由一个不区分大小写的字段名称和后跟一个冒号(“:”),可选的前导空格、字段值和可选的尾随空格。