HTTP协议

2019-10-08  本文已影响0人  伊凡的一天

1. HTTP常见方法

HTTP/1.1 200 OK
Allow: OPTIONS, GET, HEAD, POST
Cache-Control: max-age=604800
Date: Thu, 13 Oct 2016 11:45:00 GMT
Expires: Thu, 20 Oct 2016 11:45:00 GMT
Server: EOS (lax004/2813)
x-ec-custom-error: 1
Content-Length: 0

PUT和POST方法的区别在于,PUT方法是幂等的,即连续调用一次或者多次的效果相同(无副作用),而POST方法是非幂等的。

CONNECT方法用于创建代理服务器到目标服务器之间的TCP连接。我们可以在浏览器中配置一个代理服务器,之后浏览器在发送所有的HTTP请求前,会先通过CONNECT方法建立起代理服务器到目标Server间的TCP通道,之后浏览器所有的HTTP请求都发送给这台代理服务器,代理服务器收到请求后转发给目标Server并将收到的响应原封不动的返回给浏览器。因此,只有当浏览器配置为使用代理服务器时才会用到CONNECT方法,平时我们进行网页开发时是用不到的。当我们想要访问的资源客户端无法直接访问只能通过代理服务器访问时,此时我们就可以使用HTTP代理技术,例如VPN就是一种常见的HTTP代理技术。

PATCH和PUT的区别:使用PUT方法更新一个资源时,我们必须将整个资源传递给Server,然后Server会将旧对象完全覆盖。而是用PATCH方法可以直接传递变化了的资源属性,达到传输数据更少的目的。

2. HTTP协议报文

2.1 请求报文

HTTP协议的请求报文分为4部分:

例如一个GET请求的报文如下:

 GET /books/?sex=man&name=Professional HTTP/1.1
 Host: www.example.com
 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) 
 Gecko/20050225 Firefox/1.0.1
 Connection: Keep-Alive

在头部字段中设置Connection:keep-aliveKeep-Alive: timeout=60,表明连接建立之后,空闲时间超过60秒就会失效。

而一个POST请求的报文如下:

 POST / HTTP/1.1
 Host: www.example.com
 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
 Gecko/20050225 Firefox/1.0.1
 Content-Type: application/x-www-form-urlencoded
 Content-Length: 40
 Connection: Keep-Alive

 sex=man&name=Professional  

POST请求包含了一个请求实体,为sex=man&name=Professional。头部字段Content-Type: application/x-www-form-urlencoded表示请求实体中包含的是form类型的信息,其他可选值包括application/json(表示json数据),multipart/form-data(表示上传文件)等等。

2.2 响应报文

响应报文也由4部分组成:

下面是一个HTTP响应的例子:

HTTP/1.1 200 OK

Server:Apache Tomcat/5.0.12
Date:Mon,6Oct2003 13:23:42 GMT
Content-Length:112

<html>...

3. 常见首部

3.1 请求首部

下面是客户端向服务器发送请求报文时一些常见的首部:

Accept

Accept表示客户端或者代理能够处理的媒体类型。客户端期望的资源类型服务器可能没有,所以客户端会期望多种类型,并且设置优先级,服务器根据优先级寻找相应的资源返回给客户端。例如:

