Skip to content

Instantly share code, notes, and snippets.

@mbertrand
Forked from JulieGoldberg/DynamicLayersTileServer
Last active August 29, 2015 14:22
Show Gist options
  • Save mbertrand/4d20c1f94f6be14a02ef to your computer and use it in GitHub Desktop.
Save mbertrand/4d20c1f94f6be14a02ef to your computer and use it in GitHub Desktop.
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. They'll 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})".
#
# All parameters or none must be sent in a request, and when they're
# included, they're expected in the order that they're sent on the
# path. 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')"
#
class DynamicLayersTileServer():
PARAMETER_SETTER_FUNCTION_NAME = "set_tileserver_parameters"
def __init__(self, config, *parameter_names):
self.tile_server = WSGITileServer(config)
self.parameter_names = parameter_names
#regex to parse out the parameter value and the path tilestache expects if it starts with the parameter name
parameter_regex = ""
for parameter_name in parameter_names:
regex_variable_name = self.__get_regex_variable_name__(parameter_name)
parameter_regex += "\/" + parameter_name + "\/(?P<" + regex_variable_name + ">\w+)"
parameter_regex += "(?P<tilestache_path_info>\/.+$)"
self.parameter_regex = re.compile(parameter_regex)
def __call__(self, environ, start_response):
path_info = environ['PATH_INFO']
parsed_path = self.parameter_regex.match(path_info or '')
if parsed_path:
self.__update_config_with_dynamic_parameter_values__(self.tile_server.config, environ, parsed_path)
response = self.tile_server.__call__(environ, start_response)
return response
def __get_regex_variable_name__(self, parameter_name):
return parameter_name + "_value"
def __update_config_with_dynamic_parameter_values__(self, config, environ, parsed_path):
#Set PATH_INFO to what it would have been if we hadn't added our dynamic param
environ['PATH_INFO'] = parsed_path.group("tilestache_path_info")
#set our dynamic parameter on the provider for this layer
layer_name = splitPathInfo(environ['PATH_INFO'])[0]
layer = config.layers[layer_name]
parameter_values = {}
for parameter_name in self.parameter_names:
regex_variable_name = self.__get_regex_variable_name__(parameter_name)
parameter_value = parsed_path.group(regex_variable_name)
parameter_values[parameter_name] = parameter_value
self.__set_dynamic_parameters__(layer.provider, parameter_values)
self.__set_dynamic_parameters__(config.cache, parameter_values)
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