update
This commit is contained in:
73
serve.py
Executable file
73
serve.py
Executable file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Local tile server for HK aerial map. Translates /tiles/{z}/{x}/{y}.jpg -> tiles/18_{x}_{y}.jpg"""
|
||||
|
||||
import http.server
|
||||
import socketserver
|
||||
import os
|
||||
import re
|
||||
import webbrowser
|
||||
import threading
|
||||
from pathlib import Path
|
||||
|
||||
PORT = 8080
|
||||
SCRIPT_DIR = Path(__file__).parent
|
||||
TRANSPARENT_GIF = (
|
||||
b'GIF89a\x01\x00\x01\x00\x80\x00\x00\xff\xff\xff\x00\x00\x00'
|
||||
b'!\xf9\x04\x00\x00\x00\x00\x00,\x00\x00\x00\x00\x01\x00\x01'
|
||||
b'\x00\x00\x02\x02D\x01\x00;'
|
||||
)
|
||||
|
||||
TILE_PATTERN = re.compile(
|
||||
r'^/(tiles(?:_annotated)?)/(\d+)/(\d+)/(\d+)\.(jpg|png|gif)$'
|
||||
)
|
||||
|
||||
|
||||
class Handler(http.server.SimpleHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
path = self.path.split('?')[0]
|
||||
m = TILE_PATTERN.match(path)
|
||||
if m:
|
||||
layer, z, x, y, ext = m.groups()
|
||||
# Tiles are stored as 18_x_y.jpg regardless of requested zoom
|
||||
flat = SCRIPT_DIR / layer / f'18_{x}_{y}.jpg'
|
||||
if flat.exists():
|
||||
data = flat.read_bytes()
|
||||
self.send_response(200)
|
||||
self.send_header('Content-Type', 'image/jpeg')
|
||||
self.send_header('Content-Length', len(data))
|
||||
self.send_header('Cache-Control', 'public, max-age=3600')
|
||||
self.end_headers()
|
||||
self.wfile.write(data)
|
||||
else:
|
||||
self.send_response(200)
|
||||
self.send_header('Content-Type', 'image/gif')
|
||||
self.send_header('Content-Length', len(TRANSPARENT_GIF))
|
||||
self.end_headers()
|
||||
self.wfile.write(TRANSPARENT_GIF)
|
||||
return
|
||||
|
||||
super().do_GET()
|
||||
|
||||
def log_message(self, fmt, *args):
|
||||
# Only log non-tile requests so output stays readable
|
||||
if not TILE_PATTERN.match(self.path.split('?')[0]):
|
||||
print(f' {self.address_string()} {fmt % args}')
|
||||
|
||||
|
||||
def main():
|
||||
os.chdir(SCRIPT_DIR)
|
||||
|
||||
with socketserver.TCPServer(('', PORT), Handler) as httpd:
|
||||
httpd.allow_reuse_address = True
|
||||
url = f'http://localhost:{PORT}/map.html'
|
||||
print(f'HK Aerial Map → {url}')
|
||||
print('Press Ctrl+C to stop.\n')
|
||||
threading.Timer(0.4, webbrowser.open, args=(url,)).start()
|
||||
try:
|
||||
httpd.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
print('\nServer stopped.')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user