map-machine/map_machine/slippy/server.py
2021-11-11 23:52:46 +03:00

85 lines
2.7 KiB
Python

"""
Map Machine tile server for slippy maps.
"""
import argparse
import logging
from http.server import HTTPServer, SimpleHTTPRequestHandler
from pathlib import Path
from typing import Optional
import cairosvg
from map_machine.map_configuration import MapConfiguration
from map_machine.slippy.tile import Tile
from map_machine.workspace import workspace
__author__ = "Sergey Vartanov"
__email__ = "me@enzet.ru"
class TileServerHandler(SimpleHTTPRequestHandler):
"""HTTP request handler that process sloppy map tile requests."""
cache: Path = Path("cache")
update_cache: bool = False
options: Optional[argparse.Namespace] = None
def __init__(
self,
request: bytes,
client_address: tuple[str, int],
server: HTTPServer,
) -> None:
# TODO: delete?
super().__init__(request, client_address, server)
def do_GET(self) -> None:
"""Serve a GET request."""
parts: list[str] = self.path.split("/")
if not (len(parts) == 5 and not parts[0] and parts[1] == "tiles"):
return
zoom_level: int = int(parts[2])
x: int = int(parts[3])
y: int = int(parts[4])
tile: Tile = Tile(x, y, zoom_level)
tile_path: Path = workspace.get_tile_path()
svg_path: Path = tile.get_file_name(tile_path)
png_path: Path = svg_path.with_suffix(".png")
if self.update_cache:
if not png_path.exists():
if not svg_path.exists():
tile.draw(
tile_path,
self.cache,
MapConfiguration(zoom_level=zoom_level),
)
with svg_path.open(encoding="utf-8") as input_file:
cairosvg.svg2png(
file_obj=input_file, write_to=str(png_path)
)
logging.info(f"SVG file is rasterized to {png_path}.")
if png_path.exists():
with png_path.open("rb") as input_file:
self.send_response(200)
self.send_header("Content-type", "image/png")
self.end_headers()
self.wfile.write(input_file.read())
return
def run_server(options: argparse.Namespace) -> None:
"""Command-line interface for tile server."""
server: Optional[HTTPServer] = None
try:
handler = TileServerHandler
handler.cache = Path(options.cache)
handler.options = options
server: HTTPServer = HTTPServer(("", options.port), handler)
logging.info(f"Server started on port {options.port}.")
server.serve_forever()
finally:
if server:
server.socket.close()