请问你对http了解吗?javascript
一个网页的加载过程是什么样的?php
浏览器会因页面上的css/js/image等静态资源会屡次发起链接请求,能够把这个过程分红两部分css
整个过程大体通过了 DNS解析
--> 负载均衡
--> web服务器
--> 浏览器渲染
html
可是在浏览器解析页面内容的时候,会发现页面引用了其余未加载的image、css文件、js文件等静态内容,所以开始了第二部分的静态资源请求。java
经常使用的请求方法有哪些web
经常使用的Http 请求头字段有哪些?算法
Accept:浏览器端能够接受的MIME类型vim
Accept-Charset 设置接受的字符编码跨域
Accept-Encoding 设置接受的编码格式浏览器
Accept-Language 设置接受的语言
Authorization 设置HTTP身份验证的凭证
Cache-Control 设置请求响应链上全部的缓存机制必须遵照的指令
Content-Length 设置请求体的字节长度
Content-MD5 设置基于MD5算法对请求体内容进行Base64二进制编码
Content-Type 设置请求体的MIME类型(适用POST和PUT请求)
Cookie 设置服务器使用Set-Cookie发送的http cookie
Date 设置消息发送的日期和时间
Expect 标识客户端须要的特殊浏览器行为
Host 设置服务器域名和TCP端口号,若是使用的是服务请求标准端口号,端口号能够省略
If-Match 设置客户端的ETag,当时客户端ETag和服务器生成的ETag一致才执行,适用于更新自从上次更新以后没有改变的资源
If-Modified-Since 设置更新时间,从更新时间到服务端接受请求这段时间内若是资源没有改变,容许服务端返回304 Not Modified
If-None-Match 设置客户端ETag,若是和服务端接受请求生成的ETage相同,容许服务端返回304 Not Modified
If-Range 设置客户端ETag,若是和服务端接受请求生成的ETage相同,返回缺失的实体部分;不然返回整个新的实体
Forwarded 披露客户端经过http代理链接web服务的源信息
If-Unmodified-Since 设置更新时间,只有从更新时间到服务端接受请求这段时间内实体没有改变,服务端才会发送响
Max-Forwards 限制代理或网关转发消息的次数
Origin 标识跨域资源请求(请求服务端设置Access-Control-Allow-Origin响应字段)
Pragma 设置特殊实现字段,可能会对请求响应链有多种影响
Proxy-Authorization 为链接代理受权认证信息
Range 请求部分实体,设置请求实体的字节数范围,具体能够参见HTTP/1.1中的Byte serving
Referer 设置前一个页面的地址,而且前一个页面中的链接指向当前请求,意思就是若是当前请求是在A页面中发送的,那么referer就是A页面的url地址
Upgrade 请求服务端升级协议
User-Agent 用户代理的字符串值
Via 通知服务器代理请求
Warning 实体可能会发生的问题的通用警告
经常使用的Http 响应头字段有哪些?
http的响应状态码
1xx Informational(信息性状态码)
2XX Success(成功状态码)
3xx Redirection(重定向)
4XX Client Error(客户端错误状态码)
5xx Server Error(服务器错误状态码)
url模块
url.parse(urlStr,[parseQueryString]);
复制代码
http的应用
客户端须要发送一个Range:bytes=0-5 服务器 Sccept-Range:bytes Content-Range: bytes 0-5/705
// 在命令行模式范围请求
curl -v --header "Range: bytes=0-5" http://www.baidu.com/img/baidu_jgylogo3.gif
复制代码
server.js
let http = require('http')
let path = require('path')
let p = path.resolve(__dirname, '1.txt');
let fs = require('mz/fs')
const port = 3000;
async function listener(req, res) {
let range = req.headers['range'];
if (range) {
let [, start, end] = range.match(/(\d*)-(\d*)/);
let statObj = await fs.stat(p);
let total = statObj.size;
start = start ? Number(start) : 0;
end = end ? Number(end) : total - 1;
res.statusCode = 206;
res.setHeader('Accept-Ranges', 'bytes');
res.setHeader('Content-Range', `bytes ${start}-${end}/${total}`);
fs.createReadStream(p, {start, end, encoding: 'utf8'}).pipe(res);
} else {
// 读取文件 并响应给客户端
fs.createReadStream(p).pipe(res)
}
}
let server = http.createServer(listener);
server.listen(port, () => {
console.log(`server start at ${port}`)
})
复制代码
client.js
// 定时发起请求,并把请求到的结果写入download.txt,实现断点续传的功能
let http = require('http');
let fs = require('fs');
let ws = fs.createWriteStream(__dirname + '/download.txt')
let start = 0;
const unit = 4;
let config = {
host: 'localhost',
port: 3000
}
function download() {
config.headers = {
'Range': `bytes=${start}-${start + unit}`
}
start += 5;
let client = http.request(config, res => {
let total = res.headers['content-range'].split('/')[1];
let buffers = [];
res.on('data', data => {
buffers.push(data);
});
res.on('end', () => {
let result = Buffer.concat(buffers);
ws.write(result)
setTimeout(() => {
console.log('start <= total', start, total)
if (start <= total) {
download();
}
}, 1000);
})
})
client.end(); // 必须调用end 不然不会发送内容
}
download();
复制代码
server.js
/** * 实现原理 * host: 表示资源的地址,通常是服务器地址,默认端口号80 * refer/referered: 使用资源的端地址 * * 在服务器端配置资源可访问的白名单 WHITELIST, * 当host与refer/referered的域名不相同,而且refer/referered的地址在WHITELIST中时, * 表示能够该端能够访问服务器中的资源,不然不可访问. * */
let http = require('http');
let fs = require('fs');
let url = require('url');
let path = require('path');
let static = path.resolve(__dirname);
const WHITELIST = ['linda_1.cn'];
let server = http.createServer(async (req, res) => {
let { pathname } = url.parse(req.url);
let p = path.join(static, pathname);
let flag = true;
try{
fs.accessSync(p)
} catch(e) {
flag = false;
}
if (flag) {
let refer = req.headers['referer'] || req.headers['referered'];
if (refer) {
let hostname = req.headers['host'].split(':')[0];
let refername = url.parse(refer).hostname;
if (refername != hostname && !WHITELIST.includes(refername)) {
fs.createReadStream(path.join(static, '/images/girl.png')).pipe(res);
} else {
fs.createReadStream(p).pipe(res);
}
} else {
fs.createReadStream(p).pipe(res);
}
} else{
res.statusCode = 404;
res.end();
}
})
server.listen(3000, () => {
console.log('server is starting on 3000...')
})
复制代码
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<img src="http://localhost:3000/images/boy.png"/>
</body>
</html>
复制代码
mac下配置域名与主机名映射
vim /etc/hosts
127.0.0.1 linda_1.cn
127.0.0.1 linda_2.cn
复制代码
配置好后,可在浏览器中输入不一样的域名,来测试图片的显示状况。