diff --git a/src/c3nav/tileserver/wsgi.py b/src/c3nav/tileserver/wsgi.py index c28a44ee..63b7bbeb 100644 --- a/src/c3nav/tileserver/wsgi.py +++ b/src/c3nav/tileserver/wsgi.py @@ -3,7 +3,6 @@ import logging import os import re import time -from http.cookies import SimpleCookie from io import BytesIO import requests @@ -19,7 +18,8 @@ logger = logging.getLogger('c3nav') class TileServer: - regex = re.compile(r'^/(?P\d+)/(?P\d+)/(?P-?\d+)/(?P-?\d+).png$') + path_regex = re.compile(r'^/(\d+)/(\d+)/(-?\d+)/(-?\d+).png$') + cookie_regex = re.compile(r'[^ ]c3nav_tile_access=([^; ])') def __init__(self): try: @@ -86,11 +86,13 @@ class TileServer: return [text] def __call__(self, env, start_response): - match = self.regex.match(env['PATH_INFO']) + match = self.path_regex.match(env['PATH_INFO']) if match is None: return self.not_found(start_response, b'invalid tile path.') - zoom = int(match.group('zoom')) + level, zoom, x, y = match.groups() + + zoom = int(zoom) if not (0 <= zoom <= 10): return self.not_found(start_response, b'zoom out of bounds.') @@ -98,25 +100,25 @@ class TileServer: cache_package = self.cache_package # check if bounds are valid - x = int(match.group('x')) - y = int(match.group('y')) + x = int(x) + y = int(y) minx, miny, maxx, maxy = get_tile_bounds(zoom, x, y) if not cache_package.bounds_valid(minx, miny, maxx, maxy): return self.not_found(start_response, b'coordinates out of bounds.') # get level - level = int(match.group('level')) + level = int(level) level_data = cache_package.levels.get(level) if level_data is None: return self.not_found(start_response, b'invalid level.') # decode access permissions - try: - cookie = SimpleCookie(env['HTTP_COOKIE'])['c3nav_tile_access'].value - except KeyError: - access_permissions = set() - else: - access_permissions = parse_tile_access_cookie(cookie, self.tile_secret) + cookie = env.get('HTTP_COOKIE', None) + if cookie: + cookie = self.cookie_regex.match(cookie) + if cookie: + cookie = cookie.group(0) + access_permissions = parse_tile_access_cookie(cookie, self.tile_secret) if cookie else set() # only access permissions that are affecting this tile access_permissions &= set(level_data.restrictions[minx:miny, maxx:maxy]) @@ -127,11 +129,12 @@ class TileServer: access_cache_key = build_access_cache_key(access_permissions) # check browser cache - tile_etag = build_tile_etag(level, zoom, x, y, base_cache_key, access_cache_key, self.tile_secret) if_none_match = env.get('HTTP_IF_NONE_MATCH') - if if_none_match == tile_etag: - start_response('304 Not Modified', [('Content-Type', 'text/plain'), ('ETag', tile_etag)]) - return [b''] + if if_none_match: + tile_etag = build_tile_etag(level, zoom, x, y, base_cache_key, access_cache_key, self.tile_secret) + if if_none_match == tile_etag: + start_response('304 Not Modified', [('Content-Type', 'text/plain'), ('ETag', tile_etag)]) + return [b''] r = requests.get('%s/map/%d/%d/%d/%d/%s.png' % (self.upstream_base, level, zoom, x, y, access_cache_key), headers=self.auth_headers)