Forked from JulieGoldberg/DynamicLayersTileServer
Last active
August 29, 2015 14:22
-
-
Save mbertrand/4d20c1f94f6be14a02ef to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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