# Http (opens new window)

# 001. HTTP 报文结构是怎样的?

http

起始行 + 头部 + 空行 + 实体

  • 请求报文
    • 起始行 GET /home HTTP/1.1
    • 头部 请求头
    • 空行 区分头部和实体
    • 实体 请求体
  • 响应报文
    • 起始行/状态行 HTTP/1.1 200 OK
    • 响应头
    • 空行 区分头部和实体
    • 实体 响应体

# 002. 如何理解 HTTP 的请求方法?

  • GET: 通常用来获取资源
  • HEAD: 获取资源的元信息
  • POST: 提交数据,即上传数据
  • PUT: 修改数据
  • DELETE: 删除资源(几乎用不到)
  • CONNECT: 建立连接隧道,用于代理服务器
  • OPTIONS: 列出可对资源实行的请求方法,用来跨域请求
  • TRACE: 追踪请求-响应的传输路径

GET 和 POST 有什么区别?

  • 缓存
  • 编码
  • 参数
  • 幂等性
  • TCP

# 003: 如何理解 URI?

URI 包含了 URN 和 URL

# URI 的结构

scheme user:passwd@ host:port path query fragment

# URI 编码

URI 引入了编码机制,将所有非 ASCII 码字符和界定符转为十六进制字节值,然后在前面加个%

# 004: 如何理解 HTTP 状态码?

五类

  • 1xx: 表示目前是协议处理的中间状态,还需要后续操作。
  • 2xx: 表示成功状态。
  • 3xx: 重定向状态,资源位置发生变动,需要重新请求。
  • 4xx: 请求报文有误。
  • 5xx: 服务器端发生错误

# 1XX

101 Switching Protocols。在 HTTP 升级为 WebSocket 的时候,如果服务器同意变更,就会发送状态码 101

# 2XX

200 OK 是见得最多的成功状态码。通常在响应体中放有数据。 204 No Content 含义与 200 相同,但响应头后没有 body 数据。 206 Partial Content 顾名思义,表示部分内容,它的使用场景为 HTTP 分块下载和断点续传,当然也会带上相应的响应头字段 Content-Range。

# 3XX

301 Moved Permanently 即永久重定向,对应着 302 Found,即临时重定向。

比如你的网站从 HTTP 升级到了 HTTPS 了,以前的站点再也不用了,应当返回 301,这个时候浏览器默认会做缓存优化,在第二次访问的时候自动访问重定向的那个地址。

而如果只是暂时不可用,那么直接返回 302 即可,和 301 不同的是,浏览器并不会做缓存优化。

304 Not Modified: 当协商缓存命中时会返回这个状态码。详见浏览器缓存

# 4XX

400 Bad Request: 开发者经常看到一头雾水,只是笼统地提示了一下错误,并不知道哪里出错了。

403 Forbidden: 这实际上并不是请求报文出错,而是服务器禁止访问,原因有很多,比如法律禁止、信息敏感。

404 Not Found: 资源未找到,表示没在服务器上找到相应的资源。

405 Method Not Allowed: 请求方法不被服务器端允许。

406 Not Acceptable: 资源无法满足客户端的条件。

408 Request Timeout: 服务器等待了太长时间。

409 Conflict: 多个请求发生了冲突。

413 Request Entity Too Large: 请求体的数据过大。

414 Request-URI Too Long: 请求行里的 URI 太大。

429 Too Many Request: 客户端发送的请求过多。

431 Request Header Fields Too Large 请求头的字段内容太大。

# 5XX

500 Internal Server Error: 仅仅告诉你服务器出错了,出了啥错咱也不知道。

501 Not Implemented: 表示客户端请求的功能还不支持。

502 Bad Gateway: 服务器自身是正常的,但访问的时候出错了,啥错误咱也不知道。

503 Service Unavailable: 表示服务器当前很忙,暂时无法响应服务。

# 005: 简要概括一下 HTTP 的特点?HTTP 有哪些缺点

# HTTP 特点

  • 灵活可扩展
  • 可靠传输
  • 请求-应答
  • 无状态

# 缺点

# 无状态

# 明文传输

# 队头阻塞

