<-
Apache HTTP 服务器 2.4 > 过滤器在2.x中的工作方式

过滤器如何在Apache 2.0中工作

警告

这是电子邮件中的剪切粘贴作业(<022501c1c529 $ f63a9550 $ 7f00000a @ KOJ>),仅重新格式化以提高可读性。它不是最新的,但可能是进一步研究的良好开端。

支持Apache!

也可以看看

最佳

筛选器类型

共有三种基本的过滤器类型(实际上每种类型都分为两类,但稍后介绍)。

CONNECTION
此类型的过滤器在此连接的生存期内有效。(AP_FTYPE_CONNECTIONAP_FTYPE_NETWORK
PROTOCOL
从客户端的角度来看,这种类型的过滤器在此请求的生存期内有效,这意味着该请求从发送请求之时到收到响应之时才有效。(AP_FTYPE_PROTOCOLAP_FTYPE_TRANSCODE
RESOURCE
此类型的过滤器在此内容用于满足请求时有效。对于简单的请求,这与相同 PROTOCOL,但是内部重定向和子请求可以更改内容而不会结束请求。(AP_FTYPE_RESOURCEAP_FTYPE_CONTENT_SET

区分协议和资源过滤器很重要。资源过滤器绑定到特定资源,它也可能绑定到标头信息,但主要绑定是绑定到资源。如果您正在编写过滤器,并且想知道它是资源还是协议,则要问的正确问题是:“如果将请求重定向到另一个资源,可以删除此过滤器吗?” 如果答案是肯定的,则它是资源过滤器。如果为否,则很可能是协议或连接筛选器。我不会去研究连接过滤器,因为它们似乎很容易理解。使用此定义,一些示例可能会有所帮助:

字节范围
我们已将其编码为可插入所有请求,如果未使用,则将其删除。由于此过滤器在所有请求的开始时都处于活动状态,因此如果将其重定向,则无法将其删除,因此这是一个协议过滤器。
http_header
该过滤器实际上将标头写入网络。显然,这是必需的过滤器(特殊情况除外,将在下面处理),因此它是协议过滤器。
放气
管理员根据请求的文件配置此过滤器。如果我们执行从自动索引页面到index.html页面的内部重定向,则可以基于config添加或删除deflate过滤器,因此这是资源过滤器。

每个类别进一步细分为另外两种过滤器类型严格用于订购。我们可以删除它,只允许使用一种过滤器类型,但是顺序往往是错误的,并且我们需要破解一些东西才能使其工作。当前,RESOURCE过滤器只有一种过滤器类型,但是应该改变。

最佳

如何插入过滤器?

从理论上讲,这实际上很简单,但是代码很复杂。首先,重要的是每个人都必须意识到每个请求都有三个过滤器列表,但是它们都被串联在一起:

以前的问题是,我们使用一个单链表创建了过滤器堆栈,然后从“正确”的位置开始。这意味着,如果我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_handlersub_request_core过滤器之间的子请求中。

子请求的第二种情况是一个子请求将成为真实请求。每当在处理程序或过滤器之外创建子请求并将NULL作为下一个过滤器传递给make_sub_request函数时,就会发生这种情况。

在这种情况下,资源过滤器对于新请求不再有意义,因为资源已更改。因此,我们无需从头开始,只需将子请求的资源过滤器的前端指向旧请求的协议过滤器的前端。这意味着我们不会丢失任何协议过滤器,也不会尝试通过不应该看到它的过滤器发送此数据。

问题是我们现在正在为过滤器堆栈使用双向链接列表。但是,您应该注意,此模型中可能有两个列表相交。那么,您处理上一个指针了吗?这是一个很难回答的问题,因为没有“正确”的答案,任何一种方法都同样有效。我研究了为什么我们使用以前的指针。这样做的唯一原因是允许更轻松地添加新服务器。话虽如此,我选择的解决方案是使先前的指针始终停留在原始请求上。

这会导致一些更复杂的逻辑,但它适用于所有情况。我担心将其移到子请求中是,对于更常见的情况(使用子请求将数据添加到响应中),主过滤器链将是错误的。在我看来,这似乎不是一个好主意。

最佳

阿西斯

最后一个话题。:-) Mod_Asis有点hack,但是处理程序需要删除除连接过滤器之外的所有过滤器,然后发送数据。如果您使用mod_asis,则所有其他投注均关闭。

最佳

说明

绝对的最后一点是,该代码之所以难以正确编写,是因为我们破解了太多代码以迫使其工作。我最初写了大多数hack,所以我要怪很多。但是,既然代码正确,我已经开始删除一些技巧。大多数人应该已经看到reset_filtersadd_required_filters功能已消失。那些插入的针对错误条件的协议级别过滤器,实际上,两个功能都做同样的事情,一个又一个,这确实很奇怪。因为我们不再为错误情况丢失协议过滤器,所以这些黑客消失了。的HTTP_HEADERContent-lengthByterange过滤器中的所有加 insert_filters阶段,因为如果它们是较早添加的,我们将进行一些有趣的交互。现在,那些可能被移动到与插入HTTP_INCORECORE_IN过滤器。这将使代码更易于遵循。

可用语言: zh 

最佳

注释

注意:
这不是“问答”部分。此处放置的评论应指向有关改进文档或服务器的建议,如果实施或被认为无效/偏离主题,我们的主持人可以将其删除。有关如何管理Apache HTTP Server的问题,应直接指向我们的IRC频道#httpd(位于Freenode上),或发送至我们的邮件列表
目前,此页面已禁用评论。