請問你對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
複製代碼
配置好後,可在瀏覽器中輸入不一樣的域名,來測試圖片的顯示狀況。