当 http 开启长连接时,共用一个 TCP 连接,同一时刻只能处理一个请求,那么当前请求耗时过长的情况下,其它的请求只能处于阻塞状态,也就是著名的队头阻塞问题

# 006: 对 Accept 系列字段了解多少?

对于 Accept 系列字段的介绍分为四个部分: 数据格式、压缩方式、支持语言和字符集。

总结

# 007: 对于定长和不定长的数据,HTTP 是怎么传输的?

# 定长包体

Content-Length

# 不定长包体

Transfer-Encoding: chunked

  • Content-Length 字段会被忽略
  • 基于长连接持续推送动态内容
chunk长度(16进制的数)
第一个chunk的内容
chunk长度(16进制的数)
第二个chunk的内容
......
0

# 008: HTTP 如何处理大文件的传输?

采取了范围请求的解决方案

Accept-Ranges: none

# Range 字段拆解

请求单段数据和请求多段数据,响应头是不一样的

# 单端数据

# 多段数据

# 009: HTTP 中如何处理表单数据的提交?

  • Content-Type:application/x-www-form-urlencoded

  • Content-Type:multipart/form-data

# x-www-form-urlencoded

  • 其中的数据会被编码成以&分隔的键值对
  • 字符以 URL 编码方式编码。

# multipart/form-data

  • 请求头中的 Content-Type 字段会包含 boundary,且 boundary 的值有浏览器默认指定。例: Content-Type: multipart/form-data;boundary=----WebkitFormBoundaryRRJKeWfHPGrS4LKe。
  • 数据会分为多个部分,每两个部分之间通过分隔符来分隔,每部分表述均有 HTTP 头部描述子包体,如 Content-Type,在最后的分隔符会加上--表示结束。

form-data、x-www-form-urlencoded 的区别 (opens new window)

multipart/form-data:既可以上传文件等二进制数据,也可以上传表单键值对,只是最后会转化为一条信息; x-www-form-urlencoded:只能上传键值对,并且键值对都是间隔分开的。

# 总结

值得一提的是,multipart/form-data 格式最大的特点在于:每一个表单元素都是独立的资源表述。另外,你可能在写业务的过程中,并没有注意到其中还有 boundary 的存在,如果你打开抓包工具,确实可以看到不同的表单元素被拆分开了,之所以在平时感觉不到,是以为浏览器和 HTTP 给你封装了这一系列操作。

而且,在实际的场景中,对于图片等文件的上传,基本采用 multipart/form-data 而不用 application/x-www-form-urlencoded,因为没有必要做 URL 编码,带来巨大耗时的同时也占用了更多的空间。

# 010: HTTP1.1 如何解决 HTTP 的队头阻塞问题?

# 什么是 HTTP 队头阻塞?

请求任务被放在一个任务队列中串行执行,一旦队首的请求处理太慢,就会阻塞后面请求的处理

# 并发连接

对于一个域名允许分配多个长连接,那么相当于增加了任务队列

Chrome 中是 6 个。

# 域名分片

多域名或多二级域名

// 请求头
Cookie: a=xxx;b=xxx
// 响应头
Set-Cookie: a=xxx
set-Cookie: b=xxx

# 生存周期

Expires 即过期时间 Max-Age 用的是一段时间间隔,单位是秒,从浏览器收到报文开始计算。

# 作用域

Domain 和 path, 给 Cookie 绑定了域名和路径,在发送请求之前,发现域名或者路径和这两个属性不匹配,那么就不会带上 Cookie。值得注意的是,对于路径来说,/表示域名下的任意路径都允许使用 Cookie。

# 安全相关

Secure 说明只能通过 HTTPS 传输 cookie HttpOnly 只能通过 HTTP 协议传输,不能通过 JS 访问,这也是预防 XSS 攻击的重要手段。 SameSite = Strict、Lax 和 None

Strict 浏览器完全禁止第三方请求携带 Cookie Lax get 方法提交表单况或者 a 标签发送 get 请求的情况下可以携带 Cookie None 请求会自动携带上 Cookie

  • 容量缺陷。Cookie 的体积上限只有 4KB,只能用来存储少量的信息
  • 性能缺陷 有时候并不需要的时候带上了 cookie 带上以后有损耗
  • 安全缺陷
    • 纯文本的形式在浏览器和服务器中传递,很容易被非法用户截获并篡改
    • 在 HttpOnly 为 false 的情况下,Cookie 信息能直接通过 JS 脚本来读取。

