前言
总结一下http的一些基础知识
http报文
// 格式大部分分为:
// 起始行
// 头部
// 包体
// 注意格式中的空格、回车符、换行符
// 请求报文
<method> <request-url> <version> 请求方法 URL 协议版本
<headers> 请求头部
<entity-body> 请求包体
// 响应报文
<version> <status> <reason-phrase> 协议版本 状态码 状态码描述
<headers> 响应头部
<entity-body> 响应包体
method
请求方法包含GET、POST、PUT、DELETE等方法,常用的有GET和POST两种,这两种的区别是:
先来看一下网上的总结:
主要区别:
- 最直观的还是语义上的区别,GET是获取数据,POST是提交数据,比如一个商品地址是www.taoba.com?id=3,你把他发给朋友,别人也能看到,如果你用POST去去请求一个商品页面,url还是www.taobao.com,分享给别人是没有意义的,别人也看不到。同样,如果你用www.weibo.com?id=1&content=haha来发一条微博,这个url被别人看到了,那他直接复制url到浏览器就可以发微博了,这样很不合理。
- GET请求会将请求参数拼接到url的尾部,一些浏览器和服务器可能会对url的长度有限制,而POST请求是将参数放在请求体中的
- GET是幂等的,通俗的说是没有副作用的。POST是非幂等的,有副作用
接口中的get和post:
- 没有什么限制说GET请求就不能有body,POST请求就不可以在url上面拼参数,可以各种各样的定制,只要和服务端约定好就行
- GET可以带body,POST也可以一半参数拼在url另一半的参数放在body里,甚至可以让所有参数都放在Header里
- 太自由也很麻烦,开发人员还得讨论,很低效,所有就有了接口规范
关于安全性:
- 我们经常听说POST更安全,GET不安全,因为GET用url传输参数,容易被看到。其实从攻击的角度来说,两者都不安全,因为http协议是明文协议,不管是url、header、body都会在网络上传播,这就不是一个是否能在地址栏上看到的问题。为了避免数据被窃取,必须做到客户端和服务端的端端加密,比如业界常用的https—用SSL协议。
- 安全是一个巨大的主题,POST和GET在安全这件事上仅仅是一个小角色,单独讨论GET和POST哪个更安全意义不是很大,一般情况下,私密数据用POST+body就好
关于编码
- 常见的说法是,GET参数只能用ASCII,而POST能支持任意。其实GET和POST实际上都能用url和body。所谓编码确切的说应该是http的url和body用什么编码
- url只支持ASCII的说法源自于RFC1738, 实际上是ASCII的一个子集,使用Percent Encoding,也可以通过编码放在URL上的,尽管在浏览器上可以看到中文,但是浏览器会吧中文用字符编码+Percent Encode翻译成为真正的url
- 再讨论一下body, Content-Type会同时定义请求body的格式(application/x-www/form-urlencoded)和字符编码(utf-8)
浏览器的POST需要发送两个请求吗
- 可以这样简单的理解:如果请求体很小,那么一次性都发送给服务器,这里做一个优化,如果请求体的数据超过1KB就先发送请求头,如果校验成功了,服务器回复100-Continue,客户端再把剩下的数据发给服务器,如果请求被拒,就回复一个400之类的错误
url长度
- http协议本身并没有对URL长度做任何规定,实际的限制是由浏览器以及服务端决定的,一般某个url的长度有可能达到2000个bytes以上,就必须用body来传播数据。
小总结
- 协议都是人定的,只要客户端和服务器能够彼此认同,就可以。思路不能被规范限制死,更不要死抠RFC,
- 比如Elastic Search全文检索的search接口用get,却用body来表达查询,因为查询太复杂了,在请求体中用json编码更加舒服。
- 用POST写一个发布下单类似的接口也要考虑幂等,可能前端下单按键有bug,会造成用户一次点击发出N个请求。
状态码
常见的状态码:
- 200 OK 请求成功
- 301 Moved Permanent 请求的URL被移除了
- 304 Not Modified 条件请求进行再验证,资源未改变
- 404 Not Found 资源不存在
- 206 Partial Content 成功执行一个部分请求。这个在用于断点续创时会涉及到
Header
可以携带一些信息,通过与其他部分配合,可以实现各种强大的功能。
位于起始行和请求包体之间,以键值对的形式存在。
实体
请求发送的资源,或者响应返回的资源
Http缓存
我们发起一个请求后服务器返回资源,此时将资源的副本存储在本地,下次再对该url发起请求时,我们直接快速的从本地获取该url资源。
- 新鲜度检测:需要检测资源是否超过一定的时间,来判断缓存的资源是否和新的资源一致,在头部添加Cache-Control,时间相关的信息。
- 再验证:如果已经超过时间了,我们再次发起请求不会直接将缓存返回,而是去服务器查看资源是否改变。
- 再验证命中:如果发现对应的url资源没有改变,返回304,不再返回对应的实体。如果未命中,返回200,将改变后的资源返回。
Https
简单的说Https就是 Http + 加密 + 认证 + 完整性保护。
Https可以通过增加的SSL\TLS,支持对于通信内容的加密,以及对通信双方的身份进行验证
传统Http的缺点:
- Http使用明文传输,容易遭到窃听
- Http对于通信双方都没有进行身份验证,无法确认对方是否是伪装的客户端或者服务端
- Http对于传输内容的完整性没有确认的办法,容易在传输过程中被劫持篡改
Https的加密
- 对称秘钥加密:加密和解密使用同一把秘钥,速度快
- 非对称秘钥加密:加密和解密使用两把不同的秘钥,一把公开秘钥,一把私有秘钥。得到公开秘钥的客户端可以对传输内容加密,对方用私有秘钥可以解密,但处理速度较慢
- SSL\TLS加密:结合了前面两种加密方式的优点,首先采用非对称秘钥加密,将一个对称秘钥使用公开秘钥加密后传输给对方,对方使用私有秘钥解密,得到传输的对称秘钥,然后使用对称秘钥来进行通信。
Https的认证
使用由数字证书认证机构颁发的公开秘钥证书。服务器的运营人员可以向认证机构提出公开秘钥申请,审核后会将公开秘钥和共钥证书绑定。服务器将共钥证书下发给客户端,客户端收到证书,使用认证机构的公开密钥进行验证。
Https通信流程
- Client发起请求
- Server响应请求,并将证书发送给客户端
- Client使用认证机构的共钥认证证书,并从证书中取出Server端共钥
- Client使用共钥加密一个随机秘钥,并传到Server
- Server使用私钥解密出随机秘钥
- 通信双方使用随机秘钥作为对称秘钥进行加密解密
Android HttpURLConnection
附一篇好文:Android HttpURLConnection详解
这个作者写的不错,了解HttpURLConnection的同时还可以再熟悉一下http
总结
一篇简单的文章,简简单单的了解一下http,大致就先写这么多,以后有什么再补充吧