深入理解HTTP协议

HTTP(Hyper Text Transfer Protocol) 超文本传输协议,是基于应用层(TCP/IP参考模型)的通信规范;是从Web服务器传输超文本到客户端的传输协议,无状态的传输协议;不仅能够保证正确、快速、高效的传输超文本文档,而且可以确定资源加载顺序等;在Web开发中,页面缓存控制、数据传递、文档语言参数设定等等,都离不开HTTP协议。HTTP协议是整个Web应用的基础,深入理解HTTP协议,是每个PHP开发工程师必须掌握的知识。

1. 引子:

我们访问一个网页,经历了三个步骤: 步骤1. 定位到网页所在服务器;步骤2. 按照一定格式传输到浏览器;步骤3.数据通过浏览器解析展示出来。

这三步流程分别应用到的主要技术:技术1. URL/DNS;技术2. HTTP协议;技术3. HTML/渲染。技术1和3暂时按下不表,步骤2中涉及的HTTP协议,如何构造而成?

我们看一下实例:
code 1:

➜  ~ curl -v https://www.baidu.com
* Rebuilt URL to: https://www.baidu.com/
*   Trying 119.75.216.20...
* TCP_NODELAY set
* Connected to www.baidu.com (119.75.216.20) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: baidu.com
* Server certificate: Symantec Class 3 Secure Server CA - G4
* Server certificate: VeriSign Class 3 Public Primary Certification Authority - G5
> GET / HTTP/1.1
> Host: www.baidu.com
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
< Connection: Keep-Alive
< Content-Length: 2443
< Content-Type: text/html
< Date: Fri, 01 Sep 2017 02:22:25 GMT
< Etag: "588603eb-98b"
< Last-Modified: Mon, 23 Jan 2017 13:23:55 GMT
< Pragma: no-cache
< Server: bfe/1.0.8.18
< Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
<
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc>这里是百度首页的正文</body> </html>
* Connection #0 to host www.baidu.com left intact
➜  ~

我们使用curl命令,输出请求百度首页的完整文档,根据每行前缀,可以分为四部分:
1. * 开头的行,状态行,本文不做详细介绍(其实小编也还没有弄清楚~~~,后续研究)
2. > 开头的行,是请求报文,常说的请求头
3. < 开头的行,是响应报文,常说的响应头
4. 没有前缀的行,line 28~29,是正文部分,要渲染到浏览器中的部分

在这个实例中,请求头、响应头格式内容,包括换行,还有文档具体内容,构成了HTTP协议。可以说,HTTP协议就是传输这些内容格式的规范。

现在我们对HTTP协议应该有了一个大致的概念了吧?具体的构成以及参数,我们下面细说。

2. HTTP 协议详解

HTTP 在TCP/IP参考模型中,位于应用层,通常承载于TCP协议之上。如果承载于TLS/SSL之上,就是HTTPS了。HTTP端口默认80,也会使用8080/8000端口;HTTPS端口443。HTTP 协议是以 ASCII 码传输。

2.1 HTTP 协议的特征:

  • HTTP 协议简单,请求一个网页时,只需发送请求方法(GET/POST/...)和资源路径(URI)。
  • HTTP 是无状态协议,本身对事务处理没有记忆能力,但是有专门的技术为HTTP请求提供会话能力:Cookie/Session
  • HTTP 采用问答式交互模型,每次连接只处理一个请求
  • HTTP 是标准的C/S模型
  • HTTP 允许传递数据对象类型丰富,由报头Content-Type标识

2.2 HTTP 协议由请求和响应两部分构成

  • 请求,又由3部分组成:请求行,消息报头,请求正文
  • 响应,也有3部分组成:状态行,消息报头,响应正文

2.3 HTTP请求工作流程

  • Client(通指Browser) 与 Web Server 建立连接
  • Client 发送请求,包括请求行、消息报头、请求正文,示例:GET / HTTP/1.1rnHost: www.baidu.comrn...
  • Server 发送响应,包括状态行、消息报头、响应正文,示例:HTTP/1.1 200 OKrnAccept-Ranges: bytesrn...
  • Client 展示用户数据,Client 与 Server 断开连接

2.4 HTTP 连接详解

在发送HTTP请求头之前,Client 要和 Server 建立连接;连接是传输层的实际环流,建立在两个相互通信的应用程序之间。

2.5 HTTP 请求详解

