1 <?xml version="1.0" encoding="ISO-8859-1"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head><!--
4 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
5 This file is generated from xml source: DO NOT EDIT
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8 <title>How filters work in Apache 2.0 - Apache HTTP Server</title>
9 <link href="../style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
10 <link href="../style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
11 <link href="../style/css/manual-print.css" rel="stylesheet" media="print" type="text/css" />
12 <link href="../images/favicon.ico" rel="shortcut icon" /></head>
13 <body id="manual-page"><div id="page-header">
14 <p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p>
15 <p class="apache">Apache HTTP Server Version 2.0</p>
16 <img alt="" src="../images/feather.gif" /></div>
17 <div class="up"><a href="./"><img title="<-" alt="<-" src="../images/left.gif" /></a></div>
19 <a href="http://www.apache.org/">Apache</a> > <a href="http://httpd.apache.org/">HTTP Server</a> > <a href="http://httpd.apache.org/docs/">Documentation</a> > <a href="../">Version 2.0</a> > <a href="./">Developer Documentation</a></div><div id="page-content"><div id="preamble"><h1>How filters work in Apache 2.0</h1>
21 <p><span>Available Languages: </span><a href="../en/developer/filters.html" title="English"> en </a></p>
24 <div class="warning"><h3>Warning</h3>
25 <p>This is a cut 'n paste job from an email
26 (<022501c1c529$f63a9550$7f00000a@KOJ>) and only reformatted for
27 better readability. It's not up to date but may be a good start for
31 <div id="quickview"><ul id="toc"><li><img alt="" src="../images/down.gif" /> <a href="#types">Filter Types</a></li>
32 <li><img alt="" src="../images/down.gif" /> <a href="#howinserted">How are filters inserted?</a></li>
33 <li><img alt="" src="../images/down.gif" /> <a href="#asis">Asis</a></li>
34 <li><img alt="" src="../images/down.gif" /> <a href="#conclusion">Explanations</a></li>
36 <div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
38 <h2><a name="types" id="types">Filter Types</a></h2>
39 <p>There are three basic filter types (each of these is actually broken
40 down into two categories, but that comes later).</p>
43 <dt><code>CONNECTION</code></dt>
44 <dd>Filters of this type are valid for the lifetime of this connection.
45 (<code>AP_FTYPE_CONNECTION</code>, <code>AP_FTYPE_NETWORK</code>)</dd>
47 <dt><code>PROTOCOL</code></dt>
48 <dd>Filters of this type are valid for the lifetime of this request from
49 the point of view of the client, this means that the request is valid
50 from the time that the request is sent until the time that the response
51 is received. (<code>AP_FTYPE_PROTOCOL</code>,
52 <code>AP_FTYPE_TRANSCODE</code>)</dd>
54 <dt><code>RESOURCE</code></dt>
55 <dd>Filters of this type are valid for the time that this content is used
56 to satisfy a request. For simple requests, this is identical to
57 <code>PROTOCOL</code>, but internal redirects and sub-requests can change
58 the content without ending the request. (<code>AP_FTYPE_RESOURCE</code>,
59 <code>AP_FTYPE_CONTENT_SET</code>)</dd>
62 <p>It is important to make the distinction between a protocol and a
63 resource filter. A resource filter is tied to a specific resource, it
64 may also be tied to header information, but the main binding is to a
65 resource. If you are writing a filter and you want to know if it is
66 resource or protocol, the correct question to ask is: "Can this filter
67 be removed if the request is redirected to a different resource?" If
68 the answer is yes, then it is a resource filter. If it is no, then it
69 is most likely a protocol or connection filter. I won't go into
70 connection filters, because they seem to be well understood. With this
71 definition, a few examples might help:</p>
75 <dd>We have coded it to be inserted for all requests, and it is removed
76 if not used. Because this filter is active at the beginning of all
77 requests, it can not be removed if it is redirected, so this is a
81 <dd>This filter actually writes the headers to the network. This is
82 obviously a required filter (except in the asis case which is special
83 and will be dealt with below) and so it is a protocol filter.</dd>
86 <dd>The administrator configures this filter based on which file has been
87 requested. If we do an internal redirect from an autoindex page to an
88 index.html page, the deflate filter may be added or removed based on
89 config, so this is a resource filter.</dd>
92 <p>The further breakdown of each category into two more filter types is
93 strictly for ordering. We could remove it, and only allow for one
94 filter type, but the order would tend to be wrong, and we would need to
95 hack things to make it work. Currently, the <code>RESOURCE</code> filters
96 only have one filter type, but that should change.</p>
97 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
99 <h2><a name="howinserted" id="howinserted">How are filters inserted?</a></h2>
100 <p>This is actually rather simple in theory, but the code is
101 complex. First of all, it is important that everybody realize that
102 there are three filter lists for each request, but they are all
103 concatenated together. So, the first list is
104 <code>r->output_filters</code>, then <code>r->proto_output_filters</code>,
105 and finally <code>r->connection->output_filters</code>. These correspond
106 to the <code>RESOURCE</code>, <code>PROTOCOL</code>, and
107 <code>CONNECTION</code> filters respectively. The problem previously, was
108 that we used a singly linked list to create the filter stack, and we
109 started from the "correct" location. This means that if I had a
110 <code>RESOURCE</code> filter on the stack, and I added a
111 <code>CONNECTION</code> filter, the <code>CONNECTION</code> filter would
112 be ignored. This should make sense, because we would insert the connection
113 filter at the top of the <code>c->output_filters</code> list, but the end
114 of <code>r->output_filters</code> pointed to the filter that used to be
115 at the front of <code>c->output_filters</code>. This is obviously wrong.
116 The new insertion code uses a doubly linked list. This has the advantage
117 that we never lose a filter that has been inserted. Unfortunately, it comes
118 with a separate set of headaches.</p>
120 <p>The problem is that we have two different cases were we use subrequests.
121 The first is to insert more data into a response. The second is to
122 replace the existing response with an internal redirect. These are two
123 different cases and need to be treated as such.</p>
125 <p>In the first case, we are creating the subrequest from within a handler
126 or filter. This means that the next filter should be passed to
127 <code>make_sub_request</code> function, and the last resource filter in the
128 sub-request will point to the next filter in the main request. This
129 makes sense, because the sub-request's data needs to flow through the
130 same set of filters as the main request. A graphical representation
133 <div class="example"><pre>
134 Default_handler --> includes_filter --> byterange --> ...
137 <p>If the includes filter creates a sub request, then we don't want the
138 data from that sub-request to go through the includes filter, because it
139 might not be SSI data. So, the subrequest adds the following:</p>
141 <div class="example"><pre>
142 Default_handler --> includes_filter -/-> byterange --> ...
144 Default_handler --> sub_request_core
147 <p>What happens if the subrequest is SSI data? Well, that's easy, the
148 <code>includes_filter</code> is a resource filter, so it will be added to
149 the sub request in between the <code>Default_handler</code> and the
150 <code>sub_request_core</code> filter.</p>
152 <p>The second case for sub-requests is when one sub-request is going to
153 become the real request. This happens whenever a sub-request is created
154 outside of a handler or filter, and NULL is passed as the next filter to
155 the <code>make_sub_request</code> function.</p>
157 <p>In this case, the resource filters no longer make sense for the new
158 request, because the resource has changed. So, instead of starting from
159 scratch, we simply point the front of the resource filters for the
160 sub-request to the front of the protocol filters for the old request.
161 This means that we won't lose any of the protocol filters, neither will
162 we try to send this data through a filter that shouldn't see it.</p>
164 <p>The problem is that we are using a doubly-linked list for our filter
165 stacks now. But, you should notice that it is possible for two lists to
166 intersect in this model. So, you do you handle the previous pointer?
167 This is a very difficult question to answer, because there is no "right"
168 answer, either method is equally valid. I looked at why we use the
169 previous pointer. The only reason for it is to allow for easier
170 addition of new servers. With that being said, the solution I chose was
171 to make the previous pointer always stay on the original request.</p>
173 <p>This causes some more complex logic, but it works for all cases. My
174 concern in having it move to the sub-request, is that for the more
175 common case (where a sub-request is used to add data to a response), the
176 main filter chain would be wrong. That didn't seem like a good idea to
178 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
179 <div class="section">
180 <h2><a name="asis" id="asis">Asis</a></h2>
181 <p>The final topic. :-) Mod_Asis is a bit of a hack, but the
182 handler needs to remove all filters except for connection filters, and
183 send the data. If you are using <code class="module"><a href="../mod/mod_asis.html">mod_asis</a></code>, all other
185 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
186 <div class="section">
187 <h2><a name="conclusion" id="conclusion">Explanations</a></h2>
188 <p>The absolutely last point is that the reason this code was so hard to
189 get right, was because we had hacked so much to force it to work. I
190 wrote most of the hacks originally, so I am very much to blame.
191 However, now that the code is right, I have started to remove some
192 hacks. Most people should have seen that the <code>reset_filters</code>
193 and <code>add_required_filters</code> functions are gone. Those inserted
194 protocol level filters for error conditions, in fact, both functions did
195 the same thing, one after the other, it was really strange. Because we
196 don't lose protocol filters for error cases any more, those hacks went away.
197 The <code>HTTP_HEADER</code>, <code>Content-length</code>, and
198 <code>Byterange</code> filters are all added in the
199 <code>insert_filters</code> phase, because if they were added earlier, we
200 had some interesting interactions. Now, those could all be moved to be
201 inserted with the <code>HTTP_IN</code>, <code>CORE</code>, and
202 <code>CORE_IN</code> filters. That would make the code easier to
205 <div class="bottomlang">
206 <p><span>Available Languages: </span><a href="../en/developer/filters.html" title="English"> en </a></p>
207 </div><div id="footer">
208 <p class="apache">Copyright 2009 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
209 <p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p></div>