#!/usr/bin/env python """ This is a simple vector tile server that returns a PBF tile for /tiles/{z}/{x}/{y}.pbf requests Use these environment variables to configure PostgreSQL access: POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DB, POSTGRES_PASSWORD Usage: server [--fname ] [--port ] server --help server --version SQL file generated by generate-sqltomvt script with the --prepared flag Options: --fname= Name of the generated function [default: gettile] -p --port= Serve on this port [default: 8080] --help Show this screen. --version Show version. """ import tornado.ioloop import tornado.web import io import os from docopt import docopt from sqlalchemy import create_engine, inspect from sqlalchemy.orm import sessionmaker class GetTile(tornado.web.RequestHandler): def initialize(self, session, query): self.db_session = session self.db_query = query def get(self, z, x, y): z, x, y = int(z), int(x), int(y) try: result = self.db_session.execute(self.db_query, params=dict(z=z, x=x, y=y)).fetchall() if result: self.set_header("Content-Type", "application/x-protobuf") self.set_header("Content-Disposition", "attachment") self.set_header("Access-Control-Allow-Origin", "*") value = io.BytesIO(result[0][0]).getvalue() self.write(value) print('{0},{1},{2} returned {3} bytes'.format(z, x, y, len(value))) else: self.clear() self.set_status(404) print('Got NULL result for {0},{1},{2}'.format(z, x, y)) except Exception as err: print('{0},{1},{2} threw an exception {3}'.format(z, x, y, err)) raise def main(args): sqlfile = args[''] with open(sqlfile, 'r') as stream: prepared = stream.read() pghost = os.getenv('POSTGRES_HOST', 'localhost') + ':' + os.getenv('POSTGRES_PORT', '5432') pgdb = os.getenv('POSTGRES_DB', 'openmaptiles') pgcreds = os.getenv('POSTGRES_USER', 'openmaptiles') + ':' + os.getenv('POSTGRES_PASSWORD', 'openmaptiles') engine = create_engine('postgresql://' + pgcreds + '@' + pghost + '/' + pgdb) print('Connecting to PostgreSQL at {0}, db={1}'.format(pghost, pgdb)) inspector = inspect(engine) session = sessionmaker(bind=engine)() session.execute(prepared) query = "EXECUTE {0}(:z, :x, :y)".format(args['--fname']) print('Loaded {0}, will use "{1}" to get vector tiles.'.format(sqlfile, query)) port = int(args['--port']) application = tornado.web.Application([( r"/tiles/([0-9]+)/([0-9]+)/([0-9]+).pbf", GetTile, dict(session=session, query=query) )]) application.listen(port) print("Postserve started, listening on 0.0.0.0:{0}".format(port)) tornado.ioloop.IOLoop.instance().start() if __name__ == "__main__": main(docopt(__doc__, version="1.0"))