2.5.1.请求行
格式:Method URI HTTP-Version CRLF,示例:GET / HTTP/1.1rn
参数说明:

参数说明
Method 请求方法,下面详解
URI URL的Path部分,资源标识符
HTTP-Version 请求HTTP协议版本,目前常用是HTTP/1.1 版本,最新是 HTTP/2.0 版本
CRLF CRLF是Carriage-Return Line-Feed的缩写,意思是回车换行,就是回车(CR, ASCII 13, r) 换行(LF, ASCII 10, n)

2.5.2.请求方法
即我们常用到的GET、POST等等,如下表详解

方法说明
GET 请求读取资源;GET操作是安全的。所谓安全是指不管进行多少次操作,资源的状态都不会改变。
POST 一般用来想服务器提交数据,会创建新的数据,改变数据种类等资源;
POST 提交的数据必须放在消息主体(entity-body)
POST操作既不是安全的,也不是幂等的,如POST重复/提交问题。
与PUT相比,POST 是作用在一个集合资源之上的(/uri)
HEAD 用来描述同样情况下的GET请求应该返回的响应消息报文,不应包含响应的实体,即不返回响应的正文。
在下载一个大文件前,使用HEAD方法获取文件大小等信息,再决定是否需要下载,节约带宽资源
使用CURL命令演示:
curl --head -X HEAD https://dldir1.qq.com/music/clntupate/mac/QQMusicMac_Mgr.dmg
PUT PUT请求是向服务器端发送数据的,用来修改数据,无论PUT多少次,结果相同。是等幂操作。
与POST相比,PUT操作是作用在一个具体资源之上的(/uri/xxx)
DELETE 请求服务器删除资源,是等幂操作
TRACE 请求服务器返回收到请求信息
该方法使得服务器原样返回任何客户端请求的内容,甚至包括路由中的代理服务器信息;
攻击者可以通过TRACE方法进行XSS/XST攻击,盗取会话Cookie、用户账户,模拟其他用户信息,篡改网页等;
Web服务器要关闭Trace方法,使用如下命令来查看服务器是否关闭了Trace方法:
curl --head -X TRACE https://dldir1.qq.com/music/clntupate/mac/QQMusicMac_Mgr.dmg
CONNECT 保留备用
OPTIONS OPTIONS 是HTTP/1.1 协议中定义的方法
通过该方法,客户端在发起具体请求资源之前,获取服务器支持的HTTP请求方法,黑客常用;
检查服务器性能,在AJAX跨域请求中,需要向第三方资源发送 OPTIONS请求头,以判断实际发送的请求是否安全

注意:安全和幂等的意义在于:当操作没有达到预期的目标时,我们可以不停的重试,而不会对资源产生副作用。从这个意义上说,POST操作往往是有害的,但很多时候我们还是不得不使用它。

POST PUT 创建资源时区别

创建操作可以使用POST,也可以使用PUT,如果URL可以在客户端确定,那么就使用PUT,如果是在服务端确定,那么就使用POST
比如说很多资源使用数据库自增主键作为标识信息,而创建的资源的标识信息只能由服务端提供,这个时候就必须使用POST。

 

2.5.3.请求正文
在Post/Put 请求中,需要传递数据到服务器,传递的数据就是请求正文部分,和报文部分以空行分隔。如下实例:

code 2:

