Sometimes you want to generate a resource (say a chart) once and then keep it. This way you don't need to keep track of all the objects you've created and can easily clean (since if someone want the resource again it will be generated again).
One way is to do it with lighttpd 404 handlers (
view complete code).
lighttpd.conf
# lighttpd configuration file
server.modules = ( "mod_cgi" )
# This is generated by by web-up
include "lighttpd.inc"
server.document-root = var.root
server.pid-file = var.root + "/lighttpd.pid"
# files to check for if .../ is requested
index-file.names = ( "index.cgi" )
## set the event-handler (read the performance section in the manual)
# server.event-handler = "freebsd-kqueue" # needed on OS X
# mimetype mapping
mimetype.assign = (
".pdf" => "application/pdf",
".sig" => "application/pgp-signature",
".spl" => "application/futuresplash",
".class" => "application/octet-stream",
".ps" => "application/postscript",
".torrent" => "application/x-bittorrent",
".dvi" => "application/x-dvi",
".gz" => "application/x-gzip",
".pac" => "application/x-ns-proxy-autoconfig",
".swf" => "application/x-shockwave-flash",
".tar.gz" => "application/x-tgz",
".tgz" => "application/x-tgz",
".tar" => "application/x-tar",
".zip" => "application/zip",
".mp3" => "audio/mpeg",
".m3u" => "audio/x-mpegurl",
".wma" => "audio/x-ms-wma",
".wax" => "audio/x-ms-wax",
".ogg" => "application/ogg",
".wav" => "audio/x-wav",
".gif" => "image/gif",
".jpg" => "image/jpeg",
".jpeg" => "image/jpeg",
".png" => "image/png",
".xbm" => "image/x-xbitmap",
".xpm" => "image/x-xpixmap",
".xwd" => "image/x-xwindowdump",
".css" => "text/css",
".html" => "text/html",
".htm" => "text/html",
".js" => "text/javascript",
".asc" => "text/plain",
".c" => "text/plain",
".cpp" => "text/plain",
".log" => "text/plain",
".conf" => "text/plain",
".text" => "text/plain",
".txt" => "text/plain",
".dtd" => "text/xml",
".xml" => "text/xml",
".mpeg" => "video/mpeg",
".mpg" => "video/mpeg",
".mov" => "video/quicktime",
".qt" => "video/quicktime",
".avi" => "video/x-msvideo",
".asf" => "video/x-ms-asf",
".asx" => "video/x-ms-asf",
".wmv" => "video/x-ms-wmv",
".bz2" => "application/x-bzip",
".tbz" => "application/x-bzip-compressed-tar",
".tar.bz2" => "application/x-bzip-compressed-tar"
)
$HTTP["url"] =~ "\.pdf$" {
server.range-requests = "disable"
}
# which extensions should not be handle via static-file transfer
static-file.exclude-extensions = ( ".cgi" )
# This is where the magic happens :)
$HTTP["url"] =~ "/charts/.*\.png$" {
server.error-handler-404 = "/chart.cgi"
}
chart.cgi
#!/usr/bin/env python
'''This CGI script is called by lighttpd 404 error handler when it tries to find
/charts/XXX.png.
This way the image is generated once and then we let lighttpd serve it as static
content.
'''
# The below is needed to tell pylab to work without a screen
import matplotlib; matplotlib.use("Agg")
from pylab import hist, randn, title, savefig
from os import environ
from os.path import basename
from urlparse import urlparse
def generate_chart(name, outfile):
# Generate a random chart
hist(randn(1000), 100)
title("Chart for \"%s\"" % name)
savefig(outfile)
def main():
import cgitb; cgitb.enable()
o = urlparse(environ.get("REQUEST_URI", ""))
if not o.path:
print "Content-type: text/plain\n"
print "ERROR: Can't find path"
raise SystemExit
outfile = "charts/%s" % basename(o.path)
name = basename(o.path).replace(".png", "")
if not name:
print "Content-type: text/plain\n"
print "ERROR: 'name' not specified"
raise SystemExit
generate_chart(name, outfile)
image = open(outfile, "rb").read()
print "Content-type: image/png\n"
print image
if __name__ == "__main__":
main()