HTTP协议

一、什么是HTTP协议

HTTP协议 -- HyperText Transfer Protocol 超文本传输协议,HTTP 是一种能够获取如 HTML 这样的网络资源的 protocol(通讯协议)。它是在 Web 上进行数据交换的基础,是一种 client-server 协议,也就是说,请求通常是由像浏览器这样的接受方发起的。一个完整的 Web 文档通常是由不同的子文档拼接而成的,像是文本、布局描述、图片、视频、脚本等等

客户端和服务端通过交换各自的消息(与数据流正好相反)进行交互。由像浏览器这样的客户端发出的消息叫做请求(request),被服务端响应的消息叫做响应(response)

二、HTTP的发展

HTTP协议是因特网的基础协议,1989-1991年由英国计算机科学家蒂姆.伯纳斯.李发明,如今HTTP已经由传输简单文本,发展成为可以传输图像,视频等内容的重要的互联网协议。

现在HTTP协议用的最广泛的版本是HTTP1.1。相对于以前的版本主要的改进是:

  • 链接复用,节约了多次建立TCP链接的开销

  • 管线化技术,允许在第一个应答被完全发送之前就发送第二个请求,以降低通信延迟

  • 支持响应分块

  • 引入额外的缓存控制机制

  • 引入内容协商机制,包括语言、编码、类型等。并允许客户端和服务器之间约定以最合适的内容进行交换

三、HTTP消息

HTTP 消息是服务器和客户端之间交换数据的方式。有两种类型的消息:请求(request)——由客户端发送用来触发一个服务器上的动作;响应(response)——来自服务器的应答

HTTP协议是无状态的,即客户端发一个请求,服务器给一个响应。每一次请求和响应都是独立的,之间并没有联系。

HTTP请求和响应类似,结构如下:

  1. 一行起始行用于描述要执行的请求,或者是对应的状态,成功或失败。这个起始行总是单行的。

  1. 一个可选的 HTTP 标头集合指明请求或描述消息主体(body)。

  1. 一个空行指示所有关于请求的元数据已经发送完毕。

  1. 一个可选的包含请求相关数据的主体(比如 HTML 表单内容),或者响应相关的文档。主体的大小有起始行的 HTTP 头来指定。

四、HTTP会话

HTTP是客户端服务器协议(Client-server),会话分三个阶段:

  1. 客户端建立一条 TCP 连接(如果传输层不是 TCP,也可以是其他适合的连接)。

  1. 客户端发送请求并等待应答。

  1. 服务器处理请求并送回应答,回应包括一个状态码和对应的数据

从 HTTP/1.1 开始,连接在完成第三阶段后不再关闭,客户端可以再次发起新的请求。这意味着第二步和第三步可以连续进行数次。(keepalived)

五、HTTP常见的状态码

  • 200 请求成功,默认返回200状态码的响应会被缓存

  • 201 资源被成功创建

  • 302 重定向状态码,浏览器会重定向到Location 指定的URL上

  • 400 请求参数错误

  • 404 请求的资源不存在

  • 405 服务器不接受当前HTTP的条件方法,如服务器明确表明接受GET请求,发请求时指定的确实POST

  • 500 服务器发生内部错误

  • 502 表示网关或代理服务器从上游服务器收到无效响应

  • 504 网关超时

上面只列出了常见的HTTP状态码,详细可相关HTTP协议。

六、HTTP结构

HTTP报文格式:

七、HTTP的请求方法

  • GET:传递参数长度受限制,因为传递的参数是直接表示在地址栏中,而特定的浏览器和服务器对URL的长度是有限制的。因此GET请求不适合用来传递私密数据,也不太适合拿来传递大量数据

  • POST:传递的数据封装在HTTP请求数据中,以名称/值的形式出现,可以传输大量数据,对数据量没有限制,也不会显示在URL中

  • HEAD:跟GET相似,不过服务端收到HEAD请求时只返回响应头,不发送响应内容。所以,如果只需要查看某个页面的状态时,用HEAD更高效,因为省去了传输页面内容的时间

  • DELETE:删除某一资源

  • OPTIONS:用于获取当前URL所支持的方法。若请求成功,会在HTTP头中包含一个名为“Allow” 的头,值是所支持的方法,如“GET”、“POST”

  • PUT:把一个资源存放在指定位置上。与POST相似,但PUT通常指定了资源的存放位置,而POST则没有

  • TRACE:回显服务器收到的请求,主要用于测试或诊断

  • CONNECT:是HTTP1.1预留的,能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接与非加密的HTTP代理服务器的通信

