HTTP(Hyper Text Transfer Protocol)是一个基于TCP/IP通信协议来传递数据,包括html文件、图像、结果等,即是一个客户端和服务器端请求和应答的标准。
http无连接:限制每次连接只处理一个请求,服务端完成客户端的请求后,即断开连接。(传输速度快,减少不必要的连接,但也意味着每一次访问都要建立一次连接,效率降低)
http无状态:对于事务处理没有记忆能力。每一次请求都是独立的,不记录客户端任何行为。(优点解放服务器,但可能每次请求会传输大量重复的内容信息)
客户端/服务端模型:客户端支持web浏览器或其他任何客户端,服务器通常是apache或者iis等
简单快速
灵活:可以传输任何类型的数据
第一部分:请求行,用来说明请求类型,要访问的资源以及所使用的HTTP版本。
第二部分:请求头,紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息
从第二行起为请求头部,HOST将指出请求的目的地.User-Agent,服务器端和客户端脚本都能访问它,它是浏览器类型检测逻辑的重要基础.该信息由你的浏览器来定义,并且在每个请求中自动发送等等。
第三部分:空行,请求头部后面的空行是必须的
即使第四部分的请求数据为空,也必须有空行。
第四部分:请求体,可以添加任意的其他数据。
第一部分:状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成。
第二部分:响应,用来说明客户端要使用的一些附加信息。
第三部分:空行,消息报头后面的空行是必须的。
第四部分:响应体,服务器返回给客户端的文本信息。
可以是html、json串等信息。
HTTP1.0定义了三种请求方法:GET、POST、HEAD
HTTP1.1新增了五种请求方法:OPTIONS、PUT、DELETE、TRACE、CONNECT
序号 | 方法 | 描述 |
---|---|---|
1 | GET | GET方法用于使用给定的URI从给定服务器中检索信息,即从指定资源中请求数据。使用GET方法的请求应该只是检索数据,并且不应对数据产生其他影响。 在GET请求的URL中发送查询字符串(名称/值对)。请求体中不会包含请求数据,请求数据放在协议头中。 GET请求是可以缓存的,我们可以从浏览器历史记录中查找到GET请求,还可以把它收藏到书签中;且GET请求有长度限制幂等 |
2 | POST | 向服务器提交资源让服务器处理,比如提交表单、上传文件等,可能导致建立新的资源或者对原有资源的修改。 提交的资源放在请求体中。 POST请求永远不会被缓存,且对数据长度没有限制;我们无法从浏览器历史记录中查找到POST请求。非幂等 |
3 | HEAD | HEAD方法与GET方法相同,但没有响应体,仅传输状态行和标题部分。 主要用来检查资源或超链接的有效性或是否可以可达、检查网页是否被串改或更新,获取头信息等,特别适用在有限的速度和带宽下。 |
4 | PUT | 和post类似,html表单不支持。 PUT方法用于将数据发送到服务器以创建或更新资源,它可以用上传的内容替换目标资源中的所有当前内容。 它会将包含的元素放在所提供的URI下,如果URI指示的是当前资源,则会被改变。如果URI未指示当前资源,则服务器可以使用该URI创建资源。所以put是安全的,幂等。而post可能请求几次创建了几次资源。 |
5 | DELETE | 请求服务器删除某资源。和put都具有破坏性,可能被防火墙拦截。如果是https协议,则无需担心。幂等 |
6 | CONNECT | 用来建立到给定URI标识的服务器的隧道;它通过简单的TCP / IP隧道更改请求连接,通常实使用解码的HTTP代理来进行SSL编码的通信(HTTPS)。 就是把服务器作为跳板,去访问其他网页然后把数据返回回来,连接成功后,就可以正常的get、post了。 |
7 | OPTIONS | 获取http服务器支持的http请求方法,允许客户端查看服务器的性能,比如ajax跨域时的预检等。 |
8 | TRACE | 回显服务器收到的请求,主要用于测试或诊断。它回应收到的请求,以便客户可以看到中间服务器进行了哪些(假设任何)进度或增量。一般禁用,防止被恶意攻击或盗取信息。 |
GET方法用于使用给定的URI从给定服务器中检索信息,即从指定资源中请求数据。使用GET方法的请求应该只是检索数据,并且不应对数据产生其他影响。
在GET请求的URL中发送查询字符串(名称/值对)。请求体中一般不会包含请求数据,请求数据放在协议头中。
参数可见
GET 方法的参数是明文可见的包含在 URL 当中,所以说敏感信息不建议使用 GET 方法
数据类型只允许ASCII
GET方法的数据类型只允许是 ASCII 字符,所以 GET 方法不可以传递二进制文件
可以保存书签
因为GET 方法的参数可见,所以 GET 方法允许被保存书签
可以被缓存
GET 方法支持缓存,当本次请求允许被缓存时,会将资源存值本地 cache ,在未过期的情况下直接取本地 cache;缓存过期后视情况而定
参数会保留在浏览器历史记录
可以在浏览器的历史记录中查看到曾经搜索过的关键字信息
请求长度会受限于所使用的浏览器与服务器
不同的浏览器对于 GET 请求长度的限制也是不同的,注意这是 浏览器 / 服务器(IE、Chrome、Apache、IIS等) 对于长度的限制,而不是 HTTP 协议
HEAD方法与GET方法相同,但没有响应体,仅传输状态行和标题部分。
主要用来检查资源或超链接的有效性或是否可以可达、检查网页是否被串改或更新,获取头信息等,特别适用在有限的速度和带宽下。
以Apache tomcat为例(HttpServlet.doHead方法):
protected void doHead(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (DispatcherType.INCLUDE.equals(req.getDispatcherType())) {
doGet(req, resp);
} else {
NoBodyResponse response = new NoBodyResponse(resp);
doGet(req, response);
response.setContentLength();
}
}
可以看出:HEAD请求中调用的也是GET请求的方法。
类型 | GET | POST |
---|---|---|
点击返回/刷新按钮 | 没有影响 | 数据会重新提交 |
缓存/添加书签 | 可以 | 不可以 |
历史记录 | 有 | 没有 |
编码类型 | application/x-www-form-urlencoded | application/x-www-form-urlencoded multipart/form-data application/json text/xml 等 |
是否幂等 | 幂等 | 非幂等 |
长度限制 | http协议没有限制,但是实际浏览器或服务器有 | 理论上没有,可能会收到服务器配置或内存限制 |
数据类型限制 | 只能ASCII,非ascii都要编码传输 | 没有限制,允许二进制数据 |
安全性 | 数据全部展示在url中,不安全 | 相比get,通过request body传递数据,比较安全 |
可见性 | 可见 | 不可见 |
application/x-www-form-urlencoded是浏览器默认的编码格式
类型 | PATCH | PUT |
---|---|---|
是否幂等 | 非幂等 | 幂等 |
粒度 | 局部,最小粒度,节约网络带宽 | 所有 |
注意:比如更新一个userinfo,包含name,age,sex等多个字段,如果只修改了age,如果用put来更新,则需要把其他没有变更的也要提交到服务器,但是使用patch,则只需要提交age到服务器即可。这都是协议层面来讨论的。 put请求专注于update操作,但是与之相关的是还有这个patch请求,两者虽然都专注于update操作,但是前者put是全局而言,后者patch是局限于某一条件或者范围而言,简单的说就是两者的粒度是不同的。
HTTP 1.0 三个方法:HEAD、GET、POST 默认都属于简单请求
但是简单请求满足以下条件也可以触发Options请求
一般 HTTP1.1 中的方法请求默认都会触发预检请求
预检请求即在请求之前需要首先由浏览器自发发送Options请求的请求
1. application/x-www-form-urlencoded
这应该是最常见的 POST 提交数据的方式了。浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。
请求类似于下面这样(无关的请求头在本文中都省略掉了):
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
Content-Type 被指定为 application/x-www-form-urlencoded;提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。大部分服务端语言都对这种方式有很好的支持。
2. multipart/form-data
这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件
POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png
PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
这种方式,首先生成了一个 boundary 用于分割不同的字段。然后 Content-Type 里指明了数据是以 mutipart/form-data 来编码,每部分都是以 --boundary 开始,紧接着内容描述信息,然后是回车。可以看到content里面也是键值对的形式传给后台。和第一种的区别在于,第二种的value可以是文件file
3. application/json
很多老牌的服务器为了安全,会选择这种方式。特点是content里面存放的,标准格式的json。也就是序列化的json。
POST http://www.example.com HTTP/1.1
Content-Type: application/json; charset=utf-8
{"title":"test","sub":[1,2,3]}
4. text/xml
用得很少。