You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Christian Seiler <ch...@gmx.net> on 2008/01/07 19:36:40 UTC

Output filters in subrequests created by mod_actions (httpd 2.2.x)

Hi!

I hope this wasn't already discussed previously (I didn't find anything
in the archives, but maybe I overlooked something), if so, sorry for the
noise.

I recently stumbled upon the following behaviour of Apache (2.2.x,
though it will probably apply to the developement branch as well) which
I found to be quite odd at first. In order to explain better, I created
a very simple test case:

/demo/ contains the following files:

.htaccess:
---------------------------------
Options +ExecCGI +Includes
AddOutputFilter INCLUDES .demo

AddHandler cgi-script .pl
AddHandler demo .demo
Action demo /demo/test.pl

<Files test2.pl>
   SetOutputFilter INCLUDES
</Files>
---------------------------------

test.pl and test2.pl (both executable):
---------------------------------
#!/usr/bin/perl

use strict;
use warnings;

print "Content-Type: text/plain\n\n";
print '<!--#include virtual="/demo/test.txt"-->';
---------------------------------

test.txt:
---------------------------------
This is a test!
---------------------------------

test.demo:
---------------------------------
Empty
---------------------------------

If I call /demo/test.pl, my browser will display the text <!--#include
virtual="/demo/test.txt"--> - which is fine, because there are no output
filters defined for test.pl.

If I call /demo/test2.pl, my browser will display the text "This is a
test!" - which is fine too, because there's an explicit output filter
for test2.pl.

If I call /demo/test.demo, my browser will display the text <!--#include
virtual="/demo/test.txt"--> - which - er - is not exactly what I intended.

If I change the .htaccess to Action demo /demo/test2.pl and call
/demo/test.demo, my browser will display the text "This is a test!" -
which is fine.

My basic problem is that the output filters set for the original file
that was called are not copied when mod_actions does an internal
subrequest to execute the action.

The "culprit" is the function internal_internal_redirect in
server/http_request.c which only copies the protocol filters but not all
the input filters:

     new->proto_output_filters  = r->proto_output_filters;
     new->proto_input_filters   = r->proto_input_filters;

     new->output_filters  = new->proto_output_filters;
     new->input_filters   = new->proto_input_filters;

Which of course is fine by itself because otherwise this could cause
quite some headaches in all of the other use cases of internal redirects
(think, for example, mod_rewrite).

Ok, a CGI script generating a SSI directive is not the best example for
a useful use case. But take a mod_deflate, i.e. replace INCLUDES with
DEFLATE in the above example. That's an extremly useful output filter.
The problem is that it won't work if an internal redirect via Action
occurs if it's set only on the file types that are assigned to action.

To provide a useful example, have a look at PHP installations: You can
either install it as an Apache Module (mod_php) or as CGI/FastCGI in
which case you'd use Action. If you install it as a module,
AddOutputFilter DEFLATE .php works just as expected - but if you install
it as CGI/FastCGI, it won't. Of course, you could make sure that the
filter is added to the CGI wrapper of PHP itself (i.e. the target of the
Action line) but this is a) counter-intuitive and b) won't account for
configurations where you only want to activate it for certain
subdirectories or similar. Of course, this is all work-aroundable by
defining multiple actions with the same target but that makes the
configuration unecessarily complicated and well - counter-intuitive.

This applies to any other case where you'd use Action as well, PHP is
just an example (albeit probably a very prominent one).

This could be addressed by altering the ap_internal_redirect_handler
function to add the normal output filters after calling
internal_internal_redirect. I grepped the httpd source and found 4
occurrences where the function is called: In mod_actions which is the
case I described and in mod_asis, mod_cgi and mod_cgid which is used to
do an internal redirect if a Location: /... header was set by the CGI
script. I haven't looked at third-party modules so I don't know how it's
used there. But in all four cases where this occurs inside httpd I don't
see a problem in performing this change.

Any thoughts on this?

Regards,
Christian