# 012: 如何理解 HTTP 代理?

请求先到代理服务器 由代理服务器发起实际请求

  • 负载均衡

  • 保障安全

  • 缓存代理

# 相关头部字段

# Via

Via 中代理的顺序即为在 HTTP 传输中报文传达的顺序

# X-Forwarded-For

字面意思就是为谁转发, 它记录的是请求方的 IP 地址(注意,和 Via 区分开,X-Forwarded-For 记录的是请求方这一个 IP)。

# X-Real-IP

# 013: 如何理解 HTTP 缓存及缓存代理?

# 代理缓存

# 源服务器的缓存控制

# private 和 public

private 或者 public 表示是否允许代理服务器缓存,前者禁止,后者为允许

# proxy-revalidate

must-revalidate 的意思是客户端缓存过期就去源服务器获取,而 proxy-revalidate 则表示代理服务器的缓存过期后到源服务器获取。

# s-maxage

限定了缓存在代理服务器中可以存放多久

例子

Cache-Control: public, max-age=1000, s-maxage=2000

我这个响应是允许代理服务器缓存的,客户端缓存过期了到代理中拿,并且在客户端的缓存时间为 1000 秒,在代理服务器中的缓存时间为 2000 s。

# 客户端的缓存控制

max-stale 缓存进行宽容 min-fresh 缓存进行限制 only-if-cached 只会接受代理缓存

# 014: 什么是跨域?浏览器如何拦截响应?如何解决?

同源政策(scheme(协议)、host(主机)和 port(端口)都相同则为同源)

# 跨域的方案

# CORS

# 简单请求
  • 请求方法为 GET、POST 或者 HEAD
  • 请求头的取值范围: Accept、Accept-Language、Content-Language Content-Type
  • Content-Type(只限于三个值 application/x-www-form-urlencoded、multipart/form-data、text/plain)

浏览器自动在请求头当中,添加一个 Origin 字段

Access-Control-Allow-Origin

服务器用来决定浏览器是否拦截这个响应,这是必需的字段。与此同时,其它一些可选的功能性的字段,用来描述如果不会拦截,这些字段将会发挥各自的作用。

Access-Control-Allow-Credentials

是否允许发送 cookie withCredentials 客户端也需要设置

Access-Control-Expose-Headers

允许客户端可以拿到 除包括 Cache-Control、Content-Language、Content-Type、Expires、Last-Modified 和 Pragma 外的响应头

# 非简单请求

预检请求

响应字段

# JSONP

script 标签不一样,它可以通过 src 填上目标地址从而发出 GET 请求,实现跨域请求并拿到响应

# Nginx
server {
  listen  80;
  server_name  client.com;
  location /api {
    proxy_pass server.com;
  }
}

# 015: TLS1.2 握手的过程是怎样的?

HTTPS = HTTP + SSL/TLS

# 浏览器缓存

# 强缓存

HTTP/1.0

Expires 过期时间

缺点:本地时间可修改

HTTP/1.1

Cache-Control

public:资源客户端和服务器都可以缓存。

privite:资源只有客户端可以缓存。

no-cache:客户端缓存资源,但是是否缓存需要经过协商缓存来验证。

no-store:不使用缓存。

max-age:缓存保质期。

状态码:200

# 协商缓存

HTTP/1.0

Last-Modified 响应头/ If-Modified-Since 请求头

HTTP/1.1

Etag 响应头/ If-None-Match 请求头

# 三次握手

三次握手,四次挥手”你真的懂吗 (opens new window)

# 四次挥手

关于 TCP 三次握手和四次挥手,满分回答在此 (opens new window)

参考文章:

(建议精读)HTTP 灵魂之问,巩固你的 HTTP 知识体系 (opens new window)

六张图从 HTTP/0.9 进化到 HTTP3.0 (opens new window)

https://juejin.cn/post/6908327746473033741 (opens new window)

队头阻塞 (opens new window)