HTTP请求方法
HTTP请求由三部分组成,分别是:请求行(状态行)、请求头、请求正文。请求的请求行由请求方法、请求URI、协议版本组成,响应的状态行为协议及版本、响应状态码、响应的文本描述。
// 请求行
GET /index.html HTTP/1.1
Host: hacker.jp
Cookie:sid=1342077140226742
// 状态行
HTTP/1.1 200 ok
Date: thu, 12 Jul 2012 07:12:20 GMT
Server: Apache
常见的HTTP请求方法如下:
- GET:请求指定页面信息,返回实体主体
- HEAD:类似于get请求,只不过返回的响应没有具体的内容,只有报头
- POST:提交数据进行处理,数据被包在请求体中。
- PUT:提交数据取代资源内容。
- DELETE:请求删除某些资源。
POST的常见编码方式
HTTP协议规定POST提交的数据必须放在消息主体中,但协议并没有规定数据必须使用什么编码方式,实际上开发者可以自己决定消息主体的格式。服务器通常是根据请求头中的Content-Type
字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。
application/x-www-form-urlencoded
这是最常见的POST提交数据的方式,浏览器原生的form表单,如果不设置enctype
属性,那么最终就会以application/x-www-form-urlencoded
方式提交数据,提交的数据按照key1=val1&key2=val2
的方式进行编码,key和val都进行了URL转码,我们使用Ajax提交数据时,默认也是使用这种方式。
xhr.open("POST","http://www.example.com",true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
multipart/form-data
这是常用来提交文件的编码方式,我们使用表单来上传文件时,必须让form的enctype=multipart/form-data
,上面提到的这两种方式都是浏览器原生支持的。
xhr.open("POST","http://www.example.com",true);
xhr.setRequestHeader("Content-Type", "multipart/form-data");
application/json
现在越来越多的请求都将Content-Type:application/json
,用来告诉浏览器消息主体是序列化的JSON字符串,除了低版本的IE之外的各大浏览器都原生支持JOSN.stringify,服务器端也都用处理JSON的
xhr.open("POST","http://www.example.com",true);
xhr.setRequestHeader("Content-Type", "application/json");
text/xml
它是一种使用HTTP作为传输协议,XML作为编码方式的远程调用规范,它的使用也很广泛,能很好的支持已有的XML-RPC服务,不过,XML结构还是过于臃肿,一般场景使用JSON会更灵活方便。
xhr.open("POST","http://www.example.com",true);
xhr.setRequestHeader("Content-Type", "text/xml");
HTTP状态码
以下是常见的状态码:
- 100:初始请求已经接受,客户端应该继续发生请求的其余部分,这个临时响应是用来通知客户端它的部分请求已被服务器接受且未被拒绝,如果请求完成,忽略这个响应,服务器必须在请求完成后向客户端发送一个最终响应。
- 200:请求成功
- 204:表示服务器成功处理请求,其返回的响应不含有实体的主体部分,204没有响应体,在响应头后的第一个空行结束。
- 206:客户端发送了带有Range头的GET请求,服务器处理部分GET请求,类似迅雷这种HTTP下载工具使用此类响应实现断点续传或者将一个大的文档分解为多个下载段同时下载。该请求必须包含Content-Range头信息来指示希望得到的内容范围。
- 301:永久重定向,请求的资源已经永久移动到新位置,新的资源URI在响应头中的location字段中。如果这不是一个GET或者HEAD请求,浏览器禁止自动进行重定向。
- 302:临时重定向,如果用户把URI保存成书签,302不会像301那样去更新书签。并且除非在Cache-Control或Expires中进行指定,浏览器不会缓存该响应。
- 303:303和302有着相同的功能,不同的是303明确要求客户端采用GET方法获取资源。
- 304:服务器资源未改变,可直接使用客户端未过期的缓存。
- 400:语义有错误,当前请求无法被服务器理解。
- 401:当前请求需要用户验证,该响应头必须包含被请求资源的www-Authenticate信息头用以询问用户信息。客户端可以重新提交一个包含authenticate头信息的请求。如果当前请求已经包含了认证信息,401表示服务器验证已拒绝了那些证书。
- 403:资源不可用,服务器拒绝客户端的请求,通常由于服务器上文件或目录的权限所致
- 404:资源不存在。
- 500:服务器错误
- 502:服务器作为网关或者代理时,为了完成请求访问下一个服务器,当该服务器返回了非法的应答。
- 503:服务器由于维护或者负载过重未能应答。
持久连接
在HTTP1.0中默认是短连接,在HTTP1.1中所有的连接都是Keep-alive的长连接。在HTTP1.0中,一个事务就是一个TCP连接,在一个请求结束后,TCP连接关闭,后面的HTTP请求将打开新的TCP连接。HTTP1.1允许HTTP在事务处理结束以后将TCP连接保持在打开状态,后面的HTTP请求依然可以通过这个TCP连接继续传送。
持久连接的优点如下:
- 每次建立TCP连接都要经过三次握手,持久连接只需要进行一次连接的建立。
- 由于TCP连接慢启动的特性,使用过的连接速度更快。
- 每个连接对于服务器和客户端来说都是负担。
持久连接的构建过程:客户端发出请求,请求头部包含connection:keep-alive,服务器接受请求并响应中带有字段connection:keep-alive。设置Keep-Alive:max=5,timeout=120。timeout表示持续时间,max表示还可以传输多少个HTTP请求,如果使用持久连接,一定要正确上传content-length字段描述请求体的长度,持久连接依靠content-length字段来分割HTTP请求。HTTP1.1默认是开启持久连接,只有在首部包含connection:close才会在HTTP事务结束之后关闭TCP连接。
管线化:HTTP1.1允许在持久连接上使用管道,这样就不用等待前一个请求的响应,直接在官道上发送第二个请求,在高延迟的情况下提高性能。但是管线化也有相应的缺点:
- 不是持久连接不能使用管道。
- 必须按照相同的顺序回送响应,因为报文没有标签,否则顺序就会乱掉。
- 因为可以随时关闭持久连接,所以要随时准备重发。
- 不应该使用管道化发送重复请求会有副作用的请求,比如表单提交。
Cookie
HTTP是无状态协议,HTTP协议自身不保存通信状态,因此就引入cookie来管理请求状态。在请求的响应头部中,设置Set-cookie字段,浏览器接收到cookie后存储在本地,如果设置cookie的过期时间,则cookie为会话cookie,将会存储在内存中,浏览器关闭cookie被清除,否则,cookie为持久cookie,存储在本地硬盘里。
cookie的属性如下所示:document.cookie="key=value;expiress=失效时间;path=路径;domain=域名;secure;HttpOnly"
- Domain:域,表示当前cookie所属于哪个域会子域。默认为当前请求的主域名。
- Path:cookie所属路径,只有当同域同路径下的请求才会携带上cookie。
- expiress/max-age:表示有效期,expiress是一个时间,过了该时间,cookie就会被清除。max-age指定当前cookie多长时间后失效。
- secure:表示该cookie只能用https传输,一般用于包含认证信息的cookie。
- httponly:表示此cookie必须用于http和https传输,javaScript等脚本不能操作cookie。
通信数据转发程序
代理:代理服务器的基本行为就是接收客户端发送的请求后转发给其他服务器,代理不改变请求URI,会直接发送给持有资源的源服务器。使用代理服务器的理由有:
- 利用缓存技术减少网络带宽的流量,代理转发响应时,缓存代理会预先将资源的副本保存在代理服务器上。当代理再次接受到对相同资源的请求时,就可以不从源服务器那里获取资源,而是将之前缓存的资源作为响应返回。
- 组织内部针对特定网站的访问控制。
- 以获取访问日志为主要目的。
网关:网关是转发其他服务器通信数据的服务器,网关可以使通信线路上的服务器提供非HTTP协议服务。利用网关可以提高通信的安全性。因为可以在客户端与网关之间的通信线路上加密以确保连接的安全。
隧道:隧道可按要求建立起一条与其他服务器的通信线路,届时使用SSL等加密手段进行通信,隧道的目的是确保客户端能与服务器进行安全的通信。隧道本身不会去解析HTTP请求,它会保持请求原样中转给后面的服务器。
HTTP缓存
以下是有关HTTP缓存的重要字段:
- expires:HTTP1.0响应头字段,告诉浏览器缓存的过期时间,由于返回的是服务器时间,如果时钟不同步,跨时区等问题导致客户端时间与服务器时间不一致,容易导致较大误差,HTTP1.1以后使用Cache-Control:Max-age=n秒替代。
-
Cache-Control:优先级高于expires,设置缓存多少时间后过期,其值可以为以下:
public:客户端和代理服务器都可缓存 private:只能被客户端缓存。 no-cache:响应消息不能缓存,使用协商缓存来验证缓存数据 no-store:响应消息不能缓存,强制缓存和协商缓存都不能使用 max-age:缓存的过期时间
- Last-Modified/If-Modified-Since:响应头/请求头字段,需要配合Cache-Control使用,当资源过期时,发现有Last-Modified声明,则再次请求时请求头会携带If-Modified-Since,表示请求时间,服务器接收到请求后,将Last-Modified字段和If-Modified-Since字段进行对比,若资源未修改,则返回304,告诉浏览器继续使用本地缓存。
- Etag/If-None-Match:响应头/请求头字段,需要配合Cache-Control使用,当资源过期后,发现有Etag声明,再次请求时会携带上If-None-Match字段(上次请求的Etag),服务器接受到请求后,将Etag和If-None-Match进行对比,若资源未修改,则返回304,告诉浏览器继续使用本地缓存。
Etag和Last-Modified的区别:
1:Last-Modified的单位是s,所以对于1s以内的修改是不会发生变化。
2:对文件只是打开后保存,没有做内容上的修改,Last-Modified也会变化,Etag不会。
缓存流程:在客户端第一次请求时,服务器返回一个缓存时间,在该缓存时间内,执行强制缓存(直接使用本地缓存,不再发送请求),缓存过期后,执行协商缓存,请求会携带上If-None-Match/If-Modified-Since字段,服务器会判断相应字段,如果服务器资源没有更新,返回304状态码,告诉浏览器继续使用本地缓存,否者,服务器返回200状态码和更新后的资源。
浏览器刷新行为的区别:url+enter或a标签是可以使用本地缓存(强制缓存),F5刷新时,浏览器请求头Cache-Control:max-age=0,采用协商缓存机制,Ctrl+F5是不使用任何缓存,浏览器请求头Cache-controle:no-cache,并且没有If-None-Match或If-Modified-Since等字段,服务器只能返回最新资源。
HTTP首部
connection
connection的主要作用:控制不再转发的首部字段,和管理持久连接。当前请求字段connection的值为首部字段的列表(如connection:keep-alive,upgrade)时,代理服务器在接收到请求后,会将请求中的这些首部字段删除后,再转发给源服务器。
HTTP1.1版本默认的连接都是持久连接,当想明确断开连接时,需要指定connection:close。HTTP1.0版本默认的连接都是非持久连接,需要使用持久连接,则需要指定connection:keep-alive。
其他常用首部字段
- Date:表明HTTP请求的时间
- Pragma:指定pragma:no-cache,要求中间服务器不缓存资源,是HTTP1.0的字段,为了保证兼容性,一般需要指定Cache-Control:no-cache和Pragma:no-cahce。
- Accept:通知服务器可处理的媒体类型及相对优先级。其值为Accept:text/html,application/xhtml+xml,image/png;q=0.9,q=0.8。
- Authorization:用来告知服务器,用户代理的认证信息。
- Location:配合3XX的重定向状态码,告知浏览器新资源所在的URI。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。