Раздел 11. Developer Documentation RU EN Пункт 221. How Filters Work in 2.x WarningThis is a cut 'n paste job from an email (<022501c1c529$f63a9550$7f00000a@KOJ>) and only reformatted for better readability. It's not up to date but may be a good start for further research. Filter TypesThere are three basic filter types (each of these is actually broken down into two categories, but that comes later).
It is important to make the distinction between a protocol and a resource filter. A resource filter is tied to a specific resource, it may also be tied to header information, but the main binding is to a resource. If you are writing a filter and you want to know if it is resource or protocol, the correct question to ask is: "Can this filter be removed if the request is redirected to a different resource?" If the answer is yes, then it is a resource filter. If it is no, then it is most likely a protocol or connection filter. I won't go into connection filters, because they seem to be well understood. With this definition, a few examples might help:
The further breakdown of each category into two more filter types is
strictly for ordering. We could remove it, and only allow for one
filter type, but the order would tend to be wrong, and we would need to
hack things to make it work. Currently, the How are filters inserted?This is actually rather simple in theory, but the code is complex. First of all, it is important that everybody realize that there are three filter lists for each request, but they are all concatenated together:
The problem previously, was that we used a singly linked list to create the filter stack, and we
started from the "correct" location. This means that if I had a
The problem is that we have two different cases were we use subrequests. The first is to insert more data into a response. The second is to replace the existing response with an internal redirect. These are two different cases and need to be treated as such. In the first case, we are creating the subrequest from within a handler
or filter. This means that the next filter should be passed to
Default_handler --> includes_filter --> byterange --> ... If the includes filter creates a sub request, then we don't want the data from that sub-request to go through the includes filter, because it might not be SSI data. So, the subrequest adds the following: Default_handler --> includes_filter -/-> byterange --> ... / Default_handler --> sub_request_core What happens if the subrequest is SSI data? Well, that's easy, the
The second case for sub-requests is when one sub-request is going to
become the real request. This happens whenever a sub-request is created
outside of a handler or filter, and NULL is passed as the next filter to
the In this case, the resource filters no longer make sense for the new request, because the resource has changed. So, instead of starting from scratch, we simply point the front of the resource filters for the sub-request to the front of the protocol filters for the old request. This means that we won't lose any of the protocol filters, neither will we try to send this data through a filter that shouldn't see it. The problem is that we are using a doubly-linked list for our filter stacks now. But, you should notice that it is possible for two lists to intersect in this model. So, you do you handle the previous pointer? This is a very difficult question to answer, because there is no "right" answer, either method is equally valid. I looked at why we use the previous pointer. The only reason for it is to allow for easier addition of new servers. With that being said, the solution I chose was to make the previous pointer always stay on the original request. This causes some more complex logic, but it works for all cases. My concern in having it move to the sub-request, is that for the more common case (where a sub-request is used to add data to a response), the main filter chain would be wrong. That didn't seem like a good idea to me. AsisThe final topic. :-) Mod_Asis is a bit of a hack, but the
handler needs to remove all filters except for connection filters, and
send the data. If you are using ExplanationsThe absolutely last point is that the reason this code was so hard to
get right, was because we had hacked so much to force it to work. I
wrote most of the hacks originally, so I am very much to blame.
However, now that the code is right, I have started to remove some
hacks. Most people should have seen that the |
![]() |