现在的位置: 首页 > 综合 > 正文

webkit学习笔记七(Parser模块前篇)

2013年02月04日 ⁄ 综合 ⁄ 共 2333字 ⁄ 字号 评论关闭

前两节把Loader数据加载模块介绍完了,那有了数据以后就可以开始解析了,但在介绍parser模块之前,需要知道数据从curl怎么过来的,因此,本篇先介绍一下ResourceHandleManager.cpp里下面这几个函数:

 

headerCallback

writeCallback
readCallback

 

顾名思义,这三个函数是http请求发出以后的回调函数(为了实现异步操作),分别为写回调、http头回调、读回调, 大家去翻代码会发现在ResourceHandleManagerinitializeHandle函数里会调用以下函数,把这几个回调注册到libcurl里:

curl_easy_setopt(d->m_handle, CURLOPT_HEADERFUNCTION, headerCallback);

curl_easy_setopt(d->m_handle, CURLOPT_WRITEFUNCTION, writeCallback);   

 

curl_easy_setopt(d->m_handle, CURLOPT_READFUNCTION, readCallback);

重点先讲一下readCallback函数,它有点特殊,它是在ResourceHandleManagersetupPOST里函数里设置的,为什么呢?

下面解说之前,读者先要了解http协议的GetPost才行,这是必须滴。因为一般请求URL地址,都只是Get请求,请求发出去后,只要接收http数据显示就行了。并不需要再发送啥数据了。

只有当Post(上传)一个文件或者提交Form表单的Post数据时,才需要读的回调, 读回调被调用的时机是: socketconnect建立成功后,先发送的是post请求的http头部数据,再发送Body的数据,也就是说readCallback是用来发送body数据的。能理解吗?

下面分别列举一下GetPost的数据(我比较喜欢举例子,有例子更形象也容易理解):

 

Get

GET /books/?name=maxxiang HTTP/1.1

Host: www.qq.com

User-Agent: QQBrowser/1.3 (MTK 6235; U; MTK 1.3; ch-china; rv:1.7.6)

Connection: Keep-Alive

 

POST

POST / HTTP/1.1

Host: www.qq.com

User-Agent: QQBrowser/1.3 (MTK 6235; U; MTK 1.3; ch-china; rv:1.7.6)

Content-Type: application/x-www-form-urlencoded

Content-Length: 29

Connection: Keep-Alive

     (此处空一行)

name=maxxiang&bookname=webkit

 

注意: POSThttp头和Body部分,中间要有2”\r\n”来区分。没记错的话应该是RFC
2616规定的。

 

 

下面来分别跟踪一下代码:

 

1)       headerCallback

图片

从上面的函数调用栈能看出,源头就是Loader章节讲到的downloadTimerCallback函数,它是读取libcurl数据的总控制函数。

Curl库的Curl_client_write函数分别把http头,按”\r\n”切隔分多次调用headerCallback传递给Loader,每次只传一个http字段,这样的做法好处是,curl需要自已解析并保存http头部字段的数据值,同时,也方便了webkit的处理,因为webkit也是需要处理这些数据的,它需要把http头部字段都setm_response里,后面用得着。

 

2)       writeCallback

图片

发现writeCallback的函数调用栈比headerCallback深了一些,是因为html body的数据是可以做压缩的,而curl发现http头部标识的是gzip压缩的数据,会先解压后,再传给webkitwriteCallback函数。

         writeCallback里,首先会判断Http 返回Code,
200
表示成功等。

    if (CURLE_OK == err && httpCode >= 300 && httpCode < 400)

        return totalSize;

    if (d->client())

        d->client()->didReceiveData(job, static_cast<char*>(ptr), totalSize, 0);

         可以看到,httpCode判断了300—400之间,如果属于这个区间,就直接返回了,为什么呢,

         这是因为300-400之间的代码,都是需要再处理的或再跳转请求的。

举例如下(目前有用到好像只有是300-307,具体可以去查看RFC规范,这里仅举两个例子):

如果301,302都表示跳转,就不用去解析body部分了,直接跳转。

         如果303表示请求是 POST,那么就要转为调用 GET再请求才能取到正确的数据。

 

3)       readCallback

readCallback里,直接调用的m_formDataStream.read(ptr, size, nmemb)函数来上传。

FormDataStream类可以重点看一下,它的read函数实现了上传文件和上传Form表单(httpbody)的两个分支流程。

 

最近感冒了,头有点晕晕,今晚先写这些,Parser模块这道主菜明晚再做笔记。

抱歉!评论已关闭.