def test_project_json(self): """Test landing page project call in JSON format""" # Get hashes for test projects request = QgsBufferServerRequest('http://server.qgis.org/index.json') request.setHeader('Accept', 'application/json') response = QgsBufferServerResponse() self.server.handleRequest(request, response) j = json.loads(bytes(response.body())) test_projects = { p['id']: p['title'].replace(' ', '_') for p in j['projects'] } for identifier, name in test_projects.items(): request = QgsBufferServerRequest('http://server.qgis.org/map/' + identifier) request.setHeader('Accept', 'application/json') self.compareApi(request, None, 'test_project_{}.json'.format( name.replace('.', '_')), subdir='landingpage')
def test_statusCode(self): """Test return status HTTP code""" response = QgsBufferServerResponse() response.setStatusCode(222) self.assertEqual(response.statusCode(), 222)
def _assert_status_code(self, status_code, qs, requestMethod=QgsServerRequest.GetMethod, data=None, project=None): request = QgsBufferServerRequest(qs, requestMethod, {}, data) response = QgsBufferServerResponse() self.server.handleRequest(request, response, project) assert response.statusCode() == status_code, "%s != %s" % (response.statusCode(), status_code)
def testOgcApiHandler(self): """Test OGC API Handler""" project = QgsProject() project.read(unitTestDataPath('qgis_server') + '/test_project.qgs') request = QgsBufferServerRequest( 'http://server.qgis.org/wfs3/collections/testlayer%20èé/items?limit=-1' ) response = QgsBufferServerResponse() ctx = QgsServerApiContext('/services/api1', request, response, project, self.server.serverInterface()) h = Handler1() self.assertTrue( h.staticPath(ctx).endswith('/resources/server/api/ogc/static')) self.assertEqual(h.path(), QtCore.QRegularExpression("/handlerone")) self.assertEqual(h.description(), 'The first handler ever') self.assertEqual(h.operationId(), 'handlerOne') self.assertEqual(h.summary(), 'First of its name') self.assertEqual(h.linkTitle(), 'Handler One Link Title') self.assertEqual(h.linkType(), QgsServerOgcApi.data) with self.assertRaises(QgsServerApiBadRequestException) as ex: h.handleRequest(ctx) self.assertEqual(str(ex.exception), 'Missing required argument: \'value1\'') r = ctx.response() self.assertEqual(r.data(), '') with self.assertRaises(QgsServerApiBadRequestException) as ex: h.values(ctx) self.assertEqual(str(ex.exception), 'Missing required argument: \'value1\'') # Add handler to API and test for /api2 ctx = QgsServerApiContext('/services/api2', request, response, project, self.server.serverInterface()) api = QgsServerOgcApi(self.server.serverInterface(), '/api2', 'apitwo', 'a second api', '1.2') api.registerHandler(h) # Add a second handler (will be tested later) h2 = Handler2() api.registerHandler(h2) ctx.request().setUrl(QtCore.QUrl('http://www.qgis.org/services/api1')) with self.assertRaises(QgsServerApiBadRequestException) as ex: api.executeRequest(ctx) self.assertEqual( str(ex.exception), 'Requested URI does not match any registered API handler') ctx.request().setUrl(QtCore.QUrl('http://www.qgis.org/services/api2')) with self.assertRaises(QgsServerApiBadRequestException) as ex: api.executeRequest(ctx) self.assertEqual( str(ex.exception), 'Requested URI does not match any registered API handler') ctx.request().setUrl( QtCore.QUrl('http://www.qgis.org/services/api2/handlerone')) with self.assertRaises(QgsServerApiBadRequestException) as ex: api.executeRequest(ctx) self.assertEqual(str(ex.exception), 'Missing required argument: \'value1\'') ctx.request().setUrl( QtCore.QUrl( 'http://www.qgis.org/services/api2/handlerone?value1=not+a+double' )) with self.assertRaises(QgsServerApiBadRequestException) as ex: api.executeRequest(ctx) self.assertEqual( str(ex.exception), 'Argument \'value1\' could not be converted to Double') ctx.request().setUrl( QtCore.QUrl( 'http://www.qgis.org/services/api2/handlerone?value1=1.2345')) params = h.values(ctx) self.assertEqual(params, {'value1': 1.2345}) api.executeRequest(ctx) self.assertEqual( json.loads(bytes(ctx.response().data()))['value1'], 1.2345) # Test path fragments extraction ctx.request().setUrl( QtCore.QUrl( 'http://www.qgis.org/services/api2/handlertwo/00/555?value1=1.2345' )) params = h2.values(ctx) self.assertEqual(params, { 'code1': '00', 'value1': 1.2345, 'value2': None }) # Test string encoding ctx.request().setUrl( QtCore.QUrl( 'http://www.qgis.org/services/api2/handlertwo/00/555?value1=1.2345&value2=a%2Fstring%20some' )) params = h2.values(ctx) self.assertEqual(params, { 'code1': '00', 'value1': 1.2345, 'value2': 'a/string some' }) # Test links self.assertEqual( h2.href(ctx), 'http://www.qgis.org/services/api2/handlertwo/00/555?value1=1.2345&value2=a%2Fstring%20some' ) self.assertEqual( h2.href(ctx, '/extra'), 'http://www.qgis.org/services/api2/handlertwo/00/555/extra?value1=1.2345&value2=a%2Fstring%20some' ) self.assertEqual( h2.href(ctx, '/extra', 'json'), 'http://www.qgis.org/services/api2/handlertwo/00/555/extra.json?value1=1.2345&value2=a%2Fstring%20some' ) # Test template path self.assertTrue( h2.templatePath(ctx).endswith( '/resources/server/api/ogc/templates/services/api2/handlerTwo.html' ))
def compareContentType(self, url, headers, content_type): request = QgsBufferServerRequest(url, headers=headers) response = QgsBufferServerResponse() self.server.handleRequest(request, response, QgsProject()) self.assertEqual(response.headers()['Content-Type'], content_type)
def baseDoRequest(self, q): request = self.request # Uppercase REQUEST if 'REQUEST' in [k.upper() for k in q.keys()]: if request.method == 'GET': ows_request = q['REQUEST'].upper() else: if request.content_type == 'application/x-www-form-urlencoded': ows_request = request.POST['REQUEST'].upper() else: ows_request = request.POST['REQUEST'][0].upper() q['REQUEST'] = ows_request # FIXME: proxy or redirect in case of WMS/WFS/XYZ cascading? qgs_project = get_qgs_project(self.project.qgis_file.path) if qgs_project is None: raise Http404('The requested QGIS project could not be loaded!') data = None if request.method == 'GET': method = QgsBufferServerRequest.GetMethod elif request.method == 'POST': method = QgsBufferServerRequest.PostMethod data = request.body elif request.method == 'PUT': method = QgsBufferServerRequest.PutMethod data = request.body elif request.method == 'PATCH': method = QgsBufferServerRequest.PatchMethod data = request.body elif request.method == 'HEAD': method = QgsBufferServerRequest.HeadMethod elif request.method == 'DELETE': method = QgsBufferServerRequest.DeleteMethod else: logger.warning("Request method not supported: %s, assuming GET" % request.method) method = QgsBufferServerRequest.GetMethod headers = {} for header_key in request.headers.keys(): headers[header_key] = request.headers.get(header_key) uri = request.build_absolute_uri(request.path) + '?' + q.urlencode() logger.debug('Calling QGIS Server: %s' % uri) qgs_request = QgsBufferServerRequest(uri, method, headers, data) # Attach user and project to the server object to make them accessible by the # server access control plugins (constraints etc.) QGS_SERVER.user = request.user QGS_SERVER.project = self.project qgs_response = QgsBufferServerResponse() try: QGS_SERVER.handleRequest(qgs_request, qgs_response, qgs_project) except Exception as ex: return HttpResponseServerError( reason="Error handling server request: %s" % ex) response = HttpResponse(bytes(qgs_response.body())) response.status_code = qgs_response.statusCode() for key, value in qgs_response.headers().items(): response[key] = value return response
def _test_error(uri): request = QgsBufferServerRequest(uri) request.setHeader('Accept', 'application/json') response = QgsBufferServerResponse() self.server.handleRequest(request, response) self.assertEqual(bytes(response.body()), b'<ServerException>Project file error. For OWS services: please provide a SERVICE and a MAP parameter pointing to a valid QGIS project file</ServerException>\n')
def test_wms_getprint_maptheme(self): """Test project has 2 layer: red and green and three templates: red: follow map theme red green: follow map theme green blank: no map theme """ tmp_dir = QTemporaryDir() shutil.copyfile( os.path.join(unitTestDataPath('qgis_server'), 'test_project_mapthemes.qgs'), os.path.join(tmp_dir.path(), 'test_project_mapthemes.qgs')) shutil.copyfile( os.path.join(unitTestDataPath('qgis_server'), 'test_project_mapthemes.gpkg'), os.path.join(tmp_dir.path(), 'test_project_mapthemes.gpkg')) project = QgsProject() self.assertTrue( project.read( os.path.join(tmp_dir.path(), 'test_project_mapthemes.qgs'))) params = { "SERVICE": "WMS", "VERSION": "1.3", "REQUEST": "GetPrint", "TEMPLATE": "blank", "FORMAT": "png", "LAYERS": "", "map0:EXTENT": "44.92867722467413216,7.097696894150993252,45.0714498943264914,7.378188333645007368", "map0:LAYERS": "red", "CRS": "EPSG:4326", "DPI": '72' } polygon = 'POLYGON((7.09769689415099325 44.92867722467413216, 7.37818833364500737 44.92867722467413216, 7.37818833364500737 45.0714498943264914, 7.09769689415099325 45.0714498943264914, 7.09769689415099325 44.92867722467413216))' ###################################################### # Template map theme tests, no HIGHLIGHT # blank template, specified layer is red response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertRed(image.pixelColor(100, 100)) # blank template, specified layer is green params["map0:LAYERS"] = "green" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertGreen(image.pixelColor(100, 100)) # red template, no specified layers params["map0:LAYERS"] = "" params["TEMPLATE"] = "red" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertRed(image.pixelColor(100, 100)) # green template, no specified layers params["map0:LAYERS"] = "" params["TEMPLATE"] = "green" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertGreen(image.pixelColor(100, 100)) # green template, specified layer is red # This is a conflict situation: the green template map is set to follow green theme # but we tell the server to render the red layer, red is what we get. params["map0:LAYERS"] = "red" params["TEMPLATE"] = "green" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertRed(image.pixelColor(100, 100)) ###################################################### # Start HIGHLIGHT tests params["TEMPLATE"] = "blank" params["map0:LAYERS"] = "red" params["map0:HIGHLIGHT_GEOM"] = polygon params[ "map0:HIGHLIGHT_SYMBOL"] = r'<StyledLayerDescriptor><UserStyle><FeatureTypeStyle><Rule><PolygonSymbolizer><Fill><CssParameter name="fill">%230000FF</CssParameter></Fill></PolygonSymbolizer></Rule></FeatureTypeStyle></UserStyle></StyledLayerDescriptor>' response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertBlue(image.pixelColor(100, 100)) # Test highlight without layers params["TEMPLATE"] = "blank" params["map0:LAYERS"] = "" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertBlue(image.pixelColor(100, 100)) # Test highlight on follow theme (issue GH #34178) params["TEMPLATE"] = "red" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertBlue(image.pixelColor(100, 100)) # Test highlight on follow theme (issue GH #34178) params["TEMPLATE"] = "green" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertBlue(image.pixelColor(100, 100)) # Test highlight on follow theme, but add LAYERS (issue GH #34178) params["TEMPLATE"] = "green" params["LAYERS"] = "red" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertBlue(image.pixelColor(100, 100))
def test_landing_page(self): request = QgsBufferServerRequest('/') response = QgsBufferServerResponse() self.server.handleRequest(request, response) self.assertTrue(b'html' in bytes(response.body()), response.body()) self.assertEqual(response.statusCode(), 200)
def baseDoRequest(self, q): request = self.request # Uppercase REQUEST if 'REQUEST' in [k.upper() for k in q.keys()]: if request.method == 'GET': ows_request = q['REQUEST'].upper() else: if request.content_type == 'application/x-www-form-urlencoded': ows_request = request.POST['REQUEST'].upper() else: ows_request = request.POST['REQUEST'][0].upper() q['REQUEST'] = ows_request # FIXME: proxy or redirect in case of WMS/WFS/XYZ cascading? qgs_project = get_qgs_project(self.project.qgis_file.path) if qgs_project is None: raise Http404('The requested QGIS project could not be loaded!') data = None if request.method == 'GET': method = QgsBufferServerRequest.GetMethod elif request.method == 'POST': method = QgsBufferServerRequest.PostMethod data = request.body elif request.method == 'PUT': method = QgsBufferServerRequest.PutMethod data = request.body elif request.method == 'PATCH': method = QgsBufferServerRequest.PatchMethod data = request.body elif request.method == 'HEAD': method = QgsBufferServerRequest.HeadMethod elif request.method == 'DELETE': method = QgsBufferServerRequest.DeleteMethod else: logger.warning( "Request method not supported: %s, assuming GET" % request.method) method = QgsBufferServerRequest.GetMethod headers = {} for header_key in request.headers.keys(): headers[header_key] = request.headers.get(header_key) uri = request.build_absolute_uri(request.path) + '?' + q.urlencode() logger.debug('Calling QGIS Server: %s' % uri) qgs_request = QgsBufferServerRequest(uri, method, headers, data) # Attach user and project to the server object to make them accessible by the # server access control plugins (constraints etc.) QGS_SERVER.djrequest = request QGS_SERVER.user = request.user QGS_SERVER.project = self.project # For GetPrint QGIS functions that rely on layers visibility, we need to check # the layers from LAYERS use_ids = QgsServerProjectUtils.wmsUseLayerIds(qgs_project) tree_root = qgs_project.layerTreeRoot() # Loop through the layers and make them visible for layer_name in qgs_request.queryParameter('LAYERS').split(','): layer_name = urllib.parse.unquote(layer_name) layer = None if use_ids: layer = qgs_project.mapLayer(layer_name) else: try: layer = qgs_project.mapLayersByName(layer_name)[0] except: # short name? for l in qgs_project.mapLayers().values(): if l.shortName() == layer_name: layer = l break if layer is None: logger.warning( 'Could not find layer "{}" when configuring OWS call'.format(layer_name)) else: layer_node = tree_root.findLayer(layer) if layer_node is not None: layer_node.setItemVisibilityCheckedParentRecursive(True) else: logger.warning( 'Could not find layer tree node "{}" when configuring OWS call'.format(layer_name)) qgs_response = QgsBufferServerResponse() try: QGS_SERVER.handleRequest(qgs_request, qgs_response, qgs_project) except Exception as ex: return HttpResponseServerError(reason="Error handling server request: %s" % ex) response = HttpResponse(bytes(qgs_response.body())) response.status_code = qgs_response.statusCode() for key, value in qgs_response.headers().items(): response[key] = value return response
def test_wms_getprint_maptheme(self): """Test templates green and red have 2 layers: red and green template red: follow map theme red template green: follow map theme green template blank: no map theme """ project = self.project params = { "SERVICE": "WMS", "VERSION": "1.3.0", "REQUEST": "GetPrint", "TEMPLATE": "blank", "FORMAT": "png", "LAYERS": "", "map0:EXTENT": "44.92867722467413216,7.097696894150993252,45.0714498943264914,7.378188333645007368", "map0:LAYERS": "red", "CRS": "EPSG:4326", "DPI": '72' } ###################################################### # Template map theme tests, no HIGHLIGHT # blank template, specified layer is red response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertRed(image.pixelColor(100, 100)) # blank template, specified layer is green params["map0:LAYERS"] = "green" response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertGreen(image.pixelColor(100, 100)) # red template, no specified layers params["map0:LAYERS"] = "" params["TEMPLATE"] = "red" response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertRed(image.pixelColor(100, 100)) # green template, no specified layers params["map0:LAYERS"] = "" params["TEMPLATE"] = "green" response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertGreen(image.pixelColor(100, 100)) # green template, specified layer is red # This is a conflict situation: the green template map is set to follow green theme # but we tell the server to render the red layer, red is what we get. params["map0:LAYERS"] = "red" params["TEMPLATE"] = "green" response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertRed(image.pixelColor(100, 100)) # Same situation as above but LAYERS is not map0 prefixed params["LAYERS"] = "red" params["TEMPLATE"] = "green" response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertRed(image.pixelColor(100, 100)) # Same as above but we have a conflict situation: we pass both LAYERS # and map0:LAYERS, the second must prevail because it is more specific params["LAYERS"] = "red" params["map0:LAYERS"] = "green" params["TEMPLATE"] = "red" response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertGreen(image.pixelColor(100, 100))
def test_wms_getprint_maptheme_highlight(self): """Test templates green and red have 2 layers: red and green template red: follow map theme red template green: follow map theme green template blank: no map theme """ project = self.project params = { 'SERVICE': 'WMS', 'VERSION': '1.3.0', 'REQUEST': 'GetPrint', 'TEMPLATE': 'blank', 'FORMAT': 'png', 'LAYERS': '', 'map0:EXTENT': '44.92867722467413216,7.097696894150993252,45.0714498943264914,7.378188333645007368', 'map0:LAYERS': 'red', 'CRS': 'EPSG:4326', 'DPI': '72', 'map0:HIGHLIGHT_GEOM': self.polygon, 'map0:HIGHLIGHT_SYMBOL': r'<StyledLayerDescriptor><UserStyle><FeatureTypeStyle><Rule><PolygonSymbolizer><Fill><CssParameter name="fill">%230000FF</CssParameter></Fill></PolygonSymbolizer></Rule></FeatureTypeStyle></UserStyle></StyledLayerDescriptor>' } response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertBlue(image.pixelColor(100, 100)) # Test highlight without layers params["TEMPLATE"] = "blank" params["map0:LAYERS"] = "" response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertBlue(image.pixelColor(100, 100)) # Test highlight on follow theme (issue GH #34178) params["TEMPLATE"] = "red" response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertBlue(image.pixelColor(100, 100)) # Test highlight on follow theme (issue GH #34178) params["TEMPLATE"] = "green" response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertBlue(image.pixelColor(100, 100)) # Test highlight on follow theme, but add LAYERS (issue GH #34178) params["TEMPLATE"] = "green" params["LAYERS"] = "red" response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") self._assertBlue(image.pixelColor(100, 100))
def test_wms_getprint_maptheme_multiple_maps(self): """Test template points has 4 layers: points_black, points_red, points_green, points_blue the template has two maps (from top to bottom) map1 and map0 using respectively the 4points-red and 4points-green map themes """ project = self.project # No LAYERS specified params = { 'SERVICE': 'WMS', 'VERSION': '1.3.0', 'REQUEST': 'GetPrint', 'TEMPLATE': 'points', 'FORMAT': 'png', 'map0:EXTENT': '44.66151222233335716,6.71202136069002187,45.25042454764368927,7.83398711866607833', 'CRS': 'EPSG:4326', 'DPI': '72', 'map1:EXTENT': '44.66151222233335716,6.71202136069002187,45.25042454764368927,7.83398711866607833' } response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Expected: green and red # map1 (top map) self._assertRed(image.pixelColor(325, 184)) # RED self._assertWhite(image.pixelColor(474, 184)) # GREEN self._assertWhite(image.pixelColor(332, 262)) # BLUE self._assertWhite(image.pixelColor(485, 258)) # BLACK # map0 (bottom map) self._assertWhite(image.pixelColor(315, 461)) # RED self._assertGreen(image.pixelColor(475, 473)) # GREEN self._assertWhite(image.pixelColor(329, 553)) # BLUE self._assertWhite(image.pixelColor(481, 553)) # BLACK # Black LAYERS params["LAYERS"] = "points_black" response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Expected black # map1 (top map) self._assertWhite(image.pixelColor(325, 184)) # RED self._assertWhite(image.pixelColor(474, 184)) # GREEN self._assertWhite(image.pixelColor(332, 262)) # BLUE self._assertBlack(image.pixelColor(485, 258)) # BLACK # map0 (bottom map) self._assertWhite(image.pixelColor(315, 461)) # RED self._assertWhite(image.pixelColor(475, 473)) # GREEN self._assertWhite(image.pixelColor(329, 553)) # BLUE self._assertBlack(image.pixelColor(481, 553)) # BLACK # Black map0:LAYERS del params["LAYERS"] params["map0:LAYERS"] = "points_black" response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Expected black on map0, green on map1 # map1 (top map) self._assertRed(image.pixelColor(325, 184)) # RED self._assertWhite(image.pixelColor(474, 184)) # GREEN self._assertWhite(image.pixelColor(332, 262)) # BLUE self._assertWhite(image.pixelColor(485, 258)) # BLACK # map0 (bottom map) self._assertWhite(image.pixelColor(315, 461)) # RED self._assertWhite(image.pixelColor(475, 473)) # GREEN self._assertWhite(image.pixelColor(329, 553)) # BLUE self._assertBlack(image.pixelColor(481, 553)) # BLACK # Conflicting information: Black LAYERS and Green map0:LAYERS # The second gets precedence on map0 while LAYERS is applied to map1 params["map0:LAYERS"] = "points_blue" params["LAYERS"] = "points_black" response = QgsBufferServerResponse() request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Expected green on map0, black on map1 # map1 (top map) self._assertWhite(image.pixelColor(325, 184)) # RED self._assertWhite(image.pixelColor(474, 184)) # GREEN self._assertWhite(image.pixelColor(332, 262)) # BLUE self._assertBlack(image.pixelColor(485, 258)) # BLACK # map0 (bottom map) self._assertWhite(image.pixelColor(315, 461)) # RED self._assertWhite(image.pixelColor(475, 473)) # GREEN self._assertBlue(image.pixelColor(329, 553)) # BLUE self._assertWhite(image.pixelColor(481, 553)) # BLACK
def test_atlas(self): """Test atlas""" qs = "?" + "&".join([ "%s=%s" % i for i in list({ 'SERVICE': "WMS", 'VERSION': "1.3.0", 'REQUEST': "GetPrint", 'CRS': 'EPSG:4326', 'FORMAT': 'png', 'LAYERS': 'multiple_pks', 'DPI': 72, 'TEMPLATE': "print1", }.items()) ]) req = QgsBufferServerRequest('http://my_server/' + qs + '&ATLAS_PK=1,2') res = QgsBufferServerResponse() self._server.handleRequest(req, res, self.test_project) self.assertEqual(res.statusCode(), 200) result_path = os.path.join(self.temp_dir.path(), 'atlas_1_2.png') with open(result_path, 'wb+') as f: f.write(res.body()) # A full red image is expected image = QImage(result_path) self.assertFalse(image.isGrayscale()) color = image.pixelColor(100, 100) self.assertEqual(color.red(), 255) self.assertEqual(color.green(), 0) self.assertEqual(color.blue(), 0) # Forbid 1-1 self._accesscontrol.active['layerFilterSubsetString'] = True self._check_exception(qs + '&ATLAS_PK=1,2', "Atlas error: empty atlas.") self._accesscontrol.active['layerFilterSubsetString'] = False self._accesscontrol.active['layerFilterExpression'] = True self._check_exception(qs + '&ATLAS_PK=1,2', "Atlas error: empty atlas.") # Remove all constraints self._clear_constraints() req = QgsBufferServerRequest('http://my_server/' + qs + '&ATLAS_PK=1,2') res = QgsBufferServerResponse() self._server.handleRequest(req, res, self.test_project) self.assertEqual(res.statusCode(), 200) result_path = os.path.join(self.temp_dir.path(), 'atlas_1_2.png') with open(result_path, 'wb+') as f: f.write(res.body()) # A full red image is expected image = QImage(result_path) self.assertFalse(image.isGrayscale()) color = image.pixelColor(100, 100) self.assertEqual(color.red(), 255) self.assertEqual(color.green(), 0) self.assertEqual(color.blue(), 0)
def test_wms_getprint_postgres(self): """Test issue GH #41800 """ # Extent for feature where pk1 = 1, pk2 = 2 qs = "?" + "&".join([ "%s=%s" % i for i in list({ 'SERVICE': "WMS", 'VERSION': "1.3.0", 'REQUEST': "GetPrint", 'CRS': 'EPSG:4326', 'FORMAT': 'png', 'LAYERS': 'multiple_pks', 'DPI': 72, 'TEMPLATE': "print1", 'map0:EXTENT': '45.70487804878048621,7.67926829268292099,46.22987804878049189,8.42479674796748235', }.items()) ]) def _check_red(): req = QgsBufferServerRequest('http://my_server/' + qs) res = QgsBufferServerResponse() self._server.handleRequest(req, res, self.test_project) self.assertEqual(res.statusCode(), 200) result_path = os.path.join(self.temp_dir.path(), 'red.png') with open(result_path, 'wb+') as f: f.write(res.body()) # A full red image is expected image = QImage(result_path) self.assertFalse(image.isGrayscale()) color = image.pixelColor(100, 100) self.assertEqual(color.red(), 255) self.assertEqual(color.green(), 0) self.assertEqual(color.blue(), 0) _check_red() # Now activate the rule to exclude the feature where pk1 = 1, pk2 = 2 # A white image is expected self._accesscontrol.active['layerFilterExpression'] = True self._check_white(qs) # Activate the other rule for subset string self._accesscontrol.active['layerFilterExpression'] = False self._accesscontrol.active['layerFilterSubsetString'] = True self._check_white(qs) # Activate the other rule for layer permission self._accesscontrol.active['layerFilterSubsetString'] = False self._accesscontrol.active['layerPermissions'] = True req = QgsBufferServerRequest('http://my_server/' + qs) res = QgsBufferServerResponse() self._server.handleRequest(req, res, self.test_project) self.assertEqual(res.statusCode(), 403) # Test attribute table (template print2) with no rule self._accesscontrol.active['layerPermissions'] = False req = QgsBufferServerRequest('http://my_server/' + qs.replace('print1', 'print2')) res = QgsBufferServerResponse() self._server.handleRequest(req, res, self.test_project) self.assertEqual(res.statusCode(), 200) self._img_diff_error(res.body(), res.headers(), "WMS_GetPrint_postgres_print2") # Test attribute table with rule self._accesscontrol.active['authorizedLayerAttributes'] = True req = QgsBufferServerRequest('http://my_server/' + qs.replace('print1', 'print2')) res = QgsBufferServerResponse() self._server.handleRequest(req, res, self.test_project) self.assertEqual(res.statusCode(), 200) self._img_diff_error(res.body(), res.headers(), "WMS_GetPrint_postgres_print2_filtered") # Re-Test attribute table (template print2) with no rule self._accesscontrol.active['authorizedLayerAttributes'] = False req = QgsBufferServerRequest('http://my_server/' + qs.replace('print1', 'print2')) res = QgsBufferServerResponse() self._server.handleRequest(req, res, self.test_project) self.assertEqual(res.statusCode(), 200) self._img_diff_error(res.body(), res.headers(), "WMS_GetPrint_postgres_print2") # Test with layer permissions self._accesscontrol.active['layerPermissions'] = True req = QgsBufferServerRequest('http://my_server/' + qs.replace('print1', 'print2')) res = QgsBufferServerResponse() self._server.handleRequest(req, res, self.test_project) self.assertEqual(res.statusCode(), 403) # Test with subset string self._accesscontrol.active['layerPermissions'] = False self._accesscontrol.active['layerFilterSubsetString'] = True req = QgsBufferServerRequest('http://my_server/' + qs.replace('print1', 'print2')) res = QgsBufferServerResponse() self._server.handleRequest(req, res, self.test_project) self.assertEqual(res.statusCode(), 200) self._img_diff_error(res.body(), res.headers(), "WMS_GetPrint_postgres_print2_subset") # Test with filter expression self._accesscontrol.active['layerFilterExpression'] = True self._accesscontrol.active['layerFilterSubsetString'] = False req = QgsBufferServerRequest('http://my_server/' + qs.replace('print1', 'print2')) res = QgsBufferServerResponse() self._server.handleRequest(req, res, self.test_project) self.assertEqual(res.statusCode(), 200) self._img_diff_error(res.body(), res.headers(), "WMS_GetPrint_postgres_print2_subset") # Test attribute table with attribute filter self._accesscontrol.active['layerFilterExpression'] = False self._accesscontrol.active['authorizedLayerAttributes'] = True req = QgsBufferServerRequest('http://my_server/' + qs.replace('print1', 'print2')) res = QgsBufferServerResponse() self._server.handleRequest(req, res, self.test_project) self.assertEqual(res.statusCode(), 200) self._img_diff_error(res.body(), res.headers(), "WMS_GetPrint_postgres_print2_filtered") # Clear constraints self._clear_constraints() _check_red() req = QgsBufferServerRequest('http://my_server/' + qs.replace('print1', 'print2')) res = QgsBufferServerResponse() self._server.handleRequest(req, res, self.test_project) self.assertEqual(res.statusCode(), 200) self._img_diff_error(res.body(), res.headers(), "WMS_GetPrint_postgres_print2")
def test_wms_getprint_legend(self): """Test project has 2 layer: red and green and five templates: red: follow map theme red green: follow map theme green blank: no map theme full: follow map theme full with both layer falsegreen : follow map theme falsegreen (visible layer : green but with blue style) """ tmp_dir = QTemporaryDir() shutil.copyfile( os.path.join(unitTestDataPath('qgis_server'), 'test_project_legend.qgs'), os.path.join(tmp_dir.path(), 'test_project_legend.qgs')) shutil.copyfile( os.path.join(unitTestDataPath('qgis_server'), 'test_project_legend.gpkg'), os.path.join(tmp_dir.path(), 'test_project_legend.gpkg')) project = QgsProject() self.assertTrue( project.read( os.path.join(tmp_dir.path(), 'test_project_legend.qgs'))) params = { "SERVICE": "WMS", "VERSION": "1.3", "REQUEST": "GetPrint", "TEMPLATE": "blank", "FORMAT": "png", "LAYERS": "", "map0:EXTENT": "778000,5600000,836000,5650000", "map0:SCALE": "281285", "map0:LAYERS": "red", "CRS": "EPSG:3857", "DPI": '72' } ###################################################### # Template legend tests # Legend symbol are displayed at coordinates : # First item : 600 x , 40 y # Second item : 600 x , 60 y # blank template, no theme, no LAYERS, specified map0:LAYERS is red response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Only the red layer is displayed, there is no second item self._assertRed(image.pixelColor(600, 40)) self._assertWhite(image.pixelColor(600, 60)) # blank template, no LAYERS, specified map0:LAYERS is green params["map0:LAYERS"] = "green" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Only the green layer is displayed, there is no second item self._assertGreen(image.pixelColor(600, 40)) self._assertWhite(image.pixelColor(600, 60)) # blank template params["map0:LAYERS"] = "" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Only the red layer is displayed, there is no second item self._assertRed(image.pixelColor(600, 40)) self._assertGreen(image.pixelColor(600, 60)) # red template, red theme, specified map0:LAYERS is red params["TEMPLATE"] = "red" params["map0:LAYERS"] = "red" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Only the red layer is displayed, there is no second item self._assertRed(image.pixelColor(600, 40)) self._assertWhite(image.pixelColor(600, 60)) # red template, red theme, specified map0:LAYERS is green params["map0:LAYERS"] = "green" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Only the green layer is displayed, there is no second item self._assertGreen(image.pixelColor(600, 40)) self._assertWhite(image.pixelColor(600, 60)) # red template, red theme, no map0:LAYERS params["map0:LAYERS"] = "" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Only the red layer is displayed, there is no second item self._assertRed(image.pixelColor(600, 40)) self._assertWhite(image.pixelColor(600, 60)) # green template, green theme, specified map0:LAYERS is red params["TEMPLATE"] = "green" params["map0:LAYERS"] = "red" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Only the red layer is displayed, there is no second item self._assertRed(image.pixelColor(600, 40)) self._assertWhite(image.pixelColor(600, 60)) # green template, green theme, specified map0:LAYERS is green params["map0:LAYERS"] = "green" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Only the green layer is displayed, there is no second item self._assertGreen(image.pixelColor(600, 40)) self._assertWhite(image.pixelColor(600, 60)) # green template, green theme, no map0:LAYERS params["map0:LAYERS"] = "" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Only the green layer is displayed, there is no second item self._assertGreen(image.pixelColor(600, 40)) self._assertWhite(image.pixelColor(600, 60)) # full template, full theme, specified map0:LAYERS is red params["TEMPLATE"] = "full" params["map0:LAYERS"] = "red" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Only the red layer is displayed, there is no second item self._assertRed(image.pixelColor(600, 40)) self._assertWhite(image.pixelColor(600, 60)) # full template, full theme, specified map0:LAYERS is green params["map0:LAYERS"] = "green" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Only the green layer is displayed, there is no second item self._assertGreen(image.pixelColor(600, 40)) self._assertWhite(image.pixelColor(600, 60)) # full template, full theme, no map0:LAYERS params["map0:LAYERS"] = "" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Both red and green layers are displayed self._assertRed(image.pixelColor(600, 40)) self._assertGreen(image.pixelColor(600, 60)) # falsegreen template, falsegreen theme (green layer is blue), specified map0:LAYERS is red params["TEMPLATE"] = "falsegreen" params["map0:LAYERS"] = "red" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Only the red layer is displayed, there is no second item self._assertRed(image.pixelColor(600, 40)) self._assertWhite(image.pixelColor(600, 60)) # full template, full theme, specified map0:LAYERS is green params["map0:LAYERS"] = "green" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Only the green layer (in blue) is displayed, there is no second item self._assertBlue(image.pixelColor(600, 40)) self._assertWhite(image.pixelColor(600, 60)) # full template, full theme, no map0:LAYERS params["map0:LAYERS"] = "" response = QgsBufferServerResponse() request = QgsBufferServerRequest( '?' + '&'.join(["%s=%s" % i for i in params.items()])) self.server.handleRequest(request, response, project) image = QImage.fromData(response.body(), "PNG") # Only the green layer (in blue) is displayed, there is no second item self._assertBlue(image.pixelColor(600, 40)) self._assertWhite(image.pixelColor(600, 60))