学习《apache源代码全景分析》之过滤器部分摘录

1.过滤器分为输入过滤器和输出过滤器,输入过滤器用于修改从网络读取的数据;而输出过滤器则用于修改生成并写入网络的数据。

2.对比

   

   

3.输入过滤器主要是对接收到的请求进行处理,它与我们正常思维一致的地方:

   (1) 客户端和CORE_IN过滤器之间的数据流方向与输出过滤器的数据方向相反。CORE向网络写入数据,而CORE_IN则是从网络读取数据。

   (2) 数据响应的方向也与我们想象的一致。客户端的数据被CORE_IN读取后依次经过各个过滤器最终到达核心。

   唯一不同的是请求报文的方向。请求报文的读取由“Request Processing”处发起,内容生成器仅创建一个空的缓冲区,然后将其传递到前一个过滤器,要求将其填满。由于此时缓冲区中空无一物,因此它将继续要求前一个过滤器填满。这种过程直到CORE_IN过滤器位置为止。CORE_IN向网络读取数据后,填满该缓冲区,而后依次沿过滤器链表返回。各个过滤器依次处理。

4.对一个给定的HTTP请求,该请求在各个过滤器之间的传递过程如下图:

  

5.在Apache中我们使用ap_filter_rec_t数据结构来描述一个过滤器。

struct ap_filter_rec_t
{
    const char *name;  //过滤器名称
    ap_filter_func filter_func; //过滤器对应的回调函数
    ap_init_filter_func filter_init_func; //用于在过滤处理句柄被激活之前调用
    ap_filter_type ftype; //过滤器类型
    struct ap_filter_rec_t *next; //指向下一个过滤器结构

    ap_filter_provider_t *provider; //2.2.6版本中提供provider概念
    int debug;
    unsigned int proto_flags; //标记当前过滤器使用的对应的协议
};

在Apache中,ap_filter_t是主要的对外展现的过滤器数据结构:

 

 过滤器结构的最后一个成员是ctx,用来保存过滤器的上下文信息。

6.Apache中使用过滤器包括两种:静态过滤器使用和动态过滤器使用。

7.

 

8.filter_trie_node节点分配示意图

   

9.过滤器注册

   

   由于过滤器分为输入和输出过滤器两种,因此最终结果江永两棵过滤树保存。分别是registered_input_filters和registered_output_filters表示,它们都是全局变量。

10.“face”过滤器注册流程

    

    实际真正的过滤器数据保存在“e”结点的frec结构中。

11.“facd”及“fd”过滤器注册后的结构

    

12.最终的过滤器结构

    

   所有的过滤器注册完毕,形成一个典型的过滤器树,如下图:

      

13.每个请求都会关联4个过滤器,两个输入过滤器和两个输出过滤器。

struct request_rec
{
    ......
    struct ap_filter_t *output_filters;
    struct ap_filter_t *input_filters;
    struct ap_filter_t *proto_output_filters;
    struct ap_filter_t *proto_input_filters;
    ......
};

   同时在连接记录结构conn_rec中也会看到下面的代码:

struct conn_rec
{
    ......
    struct ap_filter_t *input_filters;
    struct ap_filter_t *output_filters;
    ......
}

   每个连接会关联一个输入过滤器和一个输出过滤器。在请求创建的时候(ap_read_request函数中),请求的过滤器链表直接继承连接过滤器链表。

     

14.任何一个过滤器,最终它都要插入到山中过滤器链表中的其中之一:内容过滤器链表、协议过滤器链表、连接过滤器链表。

   (1) 内容过滤器将被天际到内容过滤器链表中,即outf = r_filters;

   (2) 协议过滤器将被添加到协议过滤器链表中,即outf=p_filters;

   (3) 内容和协议之外的过滤器将被添加到连接过滤器链表中,即outf=c_filters.

15.ap_add_input_filter_handle()函数可以直接按照过滤器句柄进行添加。函数内部仅仅是调用了add_any_filter而已。

16.当一个过滤器不再需要的时候,它就可以从请求或连接中被删除。Apache中通过ap_remove_input_filter和ap_remove_output_filter函数实现移除的效果.

17.过滤器提供者

struct ap_filter_provider_t
{
    /*How to match this provider to filter dispatch criterion */
    enum {
        STRING_MATCH,
        STRING_CONTAINS,
        REGEX_MATCH,
        INT_EQ,
        INT_LT,
        INT_LE,
        INT_GT,
        INT_GE,
        DEFINED
    } match_type;

    /* negation on match_type */
    int not;

    union {
        const char *string;
        ap_regex_t *regex;
        int number;
    } match;

    /* The filter that implements this provider */
    ap_filter_rec_t *frec;

    /* The next provider in the list */
    ap_filter_provider_t *next;

    /* Dispatch criteria for filter providers */
    enum {
        HANDLER,
        REQUEST_HEADERS,
        RESPONSE_HEADERS,
        SUBPROCESS_ENV,
        CONTENT_TYPE
    } dispatch;
    
    /* Match vluae for filter providers */
    const char *value;
};

18.过滤器束和请求提供者之间的关系如下图:

   

猜你喜欢

转载自blog.csdn.net/zhangge3663/article/details/83344078
今日推荐