Skip to content

Instantly share code, notes, and snippets.

@JulieGoldberg
Last active December 25, 2015 05:39
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save JulieGoldberg/6926274 to your computer and use it in GitHub Desktop.
Save JulieGoldberg/6926274 to your computer and use it in GitHub Desktop.
A decorator around the WSGITileServer that allows for custom tilestache configuration.
from TileStache import WSGITileServer, splitPathInfo
import re
#
# Decorator for the WSGITileServer that allows for custom tilestache configuration.
#
# Takes in a tilestache config file and a series of parameter names. Any that are present will be sent to the
# provider and the cache classes on each call.
#
# If the URL is http://mytileserver.com/foo/45/bar/34/layer/x/y/z.png,
# it checks the cache and then optionally calls the provider as if
# http://mytileserver.com/layer/x/y/z.png were requested.
#
# Before the cache and/or provider is utilized for a given request, it
# checks each of those classes for a function named
# "set_tileserver_parameters". If it's there, it calls
# "set_tileserver_parameters({foo:45, bar:34})".
#
# Not all parameters must be sent on any call. If the syntax of the URL doesn't match or none are
# sent, it acts just like a regular WSGITileServer
#
# To run it, use:
# gunicorn --pythonpath $PWD "TileServer:DynamicLayersTileServer('tilestache.cfg', 'foo', 'bar')"
# gunicorn --pythonpath $PWD "TileServer:DynamicLayersTileServer('tilestache.cfg', 'foo', 'bar', 'baz')"
#
class ParameterParser():
def __init__(self, parameter_name):
self.parameter_name = parameter_name
#regex will parse out the parameter value from the path tilestache expects if it contains the parameter name
self.regex = re.compile("(?P<prefix>^.*)\/" + parameter_name + "\/(?P<value>\w+)\/(?P<suffix>.*)$")
def parse_out_parameter_value(self, string):
match = self.regex.match(string)
if match:
reassembled = "%s/%s" % (match.group('prefix'), match.group('suffix'))
return (match.group('value'), reassembled)
else:
return (None, string)
def has_parameter(self, string):
return bool(self.regex.match(string))
class DynamicLayersTileServer():
PARAMETER_SETTER_FUNCTION_NAME = "set_tileserver_parameters"
def __init__(self, config, *parameter_names):
self.tile_server = WSGITileServer(config)
self.parameter_parsers = [ParameterParser(parameter_name) for parameter_name in parameter_names]
def __call__(self, environ, start_response):
path_info = environ['PATH_INFO'] or ''
parameter_values = {}
for parser in self.parameter_parsers:
if parser.has_parameter(path_info):
(value, path_info) = parser.parse_out_parameter_value(path_info)
parameter_values[parser.parameter_name] = value
if parameter_values:
environ['PATH_INFO'] = path_info
layer_name = splitPathInfo(path_info)[0]
config = self.tile_server.config
layer = config.layers[layer_name]
self.__set_dynamic_parameters__(layer.provider, parameter_values)
self.__set_dynamic_parameters__(config.cache, parameter_values)
response = self.tile_server.__call__(environ, start_response)
return response
def __get_regex_variable_name__(self, parameter_name):
return parameter_name + "_value"
def __set_dynamic_parameters__(self, obj, parameter_values):
if hasattr(obj, DynamicLayersTileServer.PARAMETER_SETTER_FUNCTION_NAME):
getattr(obj, DynamicLayersTileServer.PARAMETER_SETTER_FUNCTION_NAME)(parameter_values)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment