本人博客文章地址:點(diǎn)擊進(jìn)入
一、 HTTP
1. http.server
- 創(chuàng)建服務(wù)器
import http from 'http';
const server = http.createServer((req, res) => {
res.end();
}).listen(8780);
- 設(shè)置超時(shí)時(shí)間(默認(rèn)是120s)
server.setTimeout(60 * 1000, () => {
console.log('超時(shí)回調(diào)');
});
- 服務(wù)器錯(cuò)誤處理(實(shí)現(xiàn)端口被占用時(shí)自動(dòng)更換端口)
import http from 'http';
let port = 80;
const createServer = () => {
const server = http.createServer((req, res) => {
res.end("hello");
}).listen(port);
console.log("Server running on port:" + port);
server.on('error', (e) => {
if (e.code === 'EADDRINUSE') {
console.log(`端口:${e.port} 被占用`);
port++;
createServer();
}
});
};
createServer();
- 關(guān)閉服務(wù)器
server.close(); // 服務(wù)器停止接受新的連接
server.on('close', () => {
// 服務(wù)器最后一個(gè)連接關(guān)閉時(shí)調(diào)用
});
2. http.IncomingMessage
- 獲取請求頭
import http from 'http';
const server = http.createServer((req, res) => {
console.log(req.headers);// 返回的是header中屬性組成的對象
res.end();
}).listen(8080);
- 獲取請求方法
import http from 'http';
const server = http.createServer((req, res) => {
if (req.method == 'GET') {}
if (req.method == 'POST') {}
res.end();
}).listen(8080);
- 獲取請求url與GET、POST參數(shù)
import http from 'http';
import URL from 'url';
import querystring from 'querystring';
const server = http.createServer((req, res) => {
const url = URL.parse(req.url, true);
console.log(url); // 獲取URL
if (req.method == "GET") {
console.log(url.query);// 獲取GET參數(shù)
}
if (req.method == "POST") {
let body = "";
req.on('data', function (chunk) {
body += chunk;
});
req.on('end', function () {
const postQuery = querystring.parse(decodeURI(body));// 獲取POST參數(shù)
});
}
res.end();
}).listen(8080);
3. http.ServerResponse
- 寫入響應(yīng)頭
import http from 'http';
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
res.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);
res.end();
}).listen(8780);
- 寫入響應(yīng)體
import http from 'http';
const server = http.createServer((req, res) => {
res.write('{name:"liuhuihao"}');
res.end();
}).listen(8780);
二、 HTTPS
image.png
1. 創(chuàng)建公鑰、私鑰及證書
- 創(chuàng)建私鑰
openssl genrsa -out privatekey.pem 1024
- 創(chuàng)建證書簽名請求
openssl req -new -key privatekey.pem -out certrequest.csr
- 獲取證書,線上證書需要經(jīng)過證書授證中心簽名的文件;下面只創(chuàng)建一個(gè)學(xué)習(xí)使用證書
openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem
- 創(chuàng)建pfx文件
openssl pkcs12 -export -in certificate.pem -inkey privatekey.pem -out certificate.pfx
2. http.server
- 創(chuàng)建服務(wù)器
import https from 'https';
import fs from 'fs';
const options = {
key: fs.readFileSync('dist/privatekey.pem'), // 私鑰
cert: fs.readFileSync('dist/certificate.pem') // 公鑰
};
https.createServer(options, (req, res) => {
res.end();
}).listen(8000);
三、 HTTP2
1. 優(yōu)勢
(1)多路復(fù)用 - 雪碧圖、多域名CDN、接口合并
這是一個(gè)HTTP2的演示地址,分別用HTTP/1.1和HTTP/2請求379張圖片,對比出HTTP/2在速度上的優(yōu)勢
image.png
打開控制臺查看網(wǎng)絡(luò)請求,我們可以發(fā)現(xiàn)HTTP/2和HTTP/1.1的明顯區(qū)別
HTTP/1.1:
image.png
HTTP/2:
image.png
由上圖可以看出,多路復(fù)用允許同時(shí)通過單一的 HTTP/2 連接發(fā)起多重的請求-響應(yīng)消息;而HTTP/1.1協(xié)議中,瀏覽器客戶端在同一時(shí)間,針對同一域名下的請求有一定數(shù)量限制。超過限制數(shù)目的請求會(huì)被阻塞
image.png
首部壓縮
- http/1.x 的 header 由于 cookie 和 user agent很容易膨脹,而且每次都要重復(fù)發(fā)送。http/2使用 encoder 來減少需要傳輸?shù)?header 大小,通訊雙方各自 cache一份 header fields 表,既避免了重復(fù) header 的傳輸,又減小了需要傳輸?shù)拇笮 8咝У膲嚎s算法可以很大的壓縮 header,減少發(fā)送包的數(shù)量從而降低延遲
服務(wù)端推送
- 服務(wù)端推送是一種在客戶端請求之前發(fā)送數(shù)據(jù)的機(jī)制。在 HTTP/2 中,服務(wù)器可以對客戶端的一個(gè)請求發(fā)送多個(gè)響應(yīng)。舉個(gè)例子,如果一個(gè)請求請求的是index.html,服務(wù)器很可能會(huì)同時(shí)響應(yīng)index.html、logo.jpg 以及 css 和 js 文件,因?yàn)樗揽蛻舳藭?huì)用到這些東西。這相當(dāng)于在一個(gè) HTML 文檔內(nèi)集合了所有的資源。
image.png
2. nodeJS http/2 實(shí)踐
- 搭建http/2 服務(wù)器
import http2 from 'http2';
import fs from 'fs';
const options = {
key: fs.readFileSync('dist/privatekey.pem'), // 私鑰
cert: fs.readFileSync('dist/certificate.pem') // 公鑰
};
http2.createSecureServer(options, (req, res) => {
res.end();
}).listen(8078);
- 驗(yàn)證 http/2 多路復(fù)用
import http2 from 'http2';
import fs from 'fs';
import URL from 'url';
import mime from 'mime';
const {HTTP2_HEADER_PATH} = http2.constants;// :path
const options = {
key: fs.readFileSync('dist/privatekey.pem'), // 私鑰
cert: fs.readFileSync('dist/certificate.pem') // 公鑰
};
http2.createSecureServer(options, (req, res) => {
const url = URL.parse(req.url, true);
if (url.pathname != "/" && url.pathname != "/favicon.ico") {
const indexObj = getFdAndHeader(url.pathname);
res.stream.respondWithFD(indexObj.fd, indexObj.headers);
} else {
const indexObj = getFdAndHeader('more.html');
res.stream.respondWithFD(indexObj.fd, indexObj.headers);
}
}).listen(8078);
const getFdAndHeader = (fileName) => {
const filePath = "public/" + fileName;
const fd = fs.openSync(filePath, 'r');
const stat = fs.fstatSync(fd);
const headers = {
'content-length': stat.size,
'last-modified': stat.mtime.toUTCString(),
'content-type': mime.lookup(filePath)
};
return {fd, headers};
};
效果:
image.png
- 實(shí)現(xiàn) http/2 服務(wù)端推送
import http2 from 'http2';
import fs from 'fs';
import mime from 'mime';
const {HTTP2_HEADER_PATH} = http2.constants;// :path
const options = {
key: fs.readFileSync('dist/privatekey.pem'), // 私鑰
cert: fs.readFileSync('dist/certificate.pem') // 公鑰
};
http2.createSecureServer(options, (req, res) => {
const indexObj = getFdAndHeader('index.html');
const jsObj = getFdAndHeader('someJs.js');
const cssObj = getFdAndHeader('someCss.css');
push(res.stream, jsObj);
push(res.stream, cssObj);
res.stream.respondWithFD(indexObj.fd, indexObj.headers);
}).listen(8078);
function push(stream, obj) {
stream.pushStream({[HTTP2_HEADER_PATH]: obj.urlPath}, (pushStream) => {
pushStream.respondWithFD(obj.fd, obj.headers)
})
}
const getFdAndHeader = (fileName) => {
const filePath = "public/" + fileName;
const fd = fs.openSync(filePath, 'r');
const stat = fs.fstatSync(fd);
const urlPath = "/" + fileName;
const headers = {
'content-length': stat.size,
'last-modified': stat.mtime.toUTCString(),
'content-type': mime.lookup(filePath)
};
return {fd, headers, urlPath};
};
推送效果:
image.png
無推送效果:
image.png
作者博客地址:https://liuhuihao.com
作者gitHub:https://github.com/geminate