[Tilecache] PATCH: X-SendFile and Expires headers

Christopher Schmidt crschmidt at metacarta.com
Wed Oct 7 10:15:54 EDT 2009


On Tue, Oct 06, 2009 at 11:02:56AM -0400, mdeneen+tiles at saucontech.com wrote:
> Chris,
> 
> I've attached another patch.  This one adds a bit of documentation, support for the cgi handler and a bug fix to my previous patch.  It will only send the X-SendFile and Expires if the content type is not text/xml.  If text/xml is returned, the output should be identical to what it would be if one were not using X-SendFile.
> 
> The patch is against TileCache 2.10, so you don't need to apply the previous patch first.

Applied, with a couple changes:
 * expires is in seconds
 * It checks for image/, rather than for text/xml, since KML is also
   not-cached and served via the KML service.
 * mod_python support added.

Commit was r396. I'll try and push a release with this and other bugfixes
relatively soon.

Thanks for the patch.

-- Chris

> Best Regards,
> Mark Deneen
> Saucon Technologies
> 
> ----- "Christopher Schmidt" <crschmidt at metacarta.com> wrote:
> 
> > On Tue, Oct 06, 2009 at 10:02:56AM -0400, Mark Deneen wrote:
> > > Where do you want the documentation for the new options?  They are
> > options for the Disk cache and the only documented options I see are
> > for the layers.  Should I just write up a description in
> > docs/Caches.txt?
> > 
> > That'd be great. And no need to write the patch for the other
> > hanlders;
> > just mention in the docs what handlers the options work for.
> > 
> > Don't worry too much about formatting; just get the text together, and
> > 
> > I can fix any formatting issues.
> > 
> > Regards,
> > -- 
> > Christopher Schmidt
> > MetaCarta
> diff -ru tilecache-2.10/docs/Caches.txt ../tilecache.mod/docs/Caches.txt
> --- tilecache-2.10/docs/Caches.txt	2008-12-14 09:59:49.000000000 -0500
> +++ ../tilecache.mod/docs/Caches.txt	2009-10-06 10:55:08.000000000 -0400
> @@ -12,9 +12,24 @@
>    type=Disk
>    base=/var/lib/tilecache
>    umask=002
> +  sendfile=yes
> +  expire=24
>  
>  Dependencies: None
>  
> +The sendfile=yes option instructs TileCache to send an X-SendFile header to
> +the web server rather than the contents of the image.
> +
> +See http://blog.lighttpd.net/articles/2006/07/02/x-sendfile and
> +http://tn123.ath.cx/mod_xsendfile/
> +
> +The expire=n option instructs TileCache to send an Expires header, with the
> +date set 'n' hours into the future.
> +
> +Both the sendfile and expire options are currently only supported with the cgi
> +and wsgi handlers. With minor changes, other handlers could easily be
> +supported.
> +
>  GoogleDisk
>  ----
>  Example Configuration::
> diff -ru tilecache-2.10/TileCache/Caches/Disk.py ../tilecache.mod/TileCache/Caches/Disk.py
> --- tilecache-2.10/TileCache/Caches/Disk.py	2008-12-14 09:32:29.000000000 -0500
> +++ ../tilecache.mod/TileCache/Caches/Disk.py	2009-10-05 15:50:57.000000000 -0400
> @@ -4,11 +4,14 @@
>  import sys, os, time, warnings
>  
>  class Disk (Cache):
> -    def __init__ (self, base = None, umask = '002', **kwargs):
> +    def __init__ (self, base = None, sendfile = False, expire = False,  umask = '002', **kwargs):
>          Cache.__init__(self, **kwargs)
>          self.basedir = base
>          self.umask = int(umask, 0)
> -        
> +        self.sendfile = sendfile and sendfile.lower() in ["yes", "y", "t", "true"]
> +        self.expire = expire
> +        if expire != False:
> +            self.expire = long(expire) * 3600
>          if sys.platform.startswith("java"):
>              from java.io import File
>              self.file_module = File
> @@ -64,8 +67,11 @@
>      def get (self, tile):
>          filename = self.getKey(tile)
>          if self.access(filename, 'read'):
> -            tile.data = file(filename, "rb").read()
> -            return tile.data
> +            if self.sendfile:
> +                return filename
> +            else:
> +                tile.data = file(filename, "rb").read()
> +                return tile.data
>          else:
>              return None
>  
> diff -ru tilecache-2.10/TileCache/Service.py ../tilecache.mod/TileCache/Service.py
> --- tilecache-2.10/TileCache/Service.py	2009-01-18 21:11:52.000000000 -0500
> +++ ../tilecache.mod/TileCache/Service.py	2009-10-06 10:47:46.000000000 -0400
> @@ -4,7 +4,7 @@
>  
>  class TileCacheException(Exception): pass
>  
> -import sys, cgi, time, os, traceback, ConfigParser
> +import sys, cgi, time, os, traceback, email, ConfigParser
>  import Cache, Caches
>  import Layer, Layers
>  
> @@ -291,8 +291,18 @@
>          fields = parse_formvars(environ)
>  
>          format, image = service.dispatchRequest( fields, path_info, req_method, host )
> -        start_response("200 OK", [('Content-Type',format)])
> -        return [image]
> +        headers = [('Content-Type',format)]
> +        if format != "text/xml":
> +            if service.cache.sendfile:
> +                headers.append(('X-SendFile', image))
> +            if service.cache.expire:
> +                headers.append(('Expires', email.Utils.formatdate(time.time() + service.cache.expire, False, True)))
> +
> +        start_response("200 OK", headers)
> +        if service.cache.sendfile and format != "text/xml":
> +            return []
> +        else:
> +            return [image]
>  
>      except TileCacheException, E:
>          start_response("404 Tile Not Found", [('Content-Type','text/plain')])
> @@ -321,12 +331,18 @@
>          host += os.environ["SCRIPT_NAME"]
>          req_method = os.environ["REQUEST_METHOD"]
>          format, image = service.dispatchRequest( params, path_info, req_method, host )
> -        print "Content-type: %s\n" % format
> -
> -        if sys.platform == "win32":
> -            binaryPrint(image)
> -        else:    
> -            print image
> +        print "Content-type: %s" % format
> +        if format != "text/xml":
> +            if service.cache.sendfile:
> +                print "X-SendFile: %s" % image
> +            if service.cache.expire:
> +                print "Expires: %s" % email.Utils.formatdate(time.time() + service.cache.expire, False, True)
> +        print "\n"
> +        if (not service.cache.sendfile) or (format == "text/xml"):
> +            if sys.platform == "win32":
> +                binaryPrint(image)
> +            else:    
> +                print image
>      except TileCacheException, E:
>          print "Cache-Control: max-age=10, must-revalidate" # make the client reload        
>          print "Content-type: text/plain\n"


-- 
Christopher Schmidt
MetaCarta



More information about the Tilecache mailing list