coconilu/Blog

HTTP 协议

coconilu opened this issue · 0 comments

概述

不论是在OSI七层模型还是TCP/IP协议族中,HTTP协议都是属于应用层。

HTTP协议的关键在于:

  1. HTTP请求方法
  2. 响应码
  3. 报文头部(包括请求和响应)
  4. 报文主体格式
  5. MIME
  6. 拓展功能
  7. 基于HTTP的功能追加协议

HTTP请求方法

  1. GET,请求一个指定资源的表示形式. 使用GET的请求应该只被用于获取数据
  2. POST,将实体提交到指定的资源,通常导致状态或服务器上的副作用的更改
  3. PUT,请求有效载荷替换目标资源的所有当前表示
  4. PATCH,对指定资源应用部分修改
  5. DELETE,删除指定资源
  6. HEAD,获得报文首部
  7. OPTIONS,询问支持的方法,还有作为CORS的预检请求
  8. TRACE,追踪路径,沿着到目标资源的路径执行一个消息环回测试
  9. CONNECT,要求用隧道协议连接代理

响应码

数字 类别 原因短语
1XX Informational(信息性状态码) 接收的请求正在处理
2XX Success(成功状态码) 请求正常处理完毕
3XX Redirection(重定向状态码) 需要进行附加操作以完成请求
4XX Client Error(客户端错误状态码) 服务器无法处理请求
5XX Server Error(服务器错误状态码) 服务器处理请求出错

1XX

  1. 100 Continue,这个临时响应表明,迄今为止的所有内容都是可行的,客户端应该继续请求,如果已经完成,则忽略它。
  2. 101 Switching Protocol,该代码是响应客户端的 Upgrade 标头发送的,并且指示服务器也正在切换的协议。

2XX

  1. 200 OK,请求成功。
  2. 201 Created,该请求已成功,并因此创建了一个新的资源。这通常是在PUT请求之后发送的响应。
  3. 202 Accepted,请求已经接收到,但还未响应,没有结果。
  4. 203 Non-Authoritative Information
  5. 204 no content,服务器成功处理了请求,但不需要返回任何实体内容,并且希望返回更新了的元信息。
  6. 205 Reset Content,服务器成功处理了请求,且没有返回任何内容。但是与204响应不同,返回此状态码的响应要求请求者重置文档视图。
  7. 206 partial content,服务器已经成功处理了部分 GET 请求。类似于 FlashGet 或者迅雷这类的 HTTP 下载工具都是使用此类响应实现断点续传或者将一个大文档分解为多个下载段同时下载。该请求必须包含 Range 头信息来指示客户端希望得到的内容范围,并且可能包含 If-Range 来作为请求条件。

3XX

  1. 300 Multiple Choice,被请求的资源有一系列可供选择的回馈信息,每个都有自己特定的地址和浏览器驱动的商议信息。
  2. 301 Moved Permanently,被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。
  3. 302 Found,请求的资源现在临时从不同的 URI 响应请求。
  4. 303 See Other,对应当前请求的响应可以在另一个 URI 上被找到,而且客户端应当采用 GET 的方式访问那个资源。
  5. 304 Not Modified,如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码。
  6. 307 Temporary Redirect,请求的资源现在临时从不同的URI 响应请求。
  7. 308 Permanent Redirect,这意味着资源现在永久位于由 Location: HTTP Response 标头指定的另一个 URI。

4XX

  1. 400 Bad Request,语义有误,当前请求无法被服务器理解。除非进行修改,否则客户端不应该重复提交这个请求;请求参数有误。
  2. 401 Unauthorized,当前请求需要用户验证。
  3. 403 Forbidden,服务器已经理解请求,但是拒绝执行它。
  4. 404 Not Found,请求失败,请求所希望得到的资源未被在服务器上发现。
  5. 405 Method Not Allowed,请求行中指定的请求方法不能被用于请求相应的资源。
  6. 406 Not Acceptable,请求的资源的内容特性无法满足请求头中的条件,因而无法生成响应实体。
  7. 408 Request Timeout,请求超时。客户端没有在服务器预备等待的时间内完成一个请求的发送。

