How can I serve unbuffered CGI content from Apache 2?

I would like to be able to allow the user to view the output of a long GCI script as it is created, and not after the script completes. However, even when I explicitly hide STDOUT, the server seems to be waiting for the script to complete before sending a response to the client. This is on a Linux server with Apache 2.2.9.

CGI python example:

#!/usr/bin/python import time import sys print "Content-type: text/plain" print for i in range(1, 10): print i sys.stdout.flush() time.sleep(1) print "Done." 

A similar example in perl:

 #!/usr/bin/perl print "Content-type: text/plain\n\n"; for ($i = 1; $i <= 10 ; $i++) { print "$i\n"; sleep(1); } print "Done."; 

This link says that the output of Apache 1.3 CGI should be unbuffered (but this can only apply to Apache 1.x): http://httpd.apache.org/docs/1.3/misc/FAQ-F.html#nph- scripts

Any ideas?

+7
python perl apache2 cgi
source share
4 answers

Randal Schwartz's article Observing lengthy processes through CGI explains another (and IMHO, best) way to view a long process.

+4
source share

You should put your push script in a special directory that has a special .htaccess with these environment specifications:

 Options +ExecCGI AddHandler cgi-script .cgi .sh .pl .py SetEnvIfNoCase Content-Type \ "^multipart/form-data;" "MODSEC_NOPOSTBUFFERING=Do not buffer file uploads" SetEnv no-gzip dont-vary 
+2
source share

According to CGI :: Push ,

Apache web server version 1.3b2 on do not need push server scripts installed as NPH scripts: -nph do_push () parameter can be set to false to disable additional headers required for NPH script.

You just need to find the do_push equivalent in python.

Change See CherryPy: Streaming the body of the response .

When you set the config entry "response.stream" to True (and use "yield"), CherryPy manages the conversation between the HTTP server and your code as follows:

alt text http://www.cherrypy.org/attachment/wiki/ReturnVsYield/cpyield.gif?format=raw

+1
source share

Resetting STDOUT may help. For example, the following Perl program should work as intended:

 #!/usr/bin/perl use strict; use warnings; local $| = 1; print "Content-type: text/plain\n\n"; for ( my $i = 1 ; $i <= 10 ; $i++ ) { print "$i\n"; sleep(1); } print "Done."; 
+1
source share

All Articles