八、HTTP常见请求头

HTTP请求头由键和值组成,每行一个

  • User-Agent : 产生请求的浏览器类型

  • Accept : 客户端希望接受的数据类型,比如 Accept:text/xml(application/json)表示希望接受到的是xml(json)类型

  • Content-Type 发送端发送实体的数据类型,如:text/html 表示发送的是html,application/json 表示发送的是json格式的数据

  • Host 表示请求的主机名

  • Accept 描述客户端希望接受到的响应的Body类型

  • Accept-Language 请求头允许客户端声明它可以理解的自然语言,以及优先选择的区域方言。借助内容协商机制,服务器可以从诸多备选项中选择一项进行应用,并使用Content-Language应答头通知客户端它的选择

  • Accept-Encoding 将客户端能够理解的内容编码方式——通常是某种压缩算法——进行通知(给服务端)。通过内容协商的方式,服务端会选择一个客户端提议的方式,使用并在响应头Content-Encoding中通知客户端该选择

  • Referer 包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。服务端一般使用Referer请求头识别访问来源,可能会以此进行统计分析、日志记录以及缓存优化等

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

  • Upgrade-Insecure-Requests 用来向服务器端发送信号,表示客户端优先选择加密及带有身份验证的响应,并且它可以成功处理upgrade-insecure-requestsCSP (en-US) 指令

  • If-Modified-Since 是一个条件式请求首部,服务器只在所请求的资源在给定的日期时间之后对内容进行过修改的情况下才会将资源返回,状态码为200。如果请求的资源从那时起未经修改,那么返回一个不带有消息主体的304响应,而在Last-Modified首部中会带有上次修改时间。

  • 只可以用在GET或HEAD请求中

  • 当与If-None-Match一同出现时,它(If-Modified-Since)会被忽略掉,除非服务器不支持If-None-Match

  • If-None-Match 是一个条件式请求首部。对于 GETGET和HEAD请求方法来说,当且仅当服务器上没有任何资源的ETag属性值与这个首部中列出的相匹配的时候,服务器端才会返回所请求的资源,响应码为200。对于其他方法来说,当且仅当最终确认没有已存在的资源的ETag属性值与这个首部中所列出的相匹配的时候,才会对请求进行相应的处理

  • ETag HTTP响应头是资源的特定版本的标识符,这可以让缓存更高效,并节省带宽,因为如果内容没有改变,Web 服务器不需要发送完整的响应。而如果内容发生了变化,使用 ETag 有助于防止资源的同时更新相互覆盖(“空中碰撞”)

  • 如果给定的URL中的资源更改,则一定会生成新的ETag值,比较这些ETag能快速确定此资源是否变化

  • Cache-Control 通用消息头字段,被用于在 http 请求和响应中,通过指定指令来实现缓存机制。缓存指令是单向的,这意味着在请求中设置的指令,不一定被包含在响应中

  • public 指示响应可能被任何缓存缓存

  • private 指示该响应是针对单个用户的,并且不能由共享缓存存储。私有缓存可以存储该响应

  • no-cache 在释放缓存副本之前,强制高速缓存将请求提交给原始服务器进行验证

  • only-if-cached 表示不检索新数据。客户端只希望获得缓存的响应,并且不应该联系原始服务器以查看是否存在新的副本

  • max-age=<seconds> 指定资源被视为新鲜的最长时间

  • s-maxage=<seconds> 覆盖max-age或Expires标题,但它只适用于共享缓存(例如,代理)并被私有缓存忽略

  • max-stale[=<seconds>] 表示客户愿意接受超过其到期时间的响应。或者,您可以以秒为单位指定一个值,指示响应不能过期的时间

  • min-fresh=<seconds> 表示客户想要的响应至少在指定的秒数内仍然是新鲜的

  • stale-while-revalidate=<seconds> 指示客户端愿意接受陈旧的响应,同时在后台异步检查新的响应。秒值指示客户愿意接受陈旧响应的时间