5XX

  1. 500 Internal Server Error,服务器遇到了不知道如何处理的情况。
  2. 501 Not Implemented,此请求方法不被服务器支持且无法被处理。
  3. 503 Service Unavailable,服务器没有准备好处理请求。 常见原因是服务器因维护或重载而停机。

报文头部(包括请求和响应)

通用首部字段

同时适用于请求和响应消息,但与最终消息主体中传输的数据无关的消息头。

  1. cache-control,控制缓存行为
  2. connection,决定当前的事务完成后,是否会关闭网络连接。如果该值是“keep-alive”,网络连接就是持久的,不会关闭,使得对同一个服务器的请求可以继续在该连接上完成。值:keep-alive、close
  3. content-disposition,在常规的HTTP应答中,Content-Disposition 消息头指示回复的内容该以何种形式展示,是以内联的形式(即网页或者页面的一部分),还是以附件的形式下载并保存到本地。在multipart/form-data类型的应答消息体中, Content-Disposition 消息头可以被用在multipart消息体的子部分中,用来给出其对应字段的相关信息。各个子部分由在Content-Type 中定义的分隔符分隔。用在消息体自身则无实际意义。
  4. date,创建报文的日期时间
  5. pragma,是一个在 HTTP/1.0 中规定的通用首部,这个首部的效果依赖于不同的实现,所以在“请求-响应”链中可能会有不同的效果。它用来向后兼容只支持 HTTP/1.0 协议的缓存服务器,那时候 HTTP/1.1 协议中的 Cache-Control 还没有出来。
  6. trailer,允许发送方在分块发送的消息后面添加额外的元信息,这些元信息可能是随着消息主体的发送动态生成的,比如消息的完整性校验,消息的数字签名,或者消息经过处理之后的最终状态等。
  7. transfer-encoding,是一个逐跳传输消息首部,即仅应用于两个节点之间的消息传递,而不是所请求的资源本身。一个多节点连接中的每一段都可以应用不同的Transfer-Encoding 值。如果你想要将压缩后的数据应用于整个连接,那么请使用端到端传输消息首部 Content-Encoding 。
  8. upgrade,升级为其它协议
  9. via,是一个通用首部,是由代理服务器添加的,适用于正向和反向代理,在请求和响应首部中均可出现。这个消息首部可以用来追踪消息转发情况,防止循环请求,以及识别在请求或响应传递链中消息发送者对于协议的支持能力。
  10. warning,是一个通用报文首部,包含报文当前状态可能存在的问题。在响应中可以出现多个 Warning 首部。
  11. Transfer-Encoding,数据以一系列分块的形式进行发送。 Content-Length 首部在这种情况下不被发送。在每一个分块的开头需要添加当前分块的长度,以十六进制的形式表示,后面紧跟着 '\r\n' ,之后是分块本身,后面也是'\r\n' 。终止块是一个常规的分块,不同之处在于其长度为0。终止块后面是一个挂载(trailer),由一系列(或者为空)的实体消息首部构成。

请求首部字段

