43 lines
1.7 KiB
Python
43 lines
1.7 KiB
Python
import logging
|
|
from pathlib import Path
|
|
import urllib.error
|
|
import urllib.request
|
|
|
|
from flask import Flask, send_file
|
|
|
|
|
|
def create_app(debug_mode: bool = False):
|
|
app = Flask('map_server', static_folder='public', static_url_path='/')
|
|
osm_timeout = 3
|
|
http_code_ok = 200
|
|
if not debug_mode:
|
|
log = logging.getLogger('werkzeug')
|
|
log.setLevel(logging.WARNING)
|
|
|
|
@app.route('/')
|
|
def _index():
|
|
return app.send_static_file('index.html')
|
|
|
|
@app.route('/<int:zoom>/<int:x>/<int:y>.png')
|
|
def _tile(zoom: int, x: int, y: int):
|
|
tile_path = Path('data', str(zoom), str(x), f'{y}.png')
|
|
if tile_path.exists():
|
|
return send_file(tile_path)
|
|
if not tile_path.parent.exists():
|
|
tile_path.parent.mkdir(parents=True, exist_ok=True)
|
|
request = urllib.request.Request(f'https://tile.openstreetmap.org/{zoom}/{x}/{y}.png')
|
|
request.add_header('User-Agent', 'Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0')
|
|
request.add_header('Accept', 'image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5')
|
|
request.add_header('Accept-Language', 'en-US,en;q=0.5')
|
|
request.add_header('Accept-Encoding', 'gzip, deflate, br, zstd')
|
|
try:
|
|
with urllib.request.urlopen(request, timeout=osm_timeout) as response:
|
|
if response.status != http_code_ok:
|
|
return (f'tile.openstreetmap.org answer is not OK (status: {response.status}) : {response.read()}',
|
|
501)
|
|
tile_path.write_bytes(response.read())
|
|
return send_file(tile_path)
|
|
except urllib.error.URLError as error:
|
|
return f'Cannot retrieve tile: {error}', 501
|
|
|
|
return app
|