➜  ~ curl -v --data-urlencode "name=kevhu.com" "http://127.0.0.1:8080" --trace-ascii /dev/stdout
Warning: --trace-ascii overrides an earlier trace/verbose option
== Info: Rebuilt URL to: http://127.0.0.1:8080/
== Info:   Trying 127.0.0.1...
== Info: TCP_NODELAY set
== Info: Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
=> Send header, 148 bytes (0x94)
0000: POST / HTTP/1.1
0011: Host: 127.0.0.1:8080
0027: User-Agent: curl/7.54.0
0040: Accept: */*
004d: Content-Length: 14
0061: Content-Type: application/x-www-form-urlencoded
0092:
=> Send data, 14 bytes (0xe)
0000: name=kevhu.com
== Info: upload completely sent off: 14 out of 14 bytes
<= Recv header, 17 bytes (0x11)
0000: HTTP/1.1 200 OK
<= Recv header, 22 bytes (0x16)
0000: Host: 127.0.0.1:8080
<= Recv header, 19 bytes (0x13)
0000: Connection: close
<= Recv header, 26 bytes (0x1a)
0000: X-Powered-By: PHP/7.0.17
<= Recv header, 40 bytes (0x28)
0000: Content-type: text/html; charset=UTF-8
<= Recv header, 2 bytes (0x2)
0000:
<= Recv data, 34 bytes (0x22)
0000: Array.(.    [name] => kevhu.com.).
Array
(
    [name] => kevhu.com
)
== Info: Closing connection 0

说明:
- ==行表示连接状态;=>发送请求报文的提示;<=接收响应报文的提示;其他行表示传递报文
- line 8~13: 请求行,和请求消息报文部分
- line 14: 空行,分隔报文和请求正文
- line 16: 请求正文部分,POST 请求提交给服务器的数据

2.6 HTTP 响应详解

2.6.1 状态行
格式:HTTP-Version Status-Code Reason-Phrase CRLF
示例:HTTP/1.1 200 OK rn
参数说明:

参数说明
HTTP-Version 服务器HTTP协议的版本,目前常见是HTTP/1.1版本
Status-Code 服务器发回的响应状态码,常见200、302、404、502 等
Reason-Phrase 状态码的文本描述,如:OK、Not Allowed 等等
CRLF CRLF是Carriage-Return Line-Feed的缩写,意思是回车换行,就是回车(CR, ASCII 13, r) 换行(LF, ASCII 10, n)

2.6.2 状态码
常见有五种响应,由状态码的第一位数字标识出来:

状态码响应类型说明
1xx 指示信息 请求已接收,继续处理
2xx 成功 请求已被成功接收、接受、理解
3xx 重定向 要完成请求,必须进行进一步操作
4xx 客户端错误 请求有语法错误或请求无法实现
5xx 服务端错误 服务器未能实现合法的请求

常见HTTP Code 说明

CodePhrase说明
200 OK 客户端请求成功
400 Bad Request 客户端请求语法有误,服务器理解不了
401 Unauthorize 请求未经授权
403 Forbidden 服务器收到请求,但是拒绝提供服务,Nginx常见于文件权限配置错误时。
404 Not Found 请求资源不存在,比如错误的URL
500 Internal Server Error 服务器发生内部错误,一般是服务程序错误
502 Gate Time Out 网关cgi错误,比如请求数量超出PHP-FPM处理能力时,通过Nginx访问PHP程序,就会报该错误
503 Server Unavailable 服务器当前不能处理客户端的请求,一段时间后可能恢复正常

2.6.3 响应正文

参考code 2,来说明响应正文:

  • line 29:空行,分隔响应报头和响应正文
  • line 31:响应的正文部分

2.7 HTTP 核心消息报头详解

2.7.1 格式

  • 格式: Name: Value
  • 示例: Content-type: text/html; charset=UTF-8

2.7.2 HTTP消息报头通常分为四类:

  • 普通报头:有少数报头域,同时可以用于请求和响应消息,如缓存控制、连接控制
  • 请求报头:请求的附加信息以及客户端自身信息,如UA、Accept
  • 响应报头:服务器发回不能放到状态行的附加响应信息
  • 实体报头:定义了关于实体正文和请求所标记的资源的元信息,如:无实体正文

2.7.3 重要报头的说明

Name类型说明
Host 请求 指定请求资源的Internet主机地址和端口,必须表示请求资源的原始服务器/网关地址,通常域名形式表示。HTTP1.1版本,必须传递该报头
User-Agent 请求 客户端的身份信息,UA是辨别客户端设备的重要依据
Accept 请求 告诉服务器,客户端可以接受的文件格式。
Cookie 请求 发送Cookie信息到服务器端
Set-Cookie 响应 告诉客户端,需要设置一个Cookie;Cookie只能在客户端新增。
Cache-Control 普通 请求和响应遵循的缓存机制,互不影响
Referer 请求 访问来源地址,常用于记录访问者地址的参数
Content-Length 响应 服务器返回正文内容长度
Content-Range 响应 响应的资源范围,常用语断点续传
Accept-Encoding 请求 可以接受的编码方式

3. PHP HTTP 请求实例

实例演示HTTP 协议请求一个资源

首先准备一个Server文件,并启动一个PHP Web 服务:
code 3:

posted @ 2019-07-12 15:15  张志健  阅读(396)  评论(0编辑  收藏  举报