@@ -6,6 +6,11 @@
specified on the environment variable QGIS_SERVER_PORT.
QGIS_SERVER_HOST (defaults to 127.0.0.1)
A XYZ slippy maps service is also available for multithreading testing:
?MAP=/path/to/projects.qgs&SERVICE=XYZ&X=1&Y=0&Z=1&LAYERS=world
For testing purposes, HTTP Basic can be enabled by setting the following
environment variables:
@@ -49,9 +54,13 @@
import sys
import signal
import ssl
import math
import urllib .parse
from http .server import BaseHTTPRequestHandler , HTTPServer
from qgis .core import QgsApplication
from socketserver import ThreadingMixIn
import threading
from qgis .core import QgsApplication , QgsCoordinateTransform , QgsCoordinateReferenceSystem
from qgis .server import QgsServer , QgsServerRequest , QgsBufferServerRequest , QgsBufferServerResponse
QGIS_SERVER_PORT = int (os .environ .get ('QGIS_SERVER_PORT' , '8081' ))
@@ -100,6 +109,42 @@ def responseComplete(self):
qgs_server .serverInterface ().registerFilter (filter )
def num2deg (xtile , ytile , zoom ):
"""This returns the NW-corner of the square. Use the function with xtile+1 and/or ytile+1
to get the other corners. With xtile+0.5 & ytile+0.5 it will return the center of the tile."""
n = 2.0 ** zoom
lon_deg = xtile / n * 360.0 - 180.0
lat_rad = math .atan (math .sinh (math .pi * (1 - 2 * ytile / n )))
lat_deg = math .degrees (lat_rad )
return (lat_deg , lon_deg )
class XYZFilter (QgsServerFilter ):
"""XYZ server, example: ?MAP=/path/to/projects.qgs&SERVICE=XYZ&X=1&Y=0&Z=1&LAYERS=world"""
def requestReady (self ):
handler = self .serverInterface ().requestHandler ()
if handler .parameter ('SERVICE' ) == 'XYZ' :
x = int (handler .parameter ('X' ))
y = int (handler .parameter ('Y' ))
z = int (handler .parameter ('Z' ))
# NW corner
lat_deg , lon_deg = num2deg (x , y , z )
# SE corner
lat_deg2 , lon_deg2 = num2deg (x + 1 , y + 1 , z )
handler .setParameter ('SERVICE' , 'WMS' )
handler .setParameter ('REQUEST' , 'GetMap' )
handler .setParameter ('VERSION' , '1.3.0' )
handler .setParameter ('SRS' , 'EPSG:4326' )
handler .setParameter ('HEIGHT' , '256' )
handler .setParameter ('WIDTH' , '256' )
handler .setParameter ('BBOX' , "{},{},{},{}" .format (lat_deg2 , lon_deg , lat_deg , lon_deg2 ))
xyzfilter = XYZFilter (qgs_server .serverInterface ())
qgs_server .serverInterface ().registerFilter (xyzfilter )
class Handler (BaseHTTPRequestHandler ):
def do_GET (self , post_body = None ):
@@ -128,8 +173,13 @@ def do_POST(self):
return self .do_GET (post_body )
class ThreadedHTTPServer (ThreadingMixIn , HTTPServer ):
"""Handle requests in a separate thread."""
pass
if __name__ == '__main__' :
server = HTTPServer ((QGIS_SERVER_HOST , QGIS_SERVER_PORT ), Handler )
server = ThreadedHTTPServer ((QGIS_SERVER_HOST , QGIS_SERVER_PORT ), Handler )
if https :
server .socket = ssl .wrap_socket (server .socket ,
certfile = QGIS_SERVER_PKI_CERTIFICATE ,