这是电子邮件中的剪切粘贴作业(<022501c1c529 $ f63a9550 $ 7f00000a @ KOJ>),仅重新格式化以提高可读性。它不是最新的,但可能是进一步研究的良好开端。
共有三种基本的过滤器类型(实际上每种类型都分为两类,但稍后介绍)。
CONNECTION
AP_FTYPE_CONNECTION
,AP_FTYPE_NETWORK
)PROTOCOL
AP_FTYPE_PROTOCOL
,
AP_FTYPE_TRANSCODE
)RESOURCE
PROTOCOL
,但是内部重定向和子请求可以更改内容而不会结束请求。(AP_FTYPE_RESOURCE
,
AP_FTYPE_CONTENT_SET
)区分协议和资源过滤器很重要。资源过滤器绑定到特定资源,它也可能绑定到标头信息,但主要绑定是绑定到资源。如果您正在编写过滤器,并且想知道它是资源还是协议,则要问的正确问题是:“如果将请求重定向到另一个资源,可以删除此过滤器吗?” 如果答案是肯定的,则它是资源过滤器。如果为否,则很可能是协议或连接筛选器。我不会去研究连接过滤器,因为它们似乎很容易理解。使用此定义,一些示例可能会有所帮助:
每个类别进一步细分为另外两种过滤器类型严格用于订购。我们可以删除它,只允许使用一种过滤器类型,但是顺序往往是错误的,并且我们需要破解一些东西才能使其工作。当前,RESOURCE
过滤器只有一种过滤器类型,但是应该改变。
从理论上讲,这实际上很简单,但是代码很复杂。首先,重要的是每个人都必须意识到每个请求都有三个过滤器列表,但是它们都被串联在一起:
r->output_filters
(对应于RESOURCE)r->proto_output_filters
(对应于PROTOCOL)r->connection->output_filters
(对应于CONNECTION)以前的问题是,我们使用一个单链表创建了过滤器堆栈,然后从“正确”的位置开始。这意味着,如果我RESOURCE
在堆栈上有一个
过滤器,并且添加了一个
CONNECTION
过滤器,则该CONNECTION
过滤器将被忽略。这应该是有道理的,因为我们会将连接过滤器插入到c->output_filters
列表的顶部,但将r->output_filters
指向末尾的过滤器插入到的前面c->output_filters
。这显然是错误的。新的插入代码使用双向链表。这样的好处是我们永远不会丢失已插入的过滤器。不幸的是,它带来了另一组头痛。
问题在于,使用子请求时,我们有两种不同的情况。首先是在响应中插入更多数据。第二个是用内部重定向替换现有响应。这是两种不同的情况,需要这样处理。
在第一种情况下,我们从处理程序或过滤器中创建子请求。这意味着应该将下一个过滤器传递给
make_sub_request
函数,并且子请求中的最后一个资源过滤器将指向主请求中的下一个过滤器。这是有道理的,因为子请求的数据需要流经与主请求相同的一组过滤器。图形表示可能会帮助:
Default_handler --> includes_filter --> byterange --> ...
如果include过滤器创建了一个子请求,则我们不希望该子请求中的数据通过include过滤器,因为它可能不是SSI数据。因此,子请求添加了以下内容:
Default_handler --> includes_filter -/-> byterange --> ... / Default_handler --> sub_request_core
如果子请求是SSI数据会怎样?好吧,这很容易,因为
includes_filter
它是资源过滤器,所以它将被添加到Default_handler
和
sub_request_core
过滤器之间的子请求中。
子请求的第二种情况是一个子请求将成为真实请求。每当在处理程序或过滤器之外创建子请求并将NULL作为下一个过滤器传递给make_sub_request
函数时,就会发生这种情况。
在这种情况下,资源过滤器对于新请求不再有意义,因为资源已更改。因此,我们无需从头开始,只需将子请求的资源过滤器的前端指向旧请求的协议过滤器的前端。这意味着我们不会丢失任何协议过滤器,也不会尝试通过不应该看到它的过滤器发送此数据。
问题是我们现在正在为过滤器堆栈使用双向链接列表。但是,您应该注意,此模型中可能有两个列表相交。那么,您处理上一个指针了吗?这是一个很难回答的问题,因为没有“正确”的答案,任何一种方法都同样有效。我研究了为什么我们使用以前的指针。这样做的唯一原因是允许更轻松地添加新服务器。话虽如此,我选择的解决方案是使先前的指针始终停留在原始请求上。
这会导致一些更复杂的逻辑,但它适用于所有情况。我担心将其移到子请求中是,对于更常见的情况(使用子请求将数据添加到响应中),主过滤器链将是错误的。在我看来,这似乎不是一个好主意。
绝对的最后一点是,该代码之所以难以正确编写,是因为我们破解了太多代码以迫使其工作。我最初写了大多数hack,所以我要怪很多。但是,既然代码正确,我已经开始删除一些技巧。大多数人应该已经看到reset_filters
和add_required_filters
功能已消失。那些插入的针对错误条件的协议级别过滤器,实际上,两个功能都做同样的事情,一个又一个,这确实很奇怪。因为我们不再为错误情况丢失协议过滤器,所以这些黑客消失了。的HTTP_HEADER
,Content-length
和
Byterange
过滤器中的所有加
insert_filters
阶段,因为如果它们是较早添加的,我们将进行一些有趣的交互。现在,那些可能被移动到与插入HTTP_IN
,CORE
和
CORE_IN
过滤器。这将使代码更易于遵循。
可用语言: zh