包含更多有关要获取的资源或客户端本身信息的消息头。

  1. Access-Control-Request-Headers,出现于 preflight request (预检请求)中,用于通知服务器在真正的请求中会采用哪些请求首部。
  2. Access-Control-Request-Method,出现于 preflight request (预检请求)中,用于通知服务器在真正的请求中会采用哪种 HTTP 方法。
  3. accept,用户代理期望的MIME 类型列表
  4. accept-charset,列出用户代理支持的字符集
  5. accept-encoding,列出用户代理支持的压缩方法
  6. accept-language,列出用户代理期望的页面语言
  7. authorization,含有服务器用于验证用户代理身份的凭证,通常会在服务器返回401 Unauthorized 状态码以及WWW-Authenticate 消息头之后在后续请求中发送此消息头。
  8. expect,包含一个期望条件,表示服务器只有在满足此期望条件的情况下才能妥善地处理请求。常见的浏览器不会发送 Expect 消息头,但是其他类型的客户端如cURL默认会这么做。
  9. from,包含一个电子邮箱地址,这个电子邮箱地址属于发送请求的用户代理的实际掌控者的人类用户。
  10. host,指明了服务器的域名(对于虚拟主机来说),以及(可选的)服务器监听的TCP端口号。
  11. if-match,条件请求,在请求方法为 GET 和 HEAD 的情况下,服务器仅在请求的资源满足此首部列出的 ETag 之一时才会返回资源。如果无法匹配,那么需要返回 416 (Range Not Satisfiable,范围请求无法满足) 响应。
  12. if-modified-since,条件请求,服务器只在所请求的资源在给定的日期时间之后对内容进行过修改的情况下才会将资源返回,状态码为 200 。如果请求的资源从那时起未经修改,那么返回一个不带有消息主体的 304 响应,而在 Last-Modified 首部中会带有上次修改时间。
  13. if-none-match,条件请求,对于 GETGET 和 HEAD 请求方法来说,当且仅当服务器上没有任何资源的 ETag 属性值与这个首部中列出的相匹配的时候,服务器端会才返回所请求的资源,响应码为 200 。当验证失败的时候,服务器端必须返回响应码 304 (Not Modified,未改变)。服务器端在生成状态码为 304 的响应的时候,必须同时生成以下会存在于对应的 200 响应中的首部:Cache-Control、Content-Location、Date、ETag、Expires 和 Vary 。
  14. if-range,条件请求,当字段值中的条件得到满足时,Range 头字段才会起作用,同时服务器回复206 部分内容状态码,以及Range 头字段请求的相应部分;如果字段值中的条件没有得到满足,服务器将会返回 200 OK 状态码,并返回完整的请求资源。
  15. if-unmodified-since,条件请求,只有当资源在指定的时间之后没有进行过修改的情况下,服务器才会返回请求的资源,或是接受 POST 或其他 non-safe 方法的请求。如果所请求的资源在指定的时间之后发生了修改,那么会返回 412 (Precondition Failed) 错误。
  16. max-forwards,通过 TRACE 方法或 OPTIONS 方法,发送包含首部字段 Max-Forwards的请求时,该字段指定可经过的服务器最大数目。
  17. origin,指示了请求来自于哪个站点,包含协议、域名、端口这三元组,主要用以判断是否同源。该首部用于 CORS 请求或者 POST 请求。除了不包含路径信息,该字段与 Referer 首部字段相似。
  18. proxy-authorization,包含了用户代理提供给代理服务器的用于身份验证的凭证。这个首部通常是在服务器返回了 407 Proxy Authentication Required 响应状态码及 Proxy-Authenticate 首部后发送的。
  19. range,告知服务器返回文件的哪一部分。在一个 Range 首部中,可以一次性请求多个部分,服务器会以 multipart 文件的形式将其返回。如果服务器返回的是范围响应,需要使用 206 Partial Content 状态码。假如所请求的范围不合法,那么服务器会返回 416 Range Not Satisfiable 状态码,表示客户端错误。服务器允许忽略 Range 首部,从而返回整个文件,状态码用 200 。
  20. referer,Referer 首部包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。服务端一般使用 Referer 首部识别访问来源,可能会以此进行统计分析、日志记录以及缓存优化等。
  21. te,用来指定用户代理希望使用的传输编码类型。(可以将其非正式称为 Accept-Transfer-Encoding, 这个名称显得更直观一些)。
  22. user-agent,包含了一个特征字符串,用来让网络协议的对端来识别发起请求的用户代理软件的应用类型、操作系统、软件开发商以及版本号。

响应首部字段