# 注意:逗号分割类型,分号分割属性
Accept: audio/*; q=0.2, audio/basic

其中q的取值范围是(0-1],其具体值并没有意义,它仅用来排序优先级,如果没有q,默认q=1,也就是最高优先级。上面表示客户端希望服务器优先返回audio/basic类型的资源,如果没有,就随便其它什么格式的audio资源都可以。

类似的,Accept-EncodingAccept-LanguageAccept-Charset分别表示优先可处理的编码格式,自然语言和字符集。

If-Match/If-None-Match

If-Match/If-None-Match用于和响应首部中的ETag进行比较。当且仅当Server对于If-Match/If-None-Match和Etag的比较符合预期,Server才会处理这个HTTP请求并返回对应的响应。

ETAG是一个响应首部,HTTP仅仅规定它是一个以引号开头结尾的值,并没有规定它的具体语义。

客户端常常使用If-Match用于HTTP乐观锁。所谓HTTP乐观锁,是指客户端先GET这个资源得到ETag的值(此时这个ETAG的语义就是版本号),然后发起一个PUT|PATCH请求时将If-Match的值设置为ETAG的值,如果服务器资源的最新ETAG满足If-Match设置的值,请求就会被执行。如果不满足,说明资源被并发修改了,就需要返回412 Precondition failed 的错误。客户端可以选择放弃或者重试整个过程。

If-None-Match可以用于缓存控制。它的原理是这样的,当浏览器请求服务器的某项资源(A)时, 服务器根据A算出一个哈希值(3f80f-1b6-3e1cb03b)并通过 ETag 返回给浏览器,浏览器把"3f80f-1b6-3e1cb03b" 和 A 同时缓存在本地,当下次再次向服务器请求A时,会通过类似If-None-Match: "3f80f-1b6-3e1cb03b"的请求头把ETag发送给服务器,服务器再次计算A的哈希值(即计算最新的Etag值)并和浏览器发送的If-None-Match值做比较,如果发现相同直接浏览器返回一个304 Not Modified响应,如果发现不相等则触发了If-None-Match语义,服务器就把A返回给浏览器(即状态码为200)。这样通过控制浏览器端的缓存,可以节省服务器的带宽,因为服务器不需要每次都把全量数据返回给客户端。

我们也可以通过If-Modified-Since请求首部来控制缓存。服务器响应首部中包含一个Last-Modified值,每一次客户端发送HTTP请求时,将上一次收到的Last-Modified值作为If-Modified-Since的值发送给服务器,服务器根据请求中If-Modified-Since的值来返回最新的资源或304 Not Modified。Last-Modified的问题在于它的精度为秒级别,不适合适合更新频繁的敏感资源。

Range

Range表示客户端告知服务器返回文件的哪一部分。支持断点续传的服务器必须处理Range头。

例如:

Range: bytes=200-1000, 2000-6576, 19000-

If-Range

在断点续传时,为确保连续2个请求之间服务器资源本身没有发生变化,需要If-Range头带上ETag的资源版本号。服务器资源根据这个版本号来判定资源是否改变了。如果没变,就返回206 Partial Content将部分资源返回。如果资源变了,那就相当于一个普通的GET请求,返回200 OK和整个资源内容。

Authorization

对于某些需要特殊权限才能访问的资源,客户端在请求里通过Authorization首部提供认证信息。

例如:

# value = base64(user_name:password)
Authorization: Basic YWRtaW46YWRtaW4xMjM=

Host

Host表示请求资源所在服务器。

User-Agent

User-Agent携带当前的客户端信息,一般包含浏览器、浏览器内核和操作系统的版本型号信息。

3.2 响应首部

Content-Type

Content-Type代表响应内容的媒体类型和编码格式,是对请求报文中Accept头和Accept-Charset头的统一应答。*

Content-Type: text/html; charset=utf8

Etag

ETag一般携带的是资源的版本号。协议没有具体规定版本号是什么。它可以是资源的md5校验码,也可以是uuid,甚至可以是自增的数字,也可以是资源的修改时间。它的匹配方式是相等/不相等(即If-Match和If-None-Match)。因为服务器需要维护版本号,取决的版本号是什么,这可能是一个存储和计算的负担。

Last-Modified携带的资源的修改时间。它的匹配方式是大于/小于(If-Modified-Since和If-Unmodified-Since)。如果是静态资源文件,一般就是操作系统记录的文件修改时间。

Expires是服务器告知客户端资源的过期时间。客户端缓存的资源在这个时间之后自动过期,而不需要非得向服务器确认一下是不是304 Not Modified才认为没过期。

Location

服务器向客户端发送302跳转的时候,总会携带Location头信息,它的值为目标URL。

例如:

HTTP/1.1 302 Temporary Redirect
Location: https://www-temp.example.org/

WWW-Authenticate

WWW-Authenticate是401 Unauthorized错误码返回时必须携带的头,该头会携带一个问题Challenge给客户端,告知客户端需要携带这个问题的答案来请求服务器才可以继续访问目标资源。这种问题Challenge可以自定义,比较常见的是Basic认证。

例如:

WWW-Authenticate: Basic realm=xxx

Basic指代base64加密算法(不安全),realm指代认证范围/场合/情景名称。

Server

用于返回服务器相关的软件信息,来告知客户端当前的HTTP服务是由某某软件提供的,可以看成是一种软件广告。 RFC协议里对这个头信息做了警告:暴露出服务器信息可能会导致黑客更易于攻击你的服务,建议谨慎使用。

Retry-After

服务器升级时,来自客户端的请求会直接给予503(Service Unavailable)错误,通过在返回头里面加入Retry-After字段告知客户端何时服务可以恢复正常访问。Retry-After的头可以是HTTP-Date,也可以是整数,表示多少秒后服务可以恢复正常访问。浏览器在拿到这个值之后可以考虑增加一个定时器在未来的某个时间进行重试。

Age

表示资源缓存的年龄,也就是资源自缓存以来到现在已经过去了多少时间,单位是秒。

3.3 通用首部

Connection

Connection决定当前的事务完成后,是否会关闭网络连接。如果该值是keep-alive,网络连接就是持久的,不会关闭,使得对同一个服务器的请求可以继续在该连接上完成。如果是close,则表示当前事务完成后,服务器应该关闭这个HTTP连接。

Connection: close

HTTP协议自从1.1版本后,Connection属性默认值是keep-alive

Cache-Control

Cache-Control既可以用于请求,也可以用于响应。在请求和响应的取值不一样,分别代表了不同的意思。

  1. no-cache 如果no-cache没有指定值,那就表示不允许缓存。对于请求来说,服务器不得使用缓存内容直接返回。对于响应来说,客户端不得缓存响应的资源内容。
  2. no-store 告知对方不要持久化请求/响应数据到其它地方,这种信息是敏感的,要保持它的易失性。告知对方记在心里(memory)就行,别写在纸上(disk)。
  3. no-transform 告知对方不要转换数据。比如客户端上传了raw图像数据,服务器一般都会选择性压缩图像数据进行存储。no-transform告知对方保留原始数据信息,不要进行任何转换。告知对方不要乱动我发过来的东西。
  4. only-if-cached 用于请求头,告知服务器只要那些已经缓存的内容,不要去reload。如果没有缓存内容就返回504 Gateway Timeout错误。表示客户端不想太麻烦服务器,有就给,没就算了。
  5. max-age 用于请求头。限制缓存内容的年龄,如果超过max-age年龄的,需要服务器去reload内容资源。这叫客户端的年龄歧视。
  6. max-stale 用于请求头。客户端允许服务器返回缓存已过期的资源内容,但是限定了最大过期时间。表示客户端虽然很宽容,那是也是有限度的。
  7. min-fresh 用于请求头。客户端限制服务器不要那些即将过期的资源内容。就好比我们去超市买牛奶,如果牛奶快过期了虽然还在保质期内咱们也就不会考虑。
  8. public 用于响应头。表示所有内容都将被缓存(客户端和代理服务器都可缓存)。
  9. private 用于响应头。表示内容只缓存到私有缓存中(仅客户端可以缓存,代理服务器不可缓存)。

Transfer-Encoding

Transfer-Encoding表示报文主体的传输编码格式。尽管这个取值理论上可以有很多,但是当前的 HTTP 规范里实际上只定义了一种传输取值——chunked。

当HTTP对Body进行分块传送时,需要增加头部信息Transfer-Encoding: chunked才可以进行分块传送。

如果一个HTTP消息(请求消息或应答消息)的Transfer-Encoding消息头的值为chunked,那么,消息体由数量未定的块组成,并以最后一个大小为0的块为结束。

每一个非空的块都以该块包含数据的字节数(字节数以十六进制表示)开始,跟随一个CRLF (回车及换行),然后是数据本身,最后块CRLF结束。在一些实现中,块大小和CRLF之间填充有白空格(0x20)。

最后一块是单行,由块大小(0),一些可选的填充白空格,以及CRLF。最后一块不再包含任何数据,但是可以发送可选的尾部,包括消息头字段。消息最后以CRLF结尾。

一个示例响应如下:

HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

25
This is the data in the first chunk

1A
and this is the second one
0

4. 常见HTTP状态码

2xx 成功

3xx 重定向

4xx 客户端错误

5XX 服务器错误

5. HTTP持久连接

我们知道 HTTP 协议采用“请求-应答”模式,当使用普通模式,即非 Keep-Alive 模式时,每个请求/应答客户和服务器都要新建一个连接,完成之后立即断开连接(HTTP 协议为无连接的协议);当使用 Keep-Alive 模式(又称持久连接、连接重用)时,Keep-Alive 功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive 功能避免了建立或者重新建立连接。

在 HTTP 1.1 版本中,默认情况下所有连接都被保持,如果请求首部加入Connection: close才关闭。目前大部分浏览器都使用 HTTP 1.1 协议,也就是说默认都会发起 Keep-Alive 的连接请求了,所以是否能完成一个完整的 Keep-Alive 连接就看服务器设置情况。

参考文章

上一篇下一篇

猜你喜欢

热点阅读