|
6 | 6 | specified on the environment variable QGIS_SERVER_PORT.
|
7 | 7 | QGIS_SERVER_HOST (defaults to 127.0.0.1)
|
8 | 8 |
|
| 9 | +A XYZ slippy maps service is also available for multithreading testing: |
| 10 | +
|
| 11 | + ?MAP=/path/to/projects.qgs&SERVICE=XYZ&X=1&Y=0&Z=1&LAYERS=world |
| 12 | +
|
| 13 | +
|
9 | 14 | For testing purposes, HTTP Basic can be enabled by setting the following
|
10 | 15 | environment variables:
|
11 | 16 |
|
|
49 | 54 | import sys
|
50 | 55 | import signal
|
51 | 56 | import ssl
|
| 57 | +import math |
52 | 58 | import urllib.parse
|
53 | 59 | from http.server import BaseHTTPRequestHandler, HTTPServer
|
54 |
| -from qgis.core import QgsApplication |
| 60 | +from socketserver import ThreadingMixIn |
| 61 | +import threading |
| 62 | + |
| 63 | +from qgis.core import QgsApplication, QgsCoordinateTransform, QgsCoordinateReferenceSystem |
55 | 64 | from qgis.server import QgsServer, QgsServerRequest, QgsBufferServerRequest, QgsBufferServerResponse
|
56 | 65 |
|
57 | 66 | QGIS_SERVER_PORT = int(os.environ.get('QGIS_SERVER_PORT', '8081'))
|
@@ -100,6 +109,42 @@ def responseComplete(self):
|
100 | 109 | qgs_server.serverInterface().registerFilter(filter)
|
101 | 110 |
|
102 | 111 |
|
| 112 | +def num2deg(xtile, ytile, zoom): |
| 113 | + """This returns the NW-corner of the square. Use the function with xtile+1 and/or ytile+1 |
| 114 | + to get the other corners. With xtile+0.5 & ytile+0.5 it will return the center of the tile.""" |
| 115 | + n = 2.0 ** zoom |
| 116 | + lon_deg = xtile / n * 360.0 - 180.0 |
| 117 | + lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * ytile / n))) |
| 118 | + lat_deg = math.degrees(lat_rad) |
| 119 | + return (lat_deg, lon_deg) |
| 120 | + |
| 121 | + |
| 122 | +class XYZFilter(QgsServerFilter): |
| 123 | + """XYZ server, example: ?MAP=/path/to/projects.qgs&SERVICE=XYZ&X=1&Y=0&Z=1&LAYERS=world""" |
| 124 | + |
| 125 | + def requestReady(self): |
| 126 | + handler = self.serverInterface().requestHandler() |
| 127 | + if handler.parameter('SERVICE') == 'XYZ': |
| 128 | + x = int(handler.parameter('X')) |
| 129 | + y = int(handler.parameter('Y')) |
| 130 | + z = int(handler.parameter('Z')) |
| 131 | + # NW corner |
| 132 | + lat_deg, lon_deg = num2deg(x, y, z) |
| 133 | + # SE corner |
| 134 | + lat_deg2, lon_deg2 = num2deg(x + 1, y + 1, z) |
| 135 | + handler.setParameter('SERVICE', 'WMS') |
| 136 | + handler.setParameter('REQUEST', 'GetMap') |
| 137 | + handler.setParameter('VERSION', '1.3.0') |
| 138 | + handler.setParameter('SRS', 'EPSG:4326') |
| 139 | + handler.setParameter('HEIGHT', '256') |
| 140 | + handler.setParameter('WIDTH', '256') |
| 141 | + handler.setParameter('BBOX', "{},{},{},{}".format(lat_deg2, lon_deg, lat_deg, lon_deg2)) |
| 142 | + |
| 143 | + |
| 144 | +xyzfilter = XYZFilter(qgs_server.serverInterface()) |
| 145 | +qgs_server.serverInterface().registerFilter(xyzfilter) |
| 146 | + |
| 147 | + |
103 | 148 | class Handler(BaseHTTPRequestHandler):
|
104 | 149 |
|
105 | 150 | def do_GET(self, post_body=None):
|
@@ -128,8 +173,13 @@ def do_POST(self):
|
128 | 173 | return self.do_GET(post_body)
|
129 | 174 |
|
130 | 175 |
|
| 176 | +class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): |
| 177 | + """Handle requests in a separate thread.""" |
| 178 | + pass |
| 179 | + |
| 180 | + |
131 | 181 | if __name__ == '__main__':
|
132 |
| - server = HTTPServer((QGIS_SERVER_HOST, QGIS_SERVER_PORT), Handler) |
| 182 | + server = ThreadedHTTPServer((QGIS_SERVER_HOST, QGIS_SERVER_PORT), Handler) |
133 | 183 | if https:
|
134 | 184 | server.socket = ssl.wrap_socket(server.socket,
|
135 | 185 | certfile=QGIS_SERVER_PKI_CERTIFICATE,
|
|
0 commit comments