As part of a content management system I'm developing I have a script which retrieves image files (JPEG, GIF, PNG etc) in response to the browser GETing a URL like http://myserver/getimage.cgi/virtual/path/to/image
. On the server the image files are stored outside DOCUMENT_ROOT as randomly-named blobs and a database keeps track of the metadata, in particular the correspondence between virtual path, blob filename and the MIME type. The script looks like this:-
#!/usr/bin/perl
use CGI::Simple;
use File::Copy;
use MYSTUFF 'dblookup';
my $q = new CGI::Simple;
my ($mimetype, $filepath) = dblookup($q->path_info);
$| = 1; # enable autoflush so header is output before calling copy()
print $q->header(-type=>$mimetype);
copy($filepath, \*STDOUT);
The dblookup
function is exported by MYSTUFF.pm and extracts the mimetype and filepath for the virtual path passed in via the standard CGI $PATH_INFO environment variable.
My concern is how the output of the CGI script is spooled by the Apache server before it starts sending it back to the browser. If it spools the entire output then potentially there's a need for a huge amount of spool space on the server because the image files can be 10's or 100's of MB, and when I start supporting video files they could get up to GB.
Is the Apache server sensible enough to spool the STDOUT stream from the CGI script only up to the point where it's got all the headers (i.e. the first "\n\n", which is generated by $q->header()
), then start copying the data buffer-for-buffer from STDOUT to whatever socket is attached to the HTTP connection back to the browser? The documentation for File::Copy suggests that it will use a 1K buffer, so if Apache behaves in the way I've outlined then I don't really have a problem, do I, as the IPC sockets/pipes will enforce flow control on my CGI script, removing the need for any further spool space beyond the buffers that are already there??
I'm not sure how Apache handles this. However, if you're asking about this for performance reasons, then I wonder why you're using CGI to begin with...
A few alternatives you might want to consider:
mod_negotiate
to pick the right MIME type based on server- and client side configurationmod_rewrite
to tell Apache to read a particular file in response to a particular request. It is possible to vary the produced result here based on, e.g., cookies, or other things set by the request; for more details, see the mod_rewrite documentation