Пример #1
0
 def test_requestHandler(self):
     """Test request handler"""
     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)
     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')
     self.assertEqual(response.headers(), {'Content-Length': '156', 'Content-Type': 'text/xml; charset=utf-8'})
     self.assertEqual(response.statusCode(), 500)
Пример #2
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)
Пример #3
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)
Пример #4
0
 def test_wfs3_field_filters(self):
     """Test field filters"""
     project = QgsProject()
     project.read(unitTestDataPath('qgis_server') + '/test_project_api.qgs')
     # Check not published
     response = QgsBufferServerResponse()
     request = QgsBufferServerRequest(
         'http://server.qgis.org/wfs3/collections/testlayer3/items?name=two'
     )
     self.server.handleRequest(request, response, project)
     self.assertEqual(response.statusCode(), 404)  # Not found
     request = QgsBufferServerRequest(
         'http://server.qgis.org/wfs3/collections/layer1_with_short_name/items?name=two'
     )
     self.server.handleRequest(request, response, project)
     self.assertEqual(response.statusCode(), 200)
     self.compareApi(
         request, project,
         'test_wfs3_collections_items_layer1_with_short_name_eq_two.json')
Пример #5
0
    def test_invalid_args(self):
        """Test wrong args"""
        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()
        self.server.handleRequest(request, response, project)
        self.assertEqual(response.statusCode(), 400)  # Bad request
        self.assertEqual(response.body(
        ), b'[{"code":"Bad request error","description":"Argument \'limit\' is not valid. Number of features to retrieve [0-10000]"}]'
                         )  # Bad request

        request = QgsBufferServerRequest(
            'http://server.qgis.org/wfs3/collections/testlayer%20èé/items?limit=10001'
        )
        response = QgsBufferServerResponse()
        self.server.handleRequest(request, response, project)
        self.assertEqual(response.statusCode(), 400)  # Bad request
        self.assertEqual(response.body(
        ), b'[{"code":"Bad request error","description":"Argument \'limit\' is not valid. Number of features to retrieve [0-10000]"}]'
                         )  # Bad request
        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)
Пример #7
0
 def test_statusCode(self):
     """Test return status HTTP code"""
     response = QgsBufferServerResponse()
     response.setStatusCode(222)
     self.assertEqual(response.statusCode(), 222)
Пример #8
0
 def test_statusCode(self):
     """Test return status HTTP code"""
     response = QgsBufferServerResponse()
     response.setStatusCode(222)
     self.assertEqual(response.statusCode(), 222)
Пример #9
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)
Пример #10
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)
Пример #11
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.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
Пример #12
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)
Пример #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
    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")