Content-Type常见值:

Content-Type值

含义

text/html

text/xml

POST专用,发送xml格式数据

text/plain

纯文本文件

text/css

text/javascript

image/gif

image/jpeg

image/png

application/x-www-form-urlencoded

POST专用,普通表单的默认提交格式,form表单数据编码为key/value格式发往服务器

application/json

POST专用,告诉服务器消息体为序列化的json数据

mutipart/form-data

用于支持向服务器发送二进制数据,上传图片,视频等二进制数据使用

HTTP请求头示例:

GET /home.html HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://developer.mozilla.org/testpage.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1
If-Modified-Since: Mon, 18 Jul 2016 02:36:04 GMT
If-None-Match: "c561c68d0ba92bbeb8b0fff2a9199f722e3a621a"
Cache-Control: max-age=0请求体部分

九、HTTP响应头

应答头

说明

Allow

服务器支持哪些请求方法(如GET、POST等)。

Content-Encoding

文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet应该通过查看Accept-Encoding头(即request.getHeader("Accept-Encoding"))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。

Content-Length

表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入 ByteArrayOutputStream,完成后查看其大小,然后把该值放入Content-Length头,最后通过byteArrayStream.writeTo(response.getOutputStream()发送内容。

Content-Type

表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType。

Date

当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。

Expires

应该在什么时候认为文档已经过期,从而不再缓存它?

Last-Modified

文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个304(Not Modified)状态。Last-Modified也可用setDateHeader方法来设置。

Location

表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。

Refresh

表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。

注意这种功能通常是通过设置HTML页面HEAD区的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">实现,这是因为,自动刷新或重定向对于那些不能使用CGI或Servlet的HTML编写者十分重要。但是,对于Servlet来说,直接设置Refresh头更加方便。

注意Refresh的意义是"N秒之后刷新本页面或访问指定页面",而不是"每隔N秒刷新本页面或访问指定页面"。因此,连续刷新要求每次都发送一个Refresh头,而发送204状态代码则可以阻止浏览器继续刷新,不管是使用Refresh头还是<META HTTP-EQUIV="Refresh" ...>。

注意Refresh头不属于HTTP 1.1正式规范的一部分,而是一个扩展,但Netscape和IE都支持它。

Server

服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。

Set-Cookie

设置和页面关联的Cookie。Servlet不应使用response.setHeader("Set-Cookie", ...),而是应使用HttpServletResponse提供的专用方法addCookie。参见下文有关Cookie设置的讨论。

WWW-Authenticate

客户应该在Authorization头中提供什么类型的授权信息?在包含401(Unauthorized)状态行的应答中这个头是必需的。例如,response.setHeader("WWW-Authenticate", "BASIC realm=\"executives\"")。

注意Servlet一般不进行这方面的处理,而是让Web服务器的专门机制来控制受密码保护页面的访问(例如.htaccess)。

Strict-Transport-Security

(通常简称为 HSTS)响应标头用来通知浏览器应该只通过 HTTPS 访问该站点,并且以后使用 HTTP 访问该站点的所有尝试都应自动转换为 HTTPS。网站通过 HTTP Strict Transport Security 通知浏览器,这个网站禁止使用 HTTP 方式加载,浏览器应该自动把所有尝试使用 HTTP 的请求自动替换为 HTTPS 请求。可预防中间人攻击。

  • max-age=<expire-time> 设置在浏览器收到这个请求后的<expire-time>秒的时间内凡是访问这个域名下的请求都使用 HTTPS 请求

  • includeSubDomains 如果这个可选的参数被指定,那么说明此规则也适用于该网站的所有子域名

X-Content-Type-Options

HTTP 消息头相当于一个提示标志,被服务器用来提示客户端一定要遵循在 Content-Type 首部中对 MIME 类型 的设定,而不能对其进行修改。这就禁用了客户端的 MIME 类型嗅探行为,换句话说,也就是意味着网站管理员确定自己的设置没有问题。

X-Frame-Options

用来给浏览器指示允许一个页面可否在 <frame>、<iframe>、<embed> 或者 <object> 中展现的标记。站点可以通过确保网站没有被嵌入到别人的站点里面,从而避免点击劫持 (en-US)攻击

  • DENY 不光在别人的网站 frame 嵌入时会无法加载,在同域名页面中同样会无法加载

  • SAMEORIGIN 表示该页面可以在相同域名页面的 frame 中展示

X-XSS-Protection

是 Internet Explorer,Chrome 和 Safari 的一个特性,当检测到跨站脚本攻击 (XSS (en-US)) 时,浏览器将停止加载页面。若网站设置了良好的 Content-Security-Policy 来禁用内联 JavaScript ('unsafe-inline'),现代浏览器不太需要这些保护,但其仍然可以为尚不支持 CSP 的旧版浏览器的用户提供保护

  • 0 禁止 XSS 过滤

  • 1 启用 XSS 过滤(通常浏览器是默认的)。如果检测到跨站脚本攻击,浏览器将清除页面(删除不安全的部分)

  • 1;mode=block 启用 XSS 过滤。如果检测到攻击,浏览器将不会清除页面,而是阻止页面加载

  • 1; report=<reporting-URI> (Chromium only) 启用 XSS 过滤。如果检测到跨站脚本攻击,浏览器将清除页面并使用 CSP report-uri (en-US)指令的功能发送违规报告

Vary

HTTP 响应头部信息,它决定了对于未来的一个请求头,应该用一个缓存的回复 (response) 还是向源服务器请求一个新的回复。它被服务器用来表明在 content negotiation algorithm(内容协商算法)中选择一个资源代表的时候应该使用哪些头部信息(headers)

语法:

Vary: *Vary: <header-name>, <header-name>, ...

Age

Age消息头里包含对象在缓存代理中存贮的时长,以秒为单位。Age 的值通常接近于 0。表示此对象刚刚从原始服务器获取不久;其他的值则是表示代理服务器当前的系统时间与此应答中的通用头 Date 的值之差

HTTP响应结构示例:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 55743
Connection: keep-alive
Cache-Control: s-maxage=300, public, max-age=0
Content-Language: en-US
Date: Thu, 06 Dec 2018 17:37:18 GMT
ETag: "2e77ad1dc6ab0b53a2996dfd4653c1c3"
Server: meinheld/0.6.1
Strict-Transport-Security: max-age=63072000
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Vary: Accept-Encoding,Cookie
Age: 7
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>A simple webpage</title>
</head>
<body>
  <h1>Simple HTML webpage</h1>
  <p>Hello, world!</p>
</body>
</html>

十、MIME类型

媒体类型(通常称为 Multipurpose Internet Mail ExtensionsMIME 类型)是一种标准,用来表示文档、文件或字节流的性质和格式。它在IETF RFC 6838中进行了定义和标准化。作用是:定义浏览器应该如何解释媒体类型和如何处理有效或无效媒体类型的内容。

常见的MIME类型:

  • application/octet-stream 这是应用程序文件的默认值。意思是 *未知的应用程序文件,*浏览器一般不会自动执行或询问执行。浏览器会像对待 设置了 HTTP 头Content-Disposition值为attachment的文件一样来对待这类文件。

  • text/plain 文本文件默认值。即使它意味着未知的文本文件,但浏览器认为是可以直接展示的

  • text/css 在网页中要被解析为 CSS 的任何 CSS 文件必须指定 MIME 为text/css。通常,服务器不识别以.css 为后缀的文件的 MIME 类型,而是将其以 MIME 为text/plain或application/octet-stream来发送给浏览器:在这种情况下,大多数浏览器不识别其为 CSS 文件,直接忽略掉。**特别要注意为 CSS 文件提供正确的 MIME 类型**

  • text/html 所有的 HTML 内容都应该使用这种类型。XHTML 的其他 MIME 类型(如application/xml+html)现在基本不再使用(HTML5 统一了这些格式)

  • text/javascript 根据HTML标准,应该总是使用MIME类型text/javascript指定javascript文件,使用其他值,将导致脚本不会被载入并运行。

十一、跨源资源共享(CORS)

CORS意为跨域共享,是一种基于HTTP头的机制,该机制通过允许服务器除自己以外的其他源(协议名+域名(地址)+ 端口号 标记一个源)来访问和加载自己的资源。例如:运行在http://domain-01.com的JavaScript代码使用XMLHttpRequest(ajax)发起的到http://domain-02.com的请求,在默认情况下,处于安全行的考虑,基于同源策略,浏览器会限制发起跨源的HTTP请求。现在系统开发很多采用的是前后端分离的默认,即前端资源和后端业务服务器分别部署在不同的服务器上,所以需要进行设置允许跨域。

跨域请求的设置方法:

假设有请求如下:

GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  #q=xxx 指定权重,权重值是从0-1的小数,最多精确到小数位3位,服务器有限返回权重值高的类型Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: https://foo.example

请求头中的 Origin 表明该请求来源于 http://foo.example

响应如下:

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml
[…XML Data…]

响应中的Access-Control-Allow-Origin: * 该资源可以被任意的外部源使用。如果资源的持有者只想允许http://foo.example访问自己的资源,如果在响应头中做如下的设置:

Access-Control-Allow-Origin: http://foo.example

关于预检请求:

预检请求要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。

预检请求示例:

POST /doc HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
X-PINGOTHER: pingpong
Content-Type: text/xml; charset=UTF-8
Referer: https://foo.example/examples/preflightInvocation.html
Content-Length: 55
Origin: https://foo.example
Pragma: no-cache
Cache-Control: no-cache

<person><name>Arun</name></person>

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:40 GMT
Server: Apache/2
Access-Control-Allow-Origin: https://foo.example
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
Content-Type: text/plain

[Some XML payload]

十二、关于HTTP缓存

HTTP 缓存存储与请求关联的响应,并将存储的响应复用于后续请求

HTTP缓存的两种类型:私有缓存和共享缓存。

是否使用缓存可以使用Cache-Control头信息进行控制,如: Cache-Control: no-store 表示不使用缓存。

注意:如果值为no-cache并不是阻止响应的缓存,而是表明不能在没有重新验证的情况之下使用缓存内容

私有缓存:

私有缓存是绑定到特定客户端的缓存——通常是浏览器缓存。由于存储的响应不与其他客户端共享,因此私有缓存可以存储该用户的个性化响应

如果响应包含个性化内容并且你只想将响应存储在私有缓存中,则必须指定 private 指令

Cache-Control: private

如果响应具有 Authorization 标头,则不能将其存储在私有缓存, 触发Cache-Control: public

共享缓存

共享缓存位于客户端和服务器之间,可以存储能在用户之间共享的响应。共享缓存可以进一步细分为代理缓存托管缓存

  • 代理缓存: 除了访问控制的功能外,一些代理还实现了缓存以减少网络流量。这通常不由服务开发人员管理,因此必须由恰当的 HTTP 标头等控制。

随着 HTTPS 变得越来越普遍,客户端/服务器通信变得加密,在许多情况下,路径中的代理缓存只能传输响应而不能充当缓存。因此,在这种情况下,无需担心甚至无法看到响应的过时代理缓存的实现

  • 托管缓存: 托管缓存由服务开发人员明确部署,以降低源服务器负载并有效地交付内容。示例包括反向代理、CDN 和 service worker 与缓存 API 的组合

启发式缓存

HTTP 旨在尽可能多地缓存,因此即使没有给出 Cache-Control,如果满足某些条件,响应也会被存储和重用。这称为启发式缓存

报文示例:

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2021 22:22:22 GMT
<!doctype html>

该响应表明,响应的内容实是1年前的缓存内容。

与启发式缓存相关的头信息:

  • max-age 这是内容保鲜的最大时间, 超过保险则不能在用缓存。

  • age age 是自响应生成以来经过的时间

  • Expires 过期时间

  • ETag 资源标记,当资源更新则ETag会改变

  • If-Modified-Since服务器只在所请求的资源在给定的日期时间之后对内容进行过修改的情况下才会将资源返回,状态码为200。如果请求的资源从那时起未经修改,那么返回一个不带有消息主体的304响应。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值