Example #1
0
 def test_requestHandlerProject(self):
     """Test request handler with none project"""
     headers = {'header-key-1': 'header-value-1', 'header-key-2': 'header-value-2'}
     request = QgsBufferServerRequest('http://somesite.com/somepath', QgsServerRequest.GetMethod, headers)
     response = QgsBufferServerResponse()
     self.server.handleRequest(request, response, None)
     self.assertEqual(bytes(response.body()), b'<ServerException>Project file error</ServerException>\n')
     self.assertEqual(response.headers(), {'Content-Length': '54', 'Content-Type': 'text/xml; charset=utf-8'})
     self.assertEqual(response.statusCode(), 500)
 def _execute_request(self, qs, requestMethod=QgsServerRequest.GetMethod, data=None):
     request = QgsBufferServerRequest(qs, requestMethod, {}, data)
     response = QgsBufferServerResponse()
     self._server.handleRequest(request, response)
     headers = []
     rh = response.headers()
     rk = sorted(rh.keys())
     for k in rk:
         headers.append(("%s: %s" % (k, rh[k])).encode('utf-8'))
     return b"\n".join(headers) + b"\n\n", bytes(response.body())
Example #3
0
 def test_responseHeaders(self):
     """Test response headers"""
     headers = {'header-key-1': 'header-value-1', 'header-key-2': 'header-value-2'}
     response = QgsBufferServerResponse()
     for k, v in headers.items():
         response.setHeader(k, v)
     for k, v in response.headers().items():
         self.assertEqual(headers[k], v)
     response.removeHeader('header-key-1')
     self.assertEqual(response.headers(), {'header-key-2': 'header-value-2'})
     response.setHeader('header-key-1', 'header-value-1')
     for k, v in response.headers().items():
         self.assertEqual(headers[k], v)
Example #4
0
    def do_GET(self, post_body=None):
        # CGI vars:
        headers = {}
        for k, v in self.headers.items():
            headers['HTTP_%s' % k.replace(' ', '-').replace('-', '_').replace(' ', '-').upper()] = v
        request = QgsBufferServerRequest(self.path, (QgsServerRequest.PostMethod if post_body is not None else QgsServerRequest.GetMethod), headers, post_body)
        response = QgsBufferServerResponse()
        qgs_server.handleRequest(request, response)

        headers_dict = response.headers()
        try:
            self.send_response(int(headers_dict['Status'].split(' ')[0]))
        except:
            self.send_response(200)
        for k, v in headers_dict.items():
            self.send_header(k, v)
        self.end_headers()
        self.wfile.write(response.body())
        return
Example #5
0
    def do_GET(self, post_body=None):
        # CGI vars:
        headers = {}
        for k, v in self.headers.items():
            headers['HTTP_%s' % k.replace(' ', '-').replace('-', '_').replace(' ', '-').upper()] = v
        if not self.path.startswith('http'):
            self.path = "%s://%s:%s%s" % ('https' if https else 'http', QGIS_SERVER_HOST, self.server.server_port, self.path)
        request = QgsBufferServerRequest(self.path, (QgsServerRequest.PostMethod if post_body is not None else QgsServerRequest.GetMethod), headers, post_body)
        response = QgsBufferServerResponse()
        qgs_server.handleRequest(request, response)

        headers_dict = response.headers()
        try:
            self.send_response(int(headers_dict['Status'].split(' ')[0]))
        except:
            self.send_response(200)
        for k, v in headers_dict.items():
            self.send_header(k, v)
        self.end_headers()
        self.wfile.write(response.body())
        return
