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)
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())
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_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 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 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
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
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)
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
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
def test_getcapabilities_advertised_url(self): server = QgsServer() request = QgsServerRequest() projectPath = os.path.join(self.testdata_path, 'test_project.qgs') request.setUrl( QUrl('http://localhost/qgis_mapserv.fcgi?MAP=' + projectPath + '&SERVICE=WMS&REQUEST=GetCapabilities')) request.setOriginalUrl(QUrl('http://localhost/wms/test_project')) response = QgsBufferServerResponse() server.handleRequest(request, response) response.flush() headers = [] rh = response.headers() rk = sorted(rh.keys()) for k in rk: headers.append(("%s: %s" % (k, rh[k])).encode('utf-8')) reference_path = os.path.join(self.testdata_path, 'wms_getcapabilities_rewriting.txt') f = open(reference_path, 'rb') expected = f.read() self.assertXMLEqual( b"\n".join(headers) + b"\n\n" + bytes(response.body()), expected)
def compareContentType(self, url, headers, content_type): request = QgsBufferServerRequest(url, headers=headers) response = QgsBufferServerResponse() self.server.handleRequest(request, response, QgsProject()) self.assertEqual(response.headers()['Content-Type'], content_type)
def baseDoRequest(self, q): request = self.request # Uppercase REQUEST if 'REQUEST' in [k.upper() for k in q.keys()]: if request.method == 'GET': ows_request = q['REQUEST'].upper() else: if request.content_type == 'application/x-www-form-urlencoded': ows_request = request.POST['REQUEST'].upper() else: ows_request = request.POST['REQUEST'][0].upper() q['REQUEST'] = ows_request # FIXME: proxy or redirect in case of WMS/WFS/XYZ cascading? qgs_project = get_qgs_project(self.project.qgis_file.path) if qgs_project is None: raise Http404('The requested QGIS project could not be loaded!') data = None if request.method == 'GET': method = QgsBufferServerRequest.GetMethod elif request.method == 'POST': method = QgsBufferServerRequest.PostMethod data = request.body elif request.method == 'PUT': method = QgsBufferServerRequest.PutMethod data = request.body elif request.method == 'PATCH': method = QgsBufferServerRequest.PatchMethod data = request.body elif request.method == 'HEAD': method = QgsBufferServerRequest.HeadMethod elif request.method == 'DELETE': method = QgsBufferServerRequest.DeleteMethod else: logger.warning("Request method not supported: %s, assuming GET" % request.method) method = QgsBufferServerRequest.GetMethod headers = {} for header_key in request.headers.keys(): headers[header_key] = request.headers.get(header_key) uri = request.build_absolute_uri(request.path) + '?' + q.urlencode() logger.debug('Calling QGIS Server: %s' % uri) qgs_request = QgsBufferServerRequest(uri, method, headers, data) # Attach user and project to the server object to make them accessible by the # server access control plugins (constraints etc.) QGS_SERVER.user = request.user QGS_SERVER.project = self.project qgs_response = QgsBufferServerResponse() try: QGS_SERVER.handleRequest(qgs_request, qgs_response, qgs_project) except Exception as ex: return HttpResponseServerError( reason="Error handling server request: %s" % ex) response = HttpResponse(bytes(qgs_response.body())) response.status_code = qgs_response.statusCode() for key, value in qgs_response.headers().items(): response[key] = value return response
def baseDoRequest(self, q): request = self.request # Uppercase REQUEST if 'REQUEST' in [k.upper() for k in q.keys()]: if request.method == 'GET': ows_request = q['REQUEST'].upper() else: if request.content_type == 'application/x-www-form-urlencoded': ows_request = request.POST['REQUEST'].upper() else: ows_request = request.POST['REQUEST'][0].upper() q['REQUEST'] = ows_request # FIXME: proxy or redirect in case of WMS/WFS/XYZ cascading? qgs_project = get_qgs_project(self.project.qgis_file.path) if qgs_project is None: raise Http404('The requested QGIS project could not be loaded!') data = None if request.method == 'GET': method = QgsBufferServerRequest.GetMethod elif request.method == 'POST': method = QgsBufferServerRequest.PostMethod data = request.body elif request.method == 'PUT': method = QgsBufferServerRequest.PutMethod data = request.body elif request.method == 'PATCH': method = QgsBufferServerRequest.PatchMethod data = request.body elif request.method == 'HEAD': method = QgsBufferServerRequest.HeadMethod elif request.method == 'DELETE': method = QgsBufferServerRequest.DeleteMethod else: logger.warning( "Request method not supported: %s, assuming GET" % request.method) method = QgsBufferServerRequest.GetMethod headers = {} for header_key in request.headers.keys(): headers[header_key] = request.headers.get(header_key) uri = request.build_absolute_uri(request.path) + '?' + q.urlencode() logger.debug('Calling QGIS Server: %s' % uri) qgs_request = QgsBufferServerRequest(uri, method, headers, data) # Attach user and project to the server object to make them accessible by the # server access control plugins (constraints etc.) QGS_SERVER.djrequest = request QGS_SERVER.user = request.user QGS_SERVER.project = self.project # For GetPrint QGIS functions that rely on layers visibility, we need to check # the layers from LAYERS use_ids = QgsServerProjectUtils.wmsUseLayerIds(qgs_project) tree_root = qgs_project.layerTreeRoot() # Loop through the layers and make them visible for layer_name in qgs_request.queryParameter('LAYERS').split(','): layer_name = urllib.parse.unquote(layer_name) layer = None if use_ids: layer = qgs_project.mapLayer(layer_name) else: try: layer = qgs_project.mapLayersByName(layer_name)[0] except: # short name? for l in qgs_project.mapLayers().values(): if l.shortName() == layer_name: layer = l break if layer is None: logger.warning( 'Could not find layer "{}" when configuring OWS call'.format(layer_name)) else: layer_node = tree_root.findLayer(layer) if layer_node is not None: layer_node.setItemVisibilityCheckedParentRecursive(True) else: logger.warning( 'Could not find layer tree node "{}" when configuring OWS call'.format(layer_name)) qgs_response = QgsBufferServerResponse() try: QGS_SERVER.handleRequest(qgs_request, qgs_response, qgs_project) except Exception as ex: return HttpResponseServerError(reason="Error handling server request: %s" % ex) response = HttpResponse(bytes(qgs_response.body())) response.status_code = qgs_response.statusCode() for key, value in qgs_response.headers().items(): response[key] = value return response
def test_wms_getprint_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")