Ejemplo n.º 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</ServerException>\n')
     self.assertEqual(response.headers(), {
         'Content-Length': '54',
         'Content-Type': 'text/xml; charset=utf-8'
     })
     self.assertEqual(response.statusCode(), 500)
Ejemplo n.º 2
0
 def get(self,
         query: str,
         project: str = None,
         headers: Dict[str, str] = {}) -> OWSResponse:
     """ Return server response from query
     """
     request = QgsBufferServerRequest(query, QgsServerRequest.GetMethod,
                                      headers, None)
     response = QgsBufferServerResponse()
     if project is not None and not os.path.isabs(project):
         projectpath = self.datapath.join(project)
         qgsproject = QgsProject()
         if not qgsproject.read(projectpath.strpath):
             raise ValueError("Error reading project '%s':" %
                              projectpath.strpath)
     else:
         qgsproject = None
     self.server.handleRequest(request, response, project=qgsproject)
     return OWSResponse(response)
    def _check_white(self, qs):
        """Check that output is a white image"""

        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(), 'white.png')
        with open(result_path, 'wb+') as f:
            f.write(res.body())

        # A full white image is expected
        image = QImage(result_path)
        self.assertTrue(image.isGrayscale())
        color = image.pixelColor(100, 100)
        self.assertEqual(color.red(), 255)
        self.assertEqual(color.green(), 255)
        self.assertEqual(color.blue(), 255)
Ejemplo n.º 4
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. 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)
Ejemplo n.º 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
        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
Ejemplo n.º 6
0
    def test_landing_page_redirects(self):
        """Test landing page redirects"""

        request = QgsBufferServerRequest('http://server.qgis.org/')
        request.setHeader('Accept', 'application/json')
        response = QgsBufferServerResponse()
        self.server.handleRequest(request, response)
        self.assertEqual(response.headers()[
                         'Location'], 'http://server.qgis.org/index.json')
        response = QgsBufferServerResponse()
        request.setHeader('Accept', 'text/html')
        self.server.handleRequest(request, response)
        self.assertEqual(response.headers()[
                         'Location'], 'http://server.qgis.org/index.html')
    def testMultiplePks(self):
        """Test issue GH #41786"""

        vl = QgsVectorLayer(self.vlconn_multiplepks, 'someData', 'postgres')
        self.assertTrue(vl.isValid())
        p = QgsProject()
        p.addMapLayers([vl])

        json_features_url = (
            'http://qgis/?SERVICE=WMS&REQUEST=GetFeatureInfo&' +
            'LAYERS=someData&STYLES=&' + 'INFO_FORMAT=application/json&' +
            'SRS=EPSG%3A4326&' + 'QUERY_LAYERS=someData&X=-1&Y=-1&' +
            'FEATURE_COUNT=100&')

        req = QgsBufferServerRequest(json_features_url)
        res = QgsBufferServerResponse()
        self.server.handleRequest(req, res, p)
        j = json.loads(bytes(res.body()).decode('utf8'))
        self.assertEqual(
            j, {
                'features': [{
                    'geometry': None,
                    'id': 'someData.1@@1',
                    'properties': {
                        'name': '1-1',
                        'pk1': 1,
                        'pk2': 1
                    },
                    'type': 'Feature'
                }, {
                    'geometry': None,
                    'id': 'someData.1@@2',
                    'properties': {
                        'name': '1-2',
                        'pk1': 1,
                        'pk2': 2
                    },
                    'type': 'Feature'
                }],
                'type':
                'FeatureCollection'
            })
Ejemplo n.º 8
0
def ows_server(request):
    register_django_provider()

    query_string = request.build_absolute_uri()
    project_path = os.path.join(os.path.dirname(__file__), 'test.qgs')
    qgis_project = QgsProject()
    qgis_project.read(project_path)

    qgis_request = QgsBufferServerRequest(query_string)
    qgis_response = QgsBufferServerResponse()
    server = QgsServer()
    server.handleRequest(qgis_request, qgis_response, qgis_project)

    body = bytes(qgis_response.body())

    response = HttpResponse(body)
    for k, v in qgis_response.headers().items():
        response[k] = v

    return response