Example #6
0
        def _check_links(params, method='GET'):
            data = urlencode(params)
            if method == 'GET':
                env = {
                    'SERVER_NAME': 'www.myserver.com',
                    'REQUEST_URI': '/aproject/',
                    'QUERY_STRING': data,
                    'REQUEST_METHOD': 'GET',
                }
            else:
                env = {
                    'SERVER_NAME': 'www.myserver.com',
                    'REQUEST_URI': '/aproject/',
                    'REQUEST_BODY': data,
                    'CONTENT_LENGTH': str(len(data)),
                    'REQUEST_METHOD': 'POST',
                }

            self._set_env(env)
            request = QgsFcgiServerRequest()
            response = QgsBufferServerResponse()
            self.server.handleRequest(request, response)
            self.assertFalse(b'ServiceExceptionReport' in response.body())

            if method == 'POST':
                self.assertEqual(request.data(), data.encode('utf8'))
            else:
                original_url = request.originalUrl().toString()
                self.assertTrue(original_url.startswith('http://www.myserver.com/aproject/'))
                self.assertEqual(original_url.find(urlencode({'MAP': params['map']})), -1)

            exp = re.compile(r'href="([^"]+)"', re.DOTALL | re.MULTILINE)
            elems = exp.findall(bytes(response.body()).decode('utf8'))
            self.assertTrue(len(elems) > 0)
            for href in elems:
                self.assertTrue(href.startswith('http://www.myserver.com/aproject/'))
                self.assertEqual(href.find(urlencode({'MAP': params['map']})), -1)
    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
Example #8
0
 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)
Example #9
0
 def test_responseHeaders(self):
     """Test response headers"""
     headers = {
         'header-key-1': 'header-value-1',
         'header-key-2': 'header-value-2'
     }
     response = QgsBufferServerResponse()
     for k, v in headers.items():
         response.setHeader(k, v)
     for k, v in response.headers().items():
         self.assertEqual(headers[k], v)
     response.removeHeader('header-key-1')
     self.assertEqual(response.headers(),
                      {'header-key-2': 'header-value-2'})
     response.setHeader('header-key-1', 'header-value-1')
     for k, v in response.headers().items():
         self.assertEqual(headers[k], v)
Example #10
0
    def test_write(self):
        """Test that writing on the buffer sets the body"""
        # Set as str
        response = QgsBufferServerResponse()
        response.write('Greetings from Essen Linux Hotel 2017 Hack Fest!')
        self.assertEqual(bytes(response.body()), b'')
        response.finish()
        self.assertEqual(bytes(response.body()), b'Greetings from Essen Linux Hotel 2017 Hack Fest!')
        self.assertEqual(response.headers(), {'Content-Length': '48'})

        # Set as a byte array
        response = QgsBufferServerResponse()
        response.write(b'Greetings from Essen Linux Hotel 2017 Hack Fest!')
        self.assertEqual(bytes(response.body()), b'')
        response.finish()
        self.assertEqual(bytes(response.body()), b'Greetings from Essen Linux Hotel 2017 Hack Fest!')
Example #11
0
 def test_statusCode(self):
     """Test return status HTTP code"""
     response = QgsBufferServerResponse()
     response.setStatusCode(222)
     self.assertEqual(response.statusCode(), 222)
Example #12
0
    def testOgcApiHandler(self):
        """Test OGC API Handler"""

        project = QgsProject()
        project.read(unitTestDataPath('qgis_server') + '/test_project_api.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'))
Example #13
0
    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
Example #14
0
 def test_statusCode(self):
     """Test return status HTTP code"""
     response = QgsBufferServerResponse()
     response.setStatusCode(222)
     self.assertEqual(response.statusCode(), 222)
    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))
Example #16
0
 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')
Example #17
0
    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))
Example #18
0
    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

        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
Example #19
0
 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 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_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))
Example #23
0
 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)
Example #24
0
 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)
Example #25
0
    def test_write(self):
        """Test that writing on the buffer sets the body"""
        # Set as str
        response = QgsBufferServerResponse()
        response.write('Greetings from Essen Linux Hotel 2017 Hack Fest!')
        self.assertEqual(bytes(response.body()), b'')
        response.finish()
        self.assertEqual(bytes(response.body()), b'Greetings from Essen Linux Hotel 2017 Hack Fest!')
        self.assertEqual(response.headers(), {'Content-Length': '48'})

        # Set as a byte array
        response = QgsBufferServerResponse()
        response.write(b'Greetings from Essen Linux Hotel 2017 Hack Fest!')
        self.assertEqual(bytes(response.body()), b'')
        response.finish()
        self.assertEqual(bytes(response.body()), b'Greetings from Essen Linux Hotel 2017 Hack Fest!')
    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))