上一篇大概的介绍了一个HTTP请求的全过程。这篇我们来具体看下HTTP报文的构成,这对Android的网络请求开发及调试有着重要作用。
请求和响应报文,这个我们可以通过抓包工具Fiddler等查看。它们实际是由请求方法、请求 URI、协议版本、可选的请求首部字段 和内容实体构成的。照例放一个截图(cr 图解HTTP),红线以上是请求报文,红线下是响应报文。
URI和版本就是请求指向的位置和HTTP协议的版本,下面着重介绍一下方法和首部字段。
1、请求方法
请求方法就是上一篇提到的GET、POST几个常用的。需要划线的是,GET和POST的区别。
GET方法表示从指定的资源请求数据,查询字符串(名称/值对)是在 GET 请求的 URL 中发送的。而POST方法表示向指定的资源提交数据,查询字符串(名称/值对)是在 POST 请求的 HTTP 消息主体中发送的。举例:
GET方法请求的URL:/test/getPeople?name1=value1&name2=value2
POST方法请求的报文:/test/getPeople HTTP/1.1
Host: www.example.com
name1=value1&name2=value2
2、HTTP首部
下图是一个请求报文的首部和响应报文的首部。
HTTP首部是构成HTTP报文的重要要素,它为浏览器和服务器提供了报文主体大小、所使用的 语言、认证信息等内容。开发也可以在这里添加各种附加信息来保证请求正常获取。
首部字段的格式为 :
首部字段名:字段值
如Content-Type: text/htm。也可以多个值如Keep-Alive: timeout=15, max=100。
首部字段根据实际用途被分为四种类型:
a.通用首部字段:请求报文和响应报文都会使用的首部
b.请求首部字段:从客户端向服务端发送请求报文时使用的首部,补充了客户端信息,优先级等附加内容。
c.响应首部字段:从服务端向客户端返回响应报文时使用的首部,补充了响应的附加内容。
d.实体首部字段:针对请求报文和响应报文的实体部分使用的首部。补充了资源内容、更新时间等与实体有关的信息
HTTP/1.1 通用首部字段:
HTTP/1.1 请求首部字段:
HTTP/1.1 响应首部字段:
HTTP/1.1 实体首部字段:
此外,还有一些非HTTP1.1首部字段,如Cookie、Set-Cookie、Content-Disposition 等。着重几个介绍一下。
(1)Date :表明创建 HTTP 报文的日期和时间 例如Date: Tue, 03 Jul 2012 04:40:59 GM
(2)Transfer-Encoding:规定了传输报文主体时采用的编码方式 例如Transfer-Encoding: chunked
(3)Warning:告知用户一些与缓存相关的问题的警告。格式为Warning: [警告码][警告的主机:端口号]“[警告内容]”([日期时间])。最后的日期时间部分可省略。例如 Warning:110 Response is stale(表示响应已过期)
(4)Accept:请求首部字段。用来通知服务器,客户端能够处理的媒体类型及媒体类型的相对优先级。
例如 Accept: text/plain;q=0.3,text/html
优先级权重值 q 的范围是 0~1(可精确到小数点 后 3 位),且 1 为最大值。不指定权重 q 值时,默认权重为 q=1.0。当服务器提供多种内容时,将会首先返回权重值最高的媒体类型。上面的例子表示希望服务器在有html格式的情况下优先返回html格式的,如果没有text格式的也可以。
(5)Accept-Charset:请求首部字段。用来通知服务器,客户端支持的字符集及 字符集的相对优先顺序。格式与Accept一致。
例如 Accept-Charset: iso-8859-5, unicode-1-1;q=0.8
(6)Accept-Encoding:请求首部字段。用来通知服务器,客户端支持的内容编码。
例如 Accept-Encoding: gzip, deflate(表示报文主体可压缩)
这里也可使用星号(*)作为通配符,表示可以选用任意的编码格式。备注一下几个编码的含义:
gzip 由文件压缩程序 gzip(GNU zip)生成的编码格式 (RFC1952),采用 Lempel-Ziv 算法(LZ77)及 32 位循环冗余校验(Cyclic Redundancy Check,通称 CRC)。
compress 由 UNIX 文件压缩程序 compress 生成的编码格式,采用 LempelZiv-Welch 算法(LZW)。
deflate 组合使用 zlib 格式(RFC1950)及由 deflate 压缩算法 (RFC1951)生成的编码格式。
identity不执行压缩或不会变化的默认编码格式。
(7)Accept-Language:请求首部字段。用来通知服务器,客户端支持的语言集(中文或英文)
例如 Accept-Language: zh-cn,zh;q=0.7,en-us,en;q=0.3
(8)Authorization:请求首部字段。用来通知服务器,客户端的认证信息。
例如 Authorization: Basic dWVub3NlbjpwYXNzd29yZA==
这里要讲一下HTTP使用的认证方式,
所谓认证,就是服务器判断访问客户端的身份以采取之后动作。HTTP使用的认证有BASIC认证(基本认证)、DIGEST 认证(摘要认证)、 SSL 客户端认证以及 FormBase 认证(基于表单认证)等。
先放一张图(cr 图解HTTP)
这是BASIC认证的图解,过程大概是客户端发送请求——》服务器返回状态码——》客户端发送编码后的用户信息——》服务器认证并返回结果。
BASIC认证没有加密和清除,DIGEST 则是通过质询码增加了安全性,SSL则放弃使用用户名和密码,采用证书分发及安装来确定用户身份,这样就避免密码被盗使得第三者冒充。最多使用的还是表单认证。表单认证的过程大致如图:
Javaweb的入门学习就有包含Cookie和Session(会话),这属于HTTP补充功能,因为协议层面上用户状态无法保存,所以使用了Cookie来管理Session。Android上我们也可以通过添加首部字段实现服务器和客户端在同一个Session中通信,代码如下
URL url = new URL(requrl);
HttpURLConnection con= (HttpURLConnection) url.openConnection();
// 取得sessionid.
String cookieval = con.getHeaderField("set-cookie");
String sessionid;
if(cookieval != null) {
sessionid = cookieval.substring(0, cookieval.indexOf(";"));
}
if(sessionid != null) {
con.setRequestProperty("cookie", sessionid);
}
(9)Host:请求首部字段。这个首部在请求报文中不可缺少,用于告知服务器客户端所处的互联网主机名和端口号。
(10)If-Match:请求首部字段。 If-xxx 这种样式的请求首部字段,都可称为条件请求。服务器接 收到附带条件的请求后,只有判断指定条件为真时,才会执行请求。
例如 If-Match: "123456"(表示只有当 If-Match 的字段值跟 ETag(资源关联值) 值匹配一致时,服务器才会执行请求)
(11)Range:c对于只需获取部分资源的范围请求,包含首部字段 Range 即可告知服 务器资源的指定范围。
例如 Range: bytes=5001-10000 (请求获取从第 5001 字节至第 10000 字节的资源)
(12)User-Agent:请求首部字段。表示浏览器的种类。
例如 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/2010010
(12)Server:响应首部字段。表示服务器上安装的 HTTP 服务器应用程序的信息。
例如 Server: Apache/2.2.17 (Unix)
(13)Age:响应首部字段。告知客户端,源服务器在多久前创建了响应。字段值的单位为秒。
(14)ETag:响应首部字段。告知客户端实体标识。它是一种可将资源以字符串形式做唯一性标识的方式。服务器会为每份资源分配对应的 ETag 值。当资源更新时,ETag 值也会同时更新。
(15)Content-Encoding:实体首部字段。告知客户端服务器对实体的主体部分选用的内容编码方式(在不丢失实体信息的前提下所进行的压缩)例如 Content-Encoding: gzip
(16)Content-Length:实体首部字段。表明了实体主体部分的大小。
(17)Content-Location:实体首部字段。表示报文主体返回资源对应的 URI。
(18)Content-MD5:实体首部字段。首部字段 Content-MD5 是一串由 MD5 算法生成的值,其目的在于检查报文主体在传输过程中是否保持完整,以及确认传输到达。操作是对报文主体执行 MD5 算法获得128 位二进制数,再通过 Base64 编码,最后将结果写入 Content-MD5 字段值。
(19)Content-Type:实体首部字段。表示实体主体内对象的媒体类型,和请求里的Accept格式一致。
例如 Content-Type: text/html; charset=UTF-8
(20)Last-Modified:实体首部字段。表示资源最终修改的时间。例如 Last-Modified: Wed, 23 May 2012 09:59:55 GMT
以上是常用首部字段,当然还有其他的字段,如上面认证提到的Set-Cookie、Cookie等,这里不再介绍。
另外, 根据RFC(Request for Comment Internet的正式标准文档),HTTP首部字段是不区分大小写的。
总结:
HTTP报文是用于HTTP协议的交互信息,。请求端(客户端)的HTTP 报文叫做请求报文,响应端(服务器端)的叫做响应报文。 报文又有报文首部和报文主体组成,其中,指定报文首部字段值,能够使请求更准备的得到想要获得的数据,了解这些,对我们进行网络请求调试,排查缺陷大有好处。