理解HTTP

HTTP:Hypertext Transfer Protocol(超文本传输协议),HTTP为网页而生,它规定了客户端(浏览器)和服务器(Web Server)之间交流的格式,简单来说是让客户端和服务器之间互相明白对方在说什么的一种协议。

由于HTTP作用在应用程序之间,所以它处在OSI模型中的最顶端:应用层,客户端(浏览器)生成HTTP报文以后委托操作系统的协议栈生成TCP报文(传输层通常是走TCP,也有走UDP的)和IP报文,然后经过因特网流向目标服务器。

HTTP的请求和响应

HTTP示意图

浏览器说的“我要”就是HTTP方法的其中一种:GET,HTTP支持的方法有:

详见:MDN HTTP请求方法

上图简单描述了HTTP的工作方式,那么真正的HTTP报文是怎么样的呢?

GET请求示例:

GET https://music.163.com/discover HTTP/1.1
Host: music.163.com
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (省略)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: https://music.163.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: _iuqxldmzr_=32; _ntes_nnid=a9e7683015916d6ce3f8a8ccf20867c0,1545667456438; (省略)

POST请求示例:

POST https://ac.dun.163yun.com/v2/b HTTP/1.1
Host: ac.dun.163yun.com
Connection: keep-alive
Content-Length: 2835
Origin: https://music.163.com
User-Agent: Mozilla/5.0 (省略)
Content-type: application/x-www-form-urlencoded
Accept: */*
Referer: https://music.163.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8

d=6U8x4NJ5usAG&v=2e562ea2(省略)

可以看到请求的格式由下面几个部分组成: HTTP请求 GET和POST的区别是GET没有消息体。

响应示例:

HTTP/1.1 200 OK
Server: nginx
Date: Fri, 18 Jan 2019 06:28:04 GMT
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: PHP/7.1.3
Access-Control-Allow-Origin: *

119
{"code":1,"msg":"ok"}
0

响应的格式: HTTP响应 相对于请求的差异是在响应的状态行。

HTTP头字段

头字段类型HTTP 版本含义
1.01.1
通用头:适用于请求和响应消息的头字段
Date表示请求和响应生成的日期
Pragma表示数据是否允许缓存的通信选项
Cache-Control控制缓存的相关信息
Connection设置发送响应之后 TCP 连接是否继续保持的通信选项
Transfer-Encoding表示消息主体的编码格式
Via记录途中经过的代理和网关
请求头:用于表示请求消息的附加信息的头字段
Authorization身份认证数据
From请求发送者的邮件地址
If-Modified-Since如果希望仅当数据在某个日期之后有更新时才执行请求,可以在这个字段指定希望的日期。一般来说,这个功能的用途在于判断客户端缓存的数据是否已经过期,如果已经过期则获取新的数据
Referer当通过点击超级链接进入下一个页面时,在这里会记录下上一个页面的 URI
User-Agent客户端软件的名称和版本号等相关信息
Accept客户端可支持的数据类型(Content-Type),以 MIME 类型来表示
Accept-Charset客户端可支持的字符集
Accept-Encoding客户端可支持的编码格式(Content-Encoding),一般来说表示数据的压缩格式
Accept-Language客户端可支持的语言,汉语为 zh,英语为 en
Host接收请求的服务器 IP 地址和端口号
If-Match参见 Etag
If-None-Match参见 Etag
If-Unmodified-Since当指定日期之后数据未更新时执行请求
Range当需要只获取部分数据而不是全部数据时,可通过这个字段指定要获取的数据范围
响应头:用于表示响应消息的附加信息的头字段
Location表示信息的准确位置。当请求的 URI 为相对路径时,这个字段用来返回绝对路径
Server服务器程序的名称和版本号等相关信息
WWW-Authenticate当请求的信息存在访问控制时,返回身份认证用的数据
Accept-Ranges当希望仅请求部分数据(使用 Range 来指定范围)时,服务器会告知客户端是否支持这一功能
实体头:用于表示实体(消息体)的附加信息的头字段
Allow表示指定的 URI 支持的方法
Content-Encoding当消息体经过压缩等编码处理时,表示其编码格式
Content-Length表示消息体的长度
Content-Type表示消息体的数据类型,以 MIME 规格定义的数据类型来表示。常见的有:text/html, text/css, text/csv, text/xml, application/x-www-form-urlencoded(普通表单内容), multipart/form-data(含有文件上传的表单内容), application/json
Expires表示消息体的有效期
Last-Modified数据的最后更新日期
Content-Language表示消息体的语言。汉语为 zh,英语为 en
Content-Location表示消息体在服务器上的位置(URI)
Content-Range当仅请求部分数据时,表示消息体包含的数据范围
Etag在更新操作中,有时候需要基于上一次请求的响应数据来发送下一次请求。在这种情况下,这个字段可以用来提供上次响应与下次请求之间的关联信息。上次响应中,服务器会通过 Etag 向客户端发送一个唯一标识,在下次请求中客户端可以通过 If- Match、If-None-Match、If-Range 字段将这个标识告知服务器,这样服务器就知道该请求和上次的响应是相关的。这个字段的功能和 Cookie 是相同的,但 Cookie 是网景(Netscape)公司自行开发的规格,而 Etag 是将其进行标准化后的规格

详见:MDN HTTP Headers

HTTP状态码

状态码 说明
1xx 告知请求的处理进度和情况
2xx 成功
3xx 需要进一步处理
4xx 客户端错误
5xx 服务器错误

常见的HTTP状态码:

200 Ok
201 Created,资源创建成功,一般在POST,PUT,PATCH成功后返回
204 No Content,不需要返回内容,一般在DELETE成功后返回
301 Moved Permanently,永久重定向
302 Found,临时重定向
304 Not Modified,缓存可以继续使用
400 Bad Request,客户端请求错误
401 Unauthorized,未通过认证
403 Forbidden,禁止访问
404 Not Found,未找到
418 I’m a teapot 我是一个茶壶,不能给你泡咖啡
500 Internet Server Error,服务器错误
502 Bad Gateway,网关没有得到响应
503 Service Unavailable,服务不可用
504 Gateway Timeout,网关获取响应超时

详见:MDN HTTP Status

HTTP版本之间的区别

HTTP 1.0版本对于每个请求都会重新创建TCP连接,而1.1版本支持长连接(底层的TCP连接可以通过头部的Connection控制)。

HTTP 和 HTTPS

HTTP是明文传输,有可能半路拦截被窃听。HTTP报文是直接通过TCP协议传输的,而HTTPS就是HTTP报文先经过SSL(Secure Socket Layer)协议加密以后,再通过TCP协议传输。

加密算法

对称加密,也就是共享秘钥加密方式,就是双方都持有一把一样的秘钥,加解密都通过这把秘钥。

对称加密要把共享秘钥发给对方,那么怎么能够保证秘钥安全地发送给对方呢?非对称加密解决了这个问题,传输数据的双方分别持有两把秘钥,一把是公钥,一把是私钥,发送数据之前,先用对方的公钥进行加密再发送,对方再通过自己的私钥解密,常用的非对称加密算法是RSA。

SSL采用非对称加密算法,HTTPS采用混合加密方式,即先通过SSL的非对称加密方式来安全地传输用来对称加密的共享密钥,然后再通过对称加密来收发数据。

HTTP错误码常见原因

500 :php语法错误

502 Bad Gateway:1. nginx连不上php-fpm(php-fpm压根没跑起来、nginx无权限访问socket文件、端口错误);2. php脚本运行时间超出php-fpm request_terminate_timeout 设置的超时时间了。

503 Service Unavailable:没有足够的 php-fpm 进程来处理请求、请求频率超过了 nginx 配置的频率限制

504 Gateway Timeout:网关无法在规定的时间内获得想要的响应,比如php的执行时间大于nginx的超时时间。

待补充

HTTP错误码出现的具体原因和例子,get和post的传输限制。

参考资料

  1. 图解HTTP
  2. 网络是怎样连接的
  3. Warriors Of The Net
  4. How TCP IP Works
  5. NGINX 502 Bad Gateway: PHP-FPM