Skip to content

Commit f29c9c9

Browse files
committedNov 9, 2017
[tests] Add XYX slippy map to test QGIS server
Plus: multi-threading server side (for speed) This is useful for testing various authentication shemes on a slippy-map server (that uses multi-threading in QGIS desktop)
1 parent 3fc4be3 commit f29c9c9

File tree

1 file changed

+52
-2
lines changed

1 file changed

+52
-2
lines changed
 

‎tests/src/python/qgis_wrapped_server.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
specified on the environment variable QGIS_SERVER_PORT.
77
QGIS_SERVER_HOST (defaults to 127.0.0.1)
88
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+
914
For testing purposes, HTTP Basic can be enabled by setting the following
1015
environment variables:
1116
@@ -49,9 +54,13 @@
4954
import sys
5055
import signal
5156
import ssl
57+
import math
5258
import urllib.parse
5359
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
5564
from qgis.server import QgsServer, QgsServerRequest, QgsBufferServerRequest, QgsBufferServerResponse
5665

5766
QGIS_SERVER_PORT = int(os.environ.get('QGIS_SERVER_PORT', '8081'))
@@ -100,6 +109,42 @@ def responseComplete(self):
100109
qgs_server.serverInterface().registerFilter(filter)
101110

102111

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+
103148
class Handler(BaseHTTPRequestHandler):
104149

105150
def do_GET(self, post_body=None):
@@ -128,8 +173,13 @@ def do_POST(self):
128173
return self.do_GET(post_body)
129174

130175

176+
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
177+
"""Handle requests in a separate thread."""
178+
pass
179+
180+
131181
if __name__ == '__main__':
132-
server = HTTPServer((QGIS_SERVER_HOST, QGIS_SERVER_PORT), Handler)
182+
server = ThreadedHTTPServer((QGIS_SERVER_HOST, QGIS_SERVER_PORT), Handler)
133183
if https:
134184
server.socket = ssl.wrap_socket(server.socket,
135185
certfile=QGIS_SERVER_PKI_CERTIFICATE,

0 commit comments

Comments
 (0)
Please sign in to comment.