初识 HTTP:网络通讯模型、HTTP 模型 协议分析:发展历史、HTTP/1.1 报文分析 场景分析:静态资源、登录、视频播放、文件上传、跨域 应用:XHR、Fetch、Node 标准库、Axios、体验优化 其他协议扩展:WebSocket、QUIC
网络通信模型如下图所示,HTTP 协议位于模型顶层
HTTP( Hyper Text Transfer Protocol
) 模型如下图所示,是一个应用层(见上图)的协议,基于 TCP 协议,它有如下特点:
协议版本 | 简介 | 内容 |
---|---|---|
HTTP/0.9 | 单行协议 | 请求只有 GET,响应只有 HTML 文档 |
HTTP/1.0 | 构建可扩展性 | 增加了 Header,有了状态码,开始支持多种文档类型 |
HTTP/1.1 | 标准化协议 | 链接复用,缓存,内容协商 |
HTTP/2 | 更优异的表现 | 二进制协议,压缩 Header,服务器推送 |
HTTP/3 | 草案 | 未来的协议 |
GET
- 请求一个指定资源的表示形式,使用 GET 的请求应该只被用于获取数据POST
- 用于将实体提交到指定的资源,通常导致在服务器上的状态变化或副作用PUT
- 用请求有效载荷替换目标资源的所有当前表示DELETE
- 删除指定的资源HEAD
- 请求一个与 GET 请求的响应相同的响应,但没有响应体CONNECT
- 建立一个到由目标资源标识的服务器的隧道OPTIONS
- 用于描述目标资源的通信选项TRACE
- 沿着到目标资源的路径执行一个消息环回测试PATCH
- 用于对资源的部分修改方法分类:
大类划分:
1xx
- 指示信息,表示信息已接受,继续处理2xx
- 成功,表示请求已被成功接收 / 理解 / 接受3xx
- 重定向,要完成请求必须进行更进一步的操作4xx
- 客户端错误,请求有语法错误或请求无法实现5xx
- 服务器端错误,服务器未能实现合法的请求常见状态码:
200
OK - 客户端请求成功301
- 资源(网页等)被永久转移到其他 URL302
- 临时跳转401
Unauthorized - 请求未经授权404
Not Found - 请求资源不存在,可能是输入了错误的 URL500
- 服务器内部发生了不可预期的错误504
Gateway Timeout - 网关或者代理的服务器无法在规定的时间内获得想要的响应一种 API 设计风格;REST ( Representation State Transfer
) 有以下特点:
Cookie 是呈键值对出现的,具体键值信息如下:
更快、更稳定、更简单
HTTPS 建立在 HTTP 之上,在 HTTP 与 TCP/IP 中间插了一层 SSL/TLS(加密层),其特点如下:
静态资源解决方案:
缓存 + CDN ( Content Delivery Network
) + 文件名 hash
通过用户就近性和服务器负载的判断,CDN 确保内容以一种极为高效的方式为用户的请求提供服务
网站记住登录态主要靠两种方式来鉴权:
JSON web token
)视频播放的 Response 状态码一般为 206 Partial Content
,意为返回部分资源,资源的长度由 Range 和 Content-range 字段决定,类型由 Content-type 决定
视频直播协议有:
协议 | 描述 | 优点 |
---|---|---|
HLS | HTTP Live Streaming ,Apple 公司基于 HTTP 协议把一段视频流,分成一个个小的基于 HTTP 的文件来下载 | 跨平台 |
RTMP | Real Time Messaging Protocol ,Adobe 公司基于 TCP | 时延低 |
HTTP-FLV | 基于 HTTPhttp+flv,将音视频数据封装成 FLV 格式,然后通过 HTTP 协议传输给客户端 | 时延低 |
小文件直传,大文件分片上传,在服务器整合
readyState | 状态名 | 含义 |
---|---|---|
0 | UNSENT | 代理被创建,但尚未调用 open () 方法。 |
1 | OPENED | open () 方法已经被调用。 |
2 | HEADERS_ RECEIVED | send () 方法已经被调用,并且头部和状态已经可获得。 |
3 | LOADING | 下载中;responseText 属性已经包含部分数据。 |
4 | DONE | 下载操作已完成。 |
XHR示例 >folded
function get() {
var xhr = new XMLHttpRequest()
//open 后面有三个参数:
// 规定请求的类型、URL 以及是否异步处理请求。
//method:请求的类型;GET 或 POST
//url:文件在服务器上的位置
//async:true(异步)或 false(同步) 默认为 true
xhr.open('get', '/getUser?id=xxx')
// 发送请求到后端(服务器)
xhr.send()
// 当请求被发送到服务器时,我们需要执行一些基于响应的任务。
// 每当 readyState 改变时,就会触发 onreadystatechange 事件。
//readyState 属性存有 XMLHttpRequest 的状态信息。
// 在 xhr 的准备状态发生改变的时候,调用该方法
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText)
}
}
}
function post() {
var xhr = new XMLHttpRequest()
//post 请求方式,接口后面不能追加参数
xhr.open('post', '/login')
// 如果使用 post 请求方式, 而且是以 key=value 这种形式提交的
// 那么需要设置请求头的类型
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
xhr.send('username=admin&password=123456')
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText)
}
}
}
Fetch示例 >folded
function postData(url, data) {
// 默认的配置选项用 * 标出
return fetch(url, {
body: JSON.stringify(data), // 必须与 'Content-Type' 头匹配
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, same-origin, *omit
headers: {
'user-agent': 'Mozilla/4.0 MDN Example',
'content-type': 'application/json'
},
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, cors, *same-origin
redirect: 'follow', // manual, *follow, error
referrer: 'no-referrer', // *client, no-referrer
})
.then(response => response.json()) //.json () 方法将响应转换为 JSON
}
postData('http://example.com/answer', {answer: 42})
.then(data => console.log(data)) //data 为 `response.json ()` 返回的 JSON
.catch(error => console.error(error))
HTTP/HTTPS模块示例1 >folded
const https = require('https');
https.get('https://test.com?api_key=DEMO_KEY', (resp) => {
let data = '';
// A chunk of data has been received.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
console.log(JSON.parse(data).explanation);
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
HTTP/HTTPS模块示例2 >folded
import * as http from 'http';
import * as https from 'https';
import { URL } from 'url';
/**
* 判断 url 是否支持范围请求
* @param url
*/
function isSupportedRange(url: URL | string): Promise<boolean> {
return new Promise((resolve, reject) => {
if (typeof url === 'string') url = new URL(url);
const options: http.RequestOptions = {
method: 'HEAD',
headers: {
'Range': 'bytes=0-',
},
};
let req: http.ClientRequest; // 根据 URL 协议,判断使用 http 还是 https 模块发送请求
function callback(response: http.IncomingMessage) {
// console.log(response.statusCode);
// console.log(response.headers);
// 假如在响应中存在 Accept-Ranges 首部(并且它的值不为 “none”),那么表示该服务器支持范围请求。
if (response.statusCode === 206 || (response.headers["accept-ranges"] && response.headers["accept-ranges"] !== 'none')) resolve(true);
resolve(false);
}
switch (url.protocol) {
case 'http:': {
req = http.request(url, options, callback);
break;
}
case 'https:': {
req = https.request(url, options, callback);
break;
}
default: return void resolve(false);
}
req.addListener('error', (err: Error) => {
reject(err); // 请求失败
});
req.end(); // refresh request stream
});
}
Axios示例 >folded
// 全局配置
axios.defaults.baseURL = "https://api.example.com";
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 发送请求
axios({
method: 'get',
url: 'http://test.com',
responseType: 'stream'
}).then(function (response) {
response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'))
});
Quick UDP Internet Connection
) - HTTP3 的草案之一