之前项目中用到了icap协议,成功实现了对http数据包的内容修改,增加等功能,现将一些协议中一些字段进行总结,参考了RFC3507,ok,让我们首先看一个icap报文

REQMOD  icap://127.0.0.1:1344/greasyspoon_req ICAP/1.0\r\n       
Host:127.0.0.1:1344\r\n                                     
Date:Wed, 08 May 2013 15:47:28 GMT\r\n                         
Encapsulated:req-hdr=0, null-body=336\r\n                                                      
Preview:0\r\n                                                    
Allow:204\r\n                               
\r\n                                     
GET   http://202.168.1.13/1.html HTTP/1.1\r\n                  
Host:   202.168.1.13\r\n                          
User-Agent:  Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 
Firefox/17.0\r\n                        
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n  
Accept-Language:   en-US,en;q=0.5\r\n                  
Accept-Encoding:   gzip, deflate\r\n                    
Referer:  http://202.168.1.13/support.html\r\n                    
\r\n

其中1到7行为icap头,剩下的是我们常见的http头,我们一条一条看一下:
第一行中REQMOD表示icap工作在请求模式,icap还有一种模式叫RESPMOD,意思是工作在响应模式,简单的说,请求模式主要针对http请求报文进行匹配修改增值,响应模式主要针对http响应报文进行匹配修改增值icap://127.0.0.1:1344/greasyspoon_req ICAP/1.0说的是资源url和版本号1.0,其中greasyspoon是指icap服务器的具体名称,icap服务器还有c-icap等。
hostdate这里就不详细说了
Encapsulated:req-hdr=0, null-body=336\r\n 说的是封装了http请求包,http头偏移量为0,这个请求包只有头,没有body,所以null-body=336,336是指body的偏移量;如果有请求包的body的话,例如post消息,会出现下面的情况:
Encapsulated: req-hdr=0, req-body=412,意思是头偏移长度0,bdoy偏移长度为412,通过这个可以得到http头和消息体的开始位置,总结一下,Encapsulated这个字段主要用来定位http消息的header和body。

再来看preview字段的用途,首先看一下RFC3507中对他的描述:

ICAP REQMOD or RESPMOD requests sent by the ICAP client to the ICAP server may include a "preview". This feature allows an ICAP server to see the beginning of a transaction, then decide if it wants to opt-out of the transaction early instead of receiving the remainder of the request message.   

翻译如下:icap客户端发送给服务端的REQMOD或者RESPMOD请求可能包含“preview” 字段,它能让icap服务端看到事务的最开始的一些信息,从而决定是否直接退出这个事务,而不是等到将所有的请求信息接收完毕再做判断。说白了就是预览icap封装消息body的前n个字节,来判断是否对这个消息进行处理,而不是接收完所有消息再判断。举个例子(RFC上的):

If an ICAP server wants to transcode all GIF87 files into GIF89 files, then the GIF87 files could quickly be detected by looking at the first few body bytes of the file.   翻译:如果icap服务器想要把所有gif87的文件转码成gif89文件,gif87的文件可以通过body的前几行检测出来。

这里由于我们的包里只有http header,没有http body,所以preview为0

最后Allow:204,我们先看看RFC上怎么说:
An ICAP client MAY include “Allow: 204” in its request headers,indicating that the server MAY reply to the message with a “204 NoContent” response if the object does not need modification.

If an ICAP server receives a request that does not have "Allow: 204",it MUST NOT reply with a 204. In this case, an ICAP server MUST return the entire message back to the client, even though it is identical to the message it received.

翻译:”Allow: 204”是可选的,加上这个选项表示:如果这个包不需要处理,则服务器返回”204 NoContent”给客户端,如果不加这个选项,服务器绝不会返回204,而是将整个消息返回给客户端
总结一下:这个allow:204主要是真针对不需要处理的数据包进行简单返回状态码204,从而减少了icap服务器和客户端的工作量

ok,到这里我们基本分析了icap的请求包,再来看看,icap服务器的返回包:

ICAP/1.0 200 OK\r\n 
ISTag:"GreasySpoon-1.0.8-01"\r\n                   
Host:0.0.0.0:1344\r\n                         
Encapsulated:req-hdr=0, null-body=333\r\n                 
Connection:close\r\n                          
\r\n                                     
GET http://202.168.2.34/2.html HTTP/1.1\r\n                 
Host:202.168.2.34\r\n                          
User-Agent:  Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 
Firefox/17.0\r\n                         
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n     
Accept-Language:   en-US,en;q=0.5\r\n                   
Accept-Encoding:   gzip, deflate\r\n                     
Referer:http://202.168.1.13/support.html\r\n                   
\r\n                                     

前6行为icap响应包头,下面的是修改后的http请求,可以看到GET http://202.168.2.34/1.html HTTP/1.1\r\n改成了GET http://202.168.2.34/2.html HTTP/1.1\r\n,我们成功修改了http请求。下面具体看一下响应包的各个字段:

ICAP/1.0 200 OK\r\n 说的是icap的返回状态码200,表示http请求已经被成功修改,类似于http状态码200

ISTag(ICAP Service Tag)说的是我们用的icap service的具体名称和版本号,我们这里用的是greasyspoon

hostEncapsulated不再赘述了

Connection字段和http协议的connection一样,含义是当client和server通信时对于长链接如何进行处理。在http1.1中,client和server都是默认对方支持长链接的, 如果client使用http1.1协议,但又不希望使用长链接,则需要在header中指明connection的值为close;如果server方也不想支持长链接,则在response中也需要明确说明connection的值为close.

不论request还是response的header中包含了值为close的connection,都表明当前正在使用的tcp链接在当天请求处理完毕后会被断掉。以后client再进行新的请求时就必须创建新的tcp链接了。

顺便再复习一下http报文里的各个字段的含义:

1、 Accept:告诉WEB服务器自己接受什么介质类型,/ 表示任何类型,type/* 表示该类型下的所有子类型,type/sub-type。

2、 Accept-Charset: 浏览器申明自己接收的字符集

Accept-Encoding: 浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate)

Accept-Language::浏览器申明自己接收的语言

语言跟字符集的区别:中文是语言,中文有多种字符集,比如big5,gb2312,gbk等等。

3、 Connection:请求:close(告诉WEB服务器或者代理服务器,在完成本次请求的响应后,断开连接,不要等待本次连接的后续请求了)。

keepalive(告诉WEB服务器或者代理服务器,在完成本次请求的响应后,保持连接,等待本次连接的后续请求)。

响应:close(连接已经关闭)。

keepalive(连接保持着,在等待本次连接的后续请求)。

Keep-Alive:如果浏览器请求保持连接,则该头部表明希望 WEB 服务器保持连接多长时间(秒)。例如:Keep-Alive:300

4、 Host:客户端指定自己想访问的WEB服务器的域名/IP 地址和端口号。例如:Host:rss.sina.com.cn

5、 Referer:浏览器向 WEB 服务器表明自己是从哪个 网页/URL 获得/点击 当前请求中的网址/URL。例如:Referer:http://www.sina.com/

6、 Server: WEB 服务器表明自己是什么软件及版本等信息。例如:Server:Apache/2.0.61 (Unix) 7、 User-Agent: 浏览器表明自己的身份(是哪种浏览器)。例如:User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.14) Gecko/20080404 Firefox/2、0、0、14



blog comments powered by Disqus