Ejemplo n.º 9
0
    def test_landing_page_json(self):
        """Test landing page in JSON format"""

        request = QgsBufferServerRequest('http://server.qgis.org/index.json')
        response = QgsBufferServerResponse()
        self.server.handleRequest(request, response)
        j_actual = 'Content-Type: application/json\n\n'
        j_actual += bytes(response.body()).decode('utf8)')

        if not os.environ.get('TRAVIS', False):
            expected_path = os.path.join(
                unitTestDataPath('qgis_server'), 'landingpage',
                'test_landing_page_with_pg_index.json')
        else:
            expected_path = os.path.join(unitTestDataPath('qgis_server'),
                                         'landingpage',
                                         'test_landing_page_index.json')

        j_expected = open(expected_path).read()
        self.compareProjects(j_actual, j_expected, expected_path)
Ejemplo n.º 10
0
 def request(self,
             method,
             query: str,
             project: str = None,
             data: bytes = None,
             headers: dict = {}) -> OWSResponse:
     """ Return server response from query
     """
     request = QgsBufferServerRequest(query, method, headers, data)
     response = QgsBufferServerResponse()
     if project is not None and not os.path.isabs(project):
         projectpath = self.datapath.join(project)
         qgsproject = QgsProject()
         if not qgsproject.read(projectpath.strpath):
             raise ValueError(
                 f"Error reading project '{projectpath.strpath}'")
     else:
         qgsproject = None
     self.server.handleRequest(request, response, project=qgsproject)
     return OWSResponse(response)
Ejemplo n.º 11
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
Ejemplo n.º 12
0
    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')
Ejemplo n.º 13
0
    def testOgcApiHandlerContentType(self):
        """Test OGC API Handler content types"""

        project = QgsProject()
        project.read(unitTestDataPath('qgis_server') + '/test_project_api.qgs')
        request = QgsBufferServerRequest('http://server.qgis.org/api3/handlerthree?value1=9.5')
        response = QgsBufferServerResponse()

        # Add handler to API and test for /api3
        ctx = QgsServerApiContext('/services/api3', request, response, project, self.server.serverInterface())
        api = QgsServerOgcApi(self.server.serverInterface(), '/api3', 'apithree', 'a third api', '1.2')
        h3 = Handler3()
        api.registerHandler(h3)

        ctx = QgsServerApiContext('/services/api3/', request, response, project, self.server.serverInterface())
        api.executeRequest(ctx)
        self.assertEqual(json.loads(bytes(ctx.response().data()))['value1'], 9.5)

        # Call HTML
        ctx.request().setUrl(QtCore.QUrl('http://server.qgis.org/api3/handlerthree.html?value1=9.5'))
        with self.assertRaises(QgsServerApiBadRequestException) as ex:
            api.executeRequest(ctx)
        self.assertEqual(str(ex.exception), 'Unsupported Content-Type: HTML')

        h3.setContentTypes([QgsServerOgcApi.HTML])
        with self.assertRaises(QgsServerApiBadRequestException) as ex:
            api.executeRequest(ctx)
        self.assertEqual(str(ex.exception), 'Template not found: handlerThree.html')

        # Define a template path
        dir = QtCore.QTemporaryDir()
        with open(dir.path() + '/handlerThree.html', 'w+') as f:
            f.write("Hello world")
        h3.templatePathOverride = dir.path() + '/handlerThree.html'
        ctx.response().clear()
        api.executeRequest(ctx)
        self.assertEqual(bytes(ctx.response().data()), b"Hello world")
