def requestReady(self): request = self.serverInterface().requestHandler() params = request.parameterMap() self.layers_render = [] # Get rastertime layers project = QGS_SERVER.project.qgis_project if params.get('LAYERS') and params.get('SERVICE').upper() == 'WMS' and \ params.get('REQUEST').upper() in ('GETMAP', 'GETLEGENDGRAPHIC') and params.get('RBAND'): layers = params.get('LAYERS').split(',') use_qgs_layer_id = QgsServerProjectUtils.wmsUseLayerIds(project) rlayer, rband = params.get('RBAND').split(',') for layer in layers: if use_qgs_layer_id: qlayer = project.mapLayer(layer) else: qlayer = project.mapLayerByName(layer) if qlayer.dataProvider().name() == Layer.TYPES.gdal and rlayer == qlayer.id(): self.layers_render.append({ 'qlayer': qlayer, 'renderer': qlayer.renderer().clone() }) rts = RTS(qlayer) rts.setDateIndex(int(rband))
def get_toc(project, info): """Get the WMS TOC information for the project""" use_ids = QgsServerProjectUtils.wmsUseLayerIds(project) wmsRestrictedLayers = QgsServerProjectUtils.wmsRestrictedLayers(project) def _harvest(node, parent_id=None): node_name = node.name() if parent_id is not None else 'root' rec = { 'title': node_name, # Override with title for layers 'name': node_name, 'expanded': node.isExpanded(), 'visible': node.isVisible(), } try: rec['id'] = node.layerId() rec['queryable'] = node.layerId() in info['wms_layers_queryable'] rec['searchable'] = node.layerId() in info['wms_layers_searchable'] rec['wfs_enabled'] = node.layerId( ) in info['capabilities']['wfsLayerIds'] short_name = node.layer().shortName() if node.layer().shortName( ) else node.layer().name() rec['typename'] = node.layer().id() if use_ids else short_name # Override title if node.layer().title(): rec['title'] = node.layer().title() if node.layer().type() not in (QgsMapLayerType.VectorLayer, QgsMapLayerType.RasterLayer): raise Exception rec['layer_type'] = 'vector' if node.layer().type( ) == QgsMapLayerType.VectorLayer else 'raster' rec['has_scale_based_visibility'] = node.layer( ).hasScaleBasedVisibility() if rec['has_scale_based_visibility']: rec['min_scale'] = node.layer().minimumScale() rec['max_scale'] = node.layer().maximumScale() rec['is_layer'] = True except AttributeError: rec['is_layer'] = False rec['tree_id'] = (parent_id + '.' + rec['title']) if parent_id is not None else 'root' rec['tree_id_hash'] = hashlib.md5( rec['tree_id'].encode('utf8')).hexdigest() children = [] for cn in [ n for n in node.children() if n.name() not in wmsRestrictedLayers ]: try: children.append(_harvest(cn, rec['tree_id'])) except: pass rec['children'] = children return rec return _harvest(project.layerTreeRoot())
def _get_custom_properties_by_layer(self, request, response, project): if QgsServerProjectUtils.wmsUseLayerIds(project): dict_key = 'id' else: dict_key = 'name' try: layer_keys_str = request.parameters()['LAYERS'] except KeyError: layer_keys_str = None try: filter_str = request.parameters()['FILTER'] except KeyError: filter_str = None if layer_keys_str: layer_keys = layer_keys_str.split(',') else: layer_keys = None if filter_str: filter_prop_items = [filter_prop.split(':') for filter_prop in filter_str.split(',')] filter_props = { filter_prop_name: filter_prop_value for filter_prop_name, filter_prop_value in filter_prop_items} else: filter_props = None custom_props = {} for layer_id, layer in project.mapLayers().items(): # If a shortname is set, we must use it instead of # the plain layer name layer_name = layer.shortName() or layer.name() if dict_key == 'name': custom_props_key = layer_name else: custom_props_key = layer_id if layer_keys: if dict_key == 'name' and layer_name not in layer_keys: continue if dict_key == 'id' and layer_id not in layer_keys: continue custom_props[custom_props_key] = {} if dict_key == 'name': custom_props[layer_name]['layer_id'] = layer_id else: custom_props[layer_id]['layer_name'] = layer_name for prop in layer.customPropertyKeys(): prop_value = layer.customProperty(prop) custom_props[custom_props_key][prop] = prop_value custom_props_filtered = custom_props.copy() if filter_props: for filter_prop in filter_props: for layer in custom_props: filter_prop_value = filter_props[filter_prop] if custom_props[layer][filter_prop] != filter_prop_value: del custom_props_filtered[layer] response.setStatusCode(200) response.write( json.dumps(custom_props_filtered, indent=4, sort_keys=True))
def project_wms(project, crs): """Calculate the extent from WMS advertized (if defined) or from WMS published layers. :param project: [description] :type project: [type] :returns: a tuple with WMS extent and list of published WMS typenames :rtype: tuple """ wms_typenames = [] extent = '' restricted_wms = QgsServerProjectUtils.wmsRestrictedLayers(project) use_ids = QgsServerProjectUtils.wmsUseLayerIds(project) for l in project.mapLayers().values(): if l.name() not in restricted_wms: lid = l.id() if use_ids else l.name() wms_typenames.append(lid) extent = QgsServerProjectUtils.wmsExtent(project) if extent.isNull(): target_crs = QgsCoordinateReferenceSystem.fromEpsgId( int(crs.split(':')[1])) for l in project.mapLayers().values(): if l.name() not in restricted_wms: l_extent = l.extent() if l.crs() != target_crs: ct = QgsCoordinateTransform(l.crs(), target_crs, project.transformContext()) l_extent = ct.transform(l_extent) if extent.isNull(): extent = l_extent else: extent.combineExtentWith(l_extent) else: if crs != project.crs().authid(): target_crs = QgsCoordinateReferenceSystem.fromEpsgId( int(crs.split(':')[1])) ct = QgsCoordinateTransform(project.crs(), target_crs, project.transformContext()) extent = ct.transform(extent) return extent, wms_typenames
def _get_fields_by_layer(self, request, response, project): if QgsServerProjectUtils.wmsUseLayerIds(project): dict_key = 'id' else: dict_key = 'name' try: layer_keys_str = request.parameters()['LAYERS'] except KeyError: layer_keys_str = None if layer_keys_str: layer_keys = layer_keys_str.split(',') else: layer_keys = None fields_by_layer = {} for layer_id, layer in project.mapLayers().items(): if isinstance(layer, QgsRasterLayer): continue # If a shortname is set, we must use it instead of # the plain layer name layer_name = layer.shortName() or layer.name() if dict_key == 'name': layer_key = layer_name else: layer_key = layer_id if layer_keys: if dict_key == 'name' and layer_name not in layer_keys: continue if dict_key == 'id' and layer_id not in layer_keys: continue fields_by_layer[layer_key] = {} if dict_key == 'name': fields_by_layer[layer_name]['layer_id'] = layer_id else: fields_by_layer[layer_id]['layer_name'] = layer_name fields_by_layer[layer_key] = [ field.name() for field in layer.fields()] response.setStatusCode(200) response.write( json.dumps(fields_by_layer, indent=4, sort_keys=True))
def test_wmsuselayerids(self): self.assertEqual(QgsServerProjectUtils.wmsUseLayerIds(self.prj), False) self.assertEqual(QgsServerProjectUtils.wmsUseLayerIds(self.prj2), True)
def test_wmsuselayerids(self): self.assertEqual(QgsServerProjectUtils.wmsUseLayerIds(self.prj), False) self.assertEqual(QgsServerProjectUtils.wmsUseLayerIds(self.prj2), True)
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