最近写一个android上的东西,要用到http代理的一些东西,包括封装解析各种http request和response以及多连接并发管理各种麻烦的东西。虽然自己也能写,但感觉是在重复的发明轮子,不如拿一些现成的东西来用,而且更快更成熟。所以选择了Webscareb,打算把里面的http协议栈相关的东西裁减出来供自己使用,这就避免不了源码的阅读。
但在网上搜了搜发现没有什么和这方面有关的资料,所以自己打算写几篇博客既能方便后来人,也能记录一下自己的学习旅程。
首先源码包我下载的是个比较旧的版本的,地址如下http://sourceforge.net/projects/owasp/files/WebScarab/,下载的是20070504-1631版本。
一大堆乱七八糟的包,通过我敏锐的嗅觉,找到了里面的httpclient包,感觉里面就是我需要的东西。
然后发现一个关键的接口:
/** * * @author rdawes */ public interface HTTPClient { Response fetchResponse(Request request) throws IOException; }
一个http客户端就是一个实现这么一个接口的东西:接收一个请求,返回一个响应。如此定义言简意赅易于理解。
然后我找到实现这个接口的一个类,也在这个包下,URLFetcher.java,大概600行,看的云里雾里的,所以打算先弄懂什么是Response和Resquest
在Model包里找到了这两个类,均继承自Message类。
Message这个类是个干什么的呢?我找到了一段注释:
Message is a class that is used to represent the bulk of an HTTP message, namely
* the headers, and (possibly null) body. Messages should not be instantiated
* directly, but should rather be created by a derived class, namely Request or
* Response.
大概就是说message代表一个http消息,也就是一个消息头+内容这样一个逻辑体,但在具体应用中应该实例化成resquest或者response
那么自然而然就想到这么几个问题:
1、如何实例化这个message,如何往里填充内容
2、这些消息和内容是怎么存在里面的。
3、这个message和外部能进行什么交互?换句话说我一个外部类使用这个message对象能干什么。
问题1:
message类有两个方法可以往其中填充数据:
public void read(InputStream is) throws IOException和
public void parse(StringBuffer buffer) throws ParseException
前者使用一个输入流而后者使用一个StringBuffer
问题2:
数据的存储分为消息头的存储和后面内容的存储,前者不能为空而后者可以为空。
消息头存储在一个NamedValue对象数组中,从名字也可以看出这是一个key-value结构,数组中每一个元素代表http头的一行。
内容的存储采用两个方式:
InputStream _contentStream 和ByteArrayOutputStream _content
数据的解析机制是这样的:
如果直接从InputStream中读取数据,首先读到的自然是Http头,存放在NamedValue数组中。头部读完后将此输入流赋值给成员变量_contentStream,此时_contentStream就代表了内容流。
如果从StringBuffer中读取数据,首先读Http头,同样存放在NamedValue中,然后实例化_content对象,并将剩余的内容写到_content中。
值得注意的是,如果在_contentStream有效的情况下调用flushContentStream()会将_contentStream里剩余的内容写入_content。
问题3:
这个类怎么用?
首先类定义了一组对Header的操作,比如AddHeader,SetHeader,DeleteHeader可以方便的对http头进行操作。
其次可以定义了方法可以取出内容部分(当然也可以取出Header部分)。
第三重载了tostring方法,可以得到一个完整的http包的字符串。
同时还有flushContent的方法,可以将内容全部冲刷到一个指定流。
当然最重要的是可以传入一个流或者一个StringBuffer,得到这个可以进行操作的对象。
待续。。。。。。。。。