Ejemplo n.º 14
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
Ejemplo n.º 15
0
    def test_getcapabilities(self):
        project = self._project_path
        assert os.path.exists(project), "Project file not found: " + project

        # without cache
        query_string = '?MAP=%s&SERVICE=WMS&VERSION=1.3.0&REQUEST=%s' % (
            urllib.parse.quote(project), 'GetCapabilities')
        header, body = self._execute_request(query_string)
        doc = QDomDocument("wms_getcapabilities_130.xml")
        doc.setContent(body)
        # with cache
        header, body = self._execute_request(query_string)

        # without cache
        query_string = '?MAP=%s&SERVICE=WMS&VERSION=1.1.1&REQUEST=%s' % (
            urllib.parse.quote(project), 'GetCapabilities')
        header, body = self._execute_request(query_string)
        # with cache
        header, body = self._execute_request(query_string)

        # without cache
        query_string = '?MAP=%s&SERVICE=WFS&VERSION=1.1.0&REQUEST=%s' % (
            urllib.parse.quote(project), 'GetCapabilities')
        header, body = self._execute_request(query_string)
        # with cache
        header, body = self._execute_request(query_string)

        # without cache
        query_string = '?MAP=%s&SERVICE=WFS&VERSION=1.0.0&REQUEST=%s' % (
            urllib.parse.quote(project), 'GetCapabilities')
        header, body = self._execute_request(query_string)
        # with cache
        header, body = self._execute_request(query_string)

        # without cache
        query_string = '?MAP=%s&SERVICE=WCS&VERSION=1.0.0&REQUEST=%s' % (
            urllib.parse.quote(project), 'GetCapabilities')
        header, body = self._execute_request(query_string)
        # with cache
        header, body = self._execute_request(query_string)

        # without cache
        query_string = '?MAP=%s&SERVICE=WMTS&VERSION=1.0.0&REQUEST=%s' % (
            urllib.parse.quote(project), 'GetCapabilities')
        header, body = self._execute_request(query_string)
        # with cache
        header, body = self._execute_request(query_string)

        filelist = [
            f for f in os.listdir(self._servercache._cache_dir)
            if f.endswith(".xml")
        ]
        self.assertEqual(len(filelist), 6, 'Not enough file in cache')

        cacheManager = self._server_iface.cacheManager()

        self.assertTrue(cacheManager.deleteCachedDocuments(None),
                        'deleteCachedDocuments does not return True')

        filelist = [
            f for f in os.listdir(self._servercache._cache_dir)
            if f.endswith(".xml")
        ]
        self.assertEqual(len(filelist), 0,
                         'All files in cache are not deleted ')

        prj = QgsProject()
        prj.read(project)

        query_string = '?MAP=%s&SERVICE=WMS&VERSION=1.3.0&REQUEST=%s' % (
            urllib.parse.quote(project), 'GetCapabilities')
        request = QgsBufferServerRequest(query_string,
                                         QgsServerRequest.GetMethod, {}, None)

        accessControls = self._server_iface.accessControls()

        cDoc = QDomDocument("wms_getcapabilities_130.xml")
        self.assertFalse(
            cacheManager.getCachedDocument(cDoc, prj, request, accessControls),
            'getCachedDocument is not None')

        self.assertTrue(
            cacheManager.setCachedDocument(doc, prj, request, accessControls),
            'setCachedDocument false')

        self.assertTrue(
            cacheManager.getCachedDocument(cDoc, prj, request, accessControls),
            'getCachedDocument is None')
        self.assertEqual(doc.documentElement().tagName(),
                         cDoc.documentElement().tagName(),
                         'cachedDocument not equal to provide document')

        self.assertTrue(cacheManager.deleteCachedDocuments(None),
                        'deleteCachedDocuments does not return True')
    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))
Ejemplo n.º 17
0
 def test_wfs3_field_filters_star(self):
     """Test field filters"""
     project = QgsProject()
     project.read(unitTestDataPath('qgis_server') + '/test_project.qgs')
     request = QgsBufferServerRequest('http://server.qgis.org/wfs3/collections/testlayer3/items?name=tw*')
     self.compareApi(request, project, 'test_wfs3_collections_items_testlayer3_name_eq_tw_star.json')
Ejemplo n.º 18
0
    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'
            ))
Ejemplo n.º 19
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)
Ejemplo n.º 20
0
    def test_wfs3_landing_page(self):
        """Test WFS3 API landing page in HTML format"""

        request = QgsBufferServerRequest('http://server.qgis.org/wfs3.html')
        self.compareApi(request, None, 'test_wfs3_landing_page.html')
Ejemplo n.º 21
0
 def test_wfs3_conformance(self):
     """Test WFS3 API"""
     request = QgsBufferServerRequest(
         'http://server.qgis.org/wfs3/conformance')
     self.compareApi(request, None, 'test_wfs3_conformance.json')
    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
Ejemplo n.º 23
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')
Ejemplo n.º 24
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_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))
Ejemplo n.º 26
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
Ejemplo n.º 27
0
 def test_wfs3_collection_items_limit(self):
     """Test WFS3 API item limits"""
     project = QgsProject()
     project.read(unitTestDataPath('qgis_server') + '/test_project_api.qgs')
     request = QgsBufferServerRequest('http://server.qgis.org/wfs3/collections/testlayer%20èé/items?limit=1')
     self.compareApi(request, project, 'test_wfs3_collections_items_testlayer_èé_limit_1.json')
Ejemplo n.º 28
0
 def test_wfs3_collections_html(self):
     """Test WFS3 API collections in html format"""
     request = QgsBufferServerRequest('http://server.qgis.org/wfs3/collections.html')
     project = QgsProject()
     project.read(unitTestDataPath('qgis_server') + '/test_project_api.qgs')
     self.compareApi(request, project, 'test_wfs3_collections_project.html')
Ejemplo n.º 29
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)
Ejemplo n.º 30
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))