http 协议小记

这篇文章只是记录一些平时遇到的关于HTTP的小知识(会不断更新),主要是因为周围的同事有时候也包括我自己有时候竟然不知道HTTP一些的一些规范,感谢现成的HTTP库,帮助我们在不懂HTTP的情况下也能写出勉强work的代码。

请求和返回

对于经常使用各种库的我们来说可能不知道http协议就是一堆格式化的文本而已,如果对一个请求抓包就会发现类似下面的原始数据

POST /check_config_update HTTP/1.1
Content-Length: 382
Content-Type: application/x-www-form-urlencoded
Host: oc.umeng.com
Connection: Keep-Alive
User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.0; Nexus 5 Build/LRX21O)

content=%7B%22type%22%3A%22online_config%22

在我们做http请求的时候,http客户端(比如Apache的httpClient)会先按照http协议把一些请求信息,比如

这些东西按照一定的格式(如上,显而易见)写入到一个字节流里面,然后用socket把这个字节流发给对应的服务器,HTTP服务器(注意这里强调HTTP服务器而不是FTP服务器或者其他类型的服务器是因为只有HTTP服务器才会解析HTTP协议的请求,好像没必要强调)会 按照HTTP协议解析这个字节流。

然后呢,服务器处理完数据之后会按照HTTP协议的返回格式返回一个新的字节流,这个字节流完全接收下来就是这个样子的

HTTP/1.1 200 OK
Server: Tengine
Date: Fri, 21 Nov 2014 06:08:33 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 1573
Connection: close

{"config_update":"Yes","report_policy":6,"last_config_time":"Thu Nov 20 18:24:08 CST 2014"}

咱们的HttpClient解析这个字节流,发现返回200 同时也返回了一段数据,然后按照服务器的要求关闭链接。这样整个流程走完了。

所以,我们完全可以基于Socket按照上面的格式发送数据给HTTP服务器,自己写一个简单的http客户端。

问题来了

POST 请求比 GET 请求大吗?

已经很明显了吧,GET和POST只是方法不同,那种请求发送的数据量更大完全取决于发送的数据量,而不是取决于方法。

Content-Type: application/json;charset=utf-8 这分号分割的是什么东西

Content-Type 是HTTP协议中定义的一个key,对应一列分号分割的数组来描述内容的类型,所以在处理这个字段的时候,一定要小心点,application/json;描述了内容格式, charset=utf-8 描述了内容编码。

GET 请求的一堆参数怎么编码的?

GET /?ssid=0&from=844b&pu=sz%401320_1001%2Cta%40iphone_2_5.0_3_537&ms=1&action=getplus&merge=1&_=1416552944494&callback=jsonp1 HTTP/1.1
Host: www.baidu.com

这个GET请求原来是这样的

http://www.baidu.com/?ssid=0&from=844b&pu=sz%401320_1001%2Cta%40iphone_2_5.0_3_537&ms=1&action=getplus&merge=1&_=1416552944494&callback=jsonp1

关于GET请求其实还有一个长度限制,根据服务器不同,大概在 2kb - 8kb 之间吧,现在是否明白了HTTP请求中经常要对数据进行编码,因为http使用简单的空格和换行等等作为格式标示,不编码的话文本中的空格和换行会导致协议错误。

Cookie 是怎么传的?

Cookie: BAIDUID=1E08353734136500E06BA830A9C32616:FG=1; BAIDULOC=12954904.758807_4836196.3663444_20.47800064086914_131_1416549976069; H5LOC=1; PLUS=1

如上 Cookie就是 HTTP协议中的一个字段而已。

http 同时上传多个文件怎么做的?

这是一个非常复杂的功能,多个文件差不多编码成这样

POST /mblogDeal/addPic HTTP/1.1
Host: m.weibo.cn
Content-Length: 39651
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://m.weibo.cn
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Linux; Android 5.0; Nexus 5 Build/LRX21O) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.59 Mobile Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryutylU4bU5esdyhew
Referer: http://m.weibo.cn/mblog
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
Cookie: _T_WM=25d81768cbad12a2dd954f0a7d80a43e; gsid_CTandWM=4uLve7771hdhHaXXYoCtv7J6m9G; SUB=_2AkMjMmrva8NlrAJZnPkTy2vkbI1H-jyQbGoZAn7oJhMyCBgv7loBqSeZyTbdRgXJJi9h4sTYqdi0bWdCLg..; M_WEIBOCN_PARAMS=rl%3D1%26luicode%3D20000174

------WebKitFormBoundaryutylU4bU5esdyhew
Content-Disposition: form-data; name="type"

json
------WebKitFormBoundaryutylU4bU5esdyhew
Content-Disposition: form-data; name="pic"; filename="052C926B666B9A1FEBEC23C96B44A9ED.jpg"
Content-Type: image/jpeg

����JFIFHH��XExifMM*�i&������8Photoshop 3.08BIM8BIM%�������	�禅B~���"��	

------WebKitFormBoundaryutylU4bU5esdyhew--

上传多个文件需要添加 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryutylU4bU5esdyhew 这样的标示,multipart/form-data 表示这是一个包含很多数据的请求,boundary=----WebKitFormBoundaryutylU4bU5esdyhew 表示这些数据的分界线。如上所示,乱码部分就是图片内容,因为图片是二进制的格式无法用文本来表示。

最后附上:http://www.w3.org/Protocols/rfc2616/rfc2616.html 有兴趣自己研究去吧

nTop 21 November 2014
blog comments powered by Disqus