包含有关响应的补充信息,如其位置或服务器本身(名称和版本等)的消息头。

  1. Access-Control-Allow-Credentials,表示是否可以将对请求的响应暴露给页面。返回true则可以,其他值均不可以。Credentials可以是 cookies, authorization headers 或 TLS client certificates。
  2. Access-Control-Allow-Headers,表示可以支持的消息首部列表,用逗号隔开。
  3. Access-Control-Allow-Methods,用逗号隔开的允许使用的 HTTP request methods 列表。
  4. Access-Control-Allow-Origin,指定了该响应的资源是否被允许与给定的origin共享。对于不需具备凭证(credentials)的请求,服务器会以“*”作为通配符,从而允许所有域都具有访问资源的权限。
  5. Access-Control-Expose-Headers,让客户端可以访问到其他的首部信息,可以将它们在 Access-Control-Expose-Headers 里面列出来。
  6. Access-Control-Max-Age,表示 preflight request (预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存多久。单位是秒,如果值为 -1,则表示禁用缓存,每一次请求都需要提供预检请求,即用OPTIONS请求进行检测。
  7. accept-ranges,服务器使用 HTTP 响应头 Accept-Range 标识自身支持范围请求(partial requests)。字段的具体值用于定义范围请求的单位。
  8. age,包含消息对象在缓存代理中存贮的时长,以秒为单位。.
  9. etag,ETagHTTP响应头是资源的特定版本的标识符。这可以让缓存更高效,并节省带宽,因为如果内容没有改变,Web服务器不需要发送完整的响应。
  10. location,指定的是需要将页面重新定向至的地址。一般在响应码为3xx的响应中才会有意义。
  11. proxy-authenticate,定了获取 proxy server (代理服务器)上的资源访问权限而采用的身份验证方式。代理服务器对请求进行验证,以便它进一步传递请求。需要与 407 Proxy Authentication Required 响应一起发送。
  12. retry-after,表示用户代理需要等待多长时间之后才能继续发送请求。
  13. server,包含了处理请求的源头服务器所用到的软件相关信息。
  14. vary,决定了对于未来的一个请求头,应该用一个缓存的回复(response)还是向源服务器请求一个新的回复。
  15. www-authenticate,定义了使用何种验证方式去获取对资源的连接,通常会和一个 401 Unauthorized 的响应一同被发送。

在跨域访问资源中,只有六种简单响应头部可以暴露给外部:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma

实体首部字段

包含有关实体主体的更多信息,比如主体长(Content-Length)度或其MIME类型。

  1. allow,用于枚举资源所支持的 HTTP 方法的集合。若服务器返回状态码 405 Method Not Allowed,则该首部字段亦需要同时返回给客户端。如果 Allow 首部字段的值为空,说明资源不接受使用任何 HTTP 方法的请求。
  2. content-encoding,用于对特定媒体类型的数据进行压缩。
  3. content-language,用来说明访问者希望采用的语言或语言组合,这样的话用户就可以根据自己偏好的语言来定制不同的内容。
  4. content-length,用来指明发送给接收方的消息主体的大小,即用十进制数字表示的八位元组的数目。
  5. content-location,指定的是要返回的数据的地址选项。最主要的用途是用来指定要访问的资源经过内容协商后的结果的URL。
  6. content-md5,客户端会对接收的报文主体执行相同的MD5算法,然后与首部字段Comtent-MD5的字段值比较。
  7. content-range,显示的是一个数据片段在整个文件中的位置。
  8. content-security-policy,允许站点管理者在指定的页面控制用户代理的资源。除了少数例外,这条政策将极大地指定服务源 以及脚本端点。这将帮助防止跨站脚本攻击(Cross-Site Script) (XSS)。
  9. content-security-policy-report-only,HTTP Content-Security-Policy-Report-Only响应头允许web开发人员通过监测(但不强制执行)政策的影响来尝试政策。这些违反报告由 JSON 文档组成通过一个HTTP POST请求发送到指定的URI。
  10. content-type,用于指示资源的MIME类型 media type 。
  11. expires,包含日期/时间, 即在此时候之后,响应过期。如果在Cache-Control响应头设置了 "max-age" 或者 "s-max-age" 指令,那么 Expires 头会被忽略。
  12. last-modified,包含源头服务器认定的资源做出修改的日期及时间。 它通常被用作一个验证器来判断接收到的或者存储的资源是否彼此一致。由于精确度比 ETag 要低,所以这是一个备用机制。包含有 If-Modified-Since 或 If-Unmodified-Since 首部的条件请求会使用这个字段。

需要注意的事项

自定专用消息头可通过'X-' 前缀来添加。

如果HTTP首部字段重复了,不同的浏览器的处理逻辑不同,结果可能不一致。

消息头还可以根据代理对其的处理方式分为:

  1. 端到端消息头,这类消息头必须被传输到最终的消息接收者,也即,请求的服务器或响应的客户端。中间的代理服务器必须转发未经修改的端到端消息头,并且必须缓存它们。
  2. 逐跳消息头,这类消息头仅对单次传输连接有意义,不能通过代理或缓存进行重新转发。这些消息头包括 Connection, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, TE, Trailer, Transfer-Encoding 及 Upgrade。注意,只能使用 Connection 来设置逐跳一般头。

报文主体格式

除了HTML外,还有:

  1. XML
  2. rss/ATOM
  3. json
  4. Google Protocol Buffer

MIME(多用途因特网邮件扩展)

独立类型

类型 描述 典型示例
text 表明文件是普通文本,理论上是人类可读 text/plain, text/html, text/css, text/javascript
image 表明是某种图像。不包括视频,但是动态图(比如动态gif)也使用image类型 image/gif, image/png, image/jpeg, image/bmp, image/webp,
 image/x-icon, image/vnd.microsoft.icon
audio 表明是某种音频文件 audio/midi, audio/mpeg, audio/webm, audio/ogg, audio/wav
video 表明是某种视频文件 video/webm, video/ogg
application 表明是某种二进制数据 application/octet-stream, application/pkcs12,
 application/vnd.mspowerpoint, application/xhtml+xml,
 application/xml,  application/pdf

复合类型

  1. multipart/form=data,联系 HTML Forms 和 POST 方法
  2. multipart/byteranges,使用状态码206 Partial Content来发送整个文件的子集,而HTTP对不能处理的复合文件使用特殊的方式:将信息直接传送给浏览器

拓展功能

状态管理

Set-Cookie/Cookie,用于解决无状态的HTTP协议。

由服务器发送的响应报文的头部里携带Set-Cookie字段,以后客户端发送请求都会携带Cookie。

属性:
expires:过期时间
max-age:有效时长
secure:Cookie只应通过被HTTPS协议加密过的请求发送给服务端。
httponly:为避免跨域脚本 (XSS) 攻击,通过JavaScript的 Document.cookie API无法访问带有 HttpOnly 标记的Cookie,它们只应该发送给服务端。
domain:指定了哪些主机可以接受Cookie。
path:指定了主机下的哪些路径可以接受Cookie。

长连接

HTTP1.0需要设置:connection: keep-alive
HTTP1.1默认保持长连接。

  1. 目的是在建立1次TCP连接后进行多次请求和响应的交互
  2. 只要任意一端没有明确提出断开连接,则保持TCP连接状态
  3. 需要服务器端和客户端同时支持

范围请求

客户端可以通过请求报文设置range头部,用以请求完整内容的部分。如果服务器端无法响应范围请求,则会返回状态码200 OK和完整的实体内容。

这也是断点续传的原理。

Range头部可以设置几段,用以分别加载不连续的分块内容。这样的情况下,服务器返回的响应头部的Content-Type会表明multipart/byteranges,同时Accept-Ranges会设置为返回的分段(如果服务器不支持范围请求,会设置为none)。

编码压缩

内容编码指明应用在实体内容上的编码格式,并保持实体信息原样压缩。内容编码后的实体由客户端接收并负责解码。

客户端在请求数据的时候会通过头字段:Accept-Encoding表明支持的编码格式,由服务器进行选择,并在响应报文中使用头字段:Content-Encoding指明使用的编码格式。

主流编码格式有:

  1. gzip(GNU zip)
  2. compress(UNIX系统的标准压缩)
  3. deflate(zlib)
  4. identity(不进行编码)

缓存机制

请参考:《浏览器缓存机制》

内容协商

内容协商可以根据不同的客户端环境来呈现不一样的内容。主要有以下三类:

  1. 服务器驱动协商:根据头部来判断,比如语言版本
  2. 客户端驱动协商:响应式设计
  3. 透明协商:结合服务器驱动和客户端驱动

基于HTTP的功能追加协议

HTTP功能上的不足可通过创建一套全新的协议来弥补。可是目前基于HTTP的Web浏览器的使用环境已遍布全球,因此无法完全抛弃HTTP。

有一些新协议的规则是基于HTTP的,并在此基础上添加了新的功能。代表有:

  1. Google 的SPDY
  2. WebSocket
  3. HTTP/2
  4. WebDAV(Web-based Distributed Authoring and Versioning)

参考

《网络是怎样连接的》
《图解TCP/IP》
《TCP/IP详解》

HTTP
HTTP概述
HTTP 请求方法
HTTP Headers
MIME 类型
HTTP 响应代码