diff --git a/geonode/harvesting/harvesters/wms.py b/geonode/harvesting/harvesters/wms.py index 847b8ff2efc..a99b3fb1ca5 100644 --- a/geonode/harvesting/harvesters/wms.py +++ b/geonode/harvesting/harvesters/wms.py @@ -34,7 +34,7 @@ from django.template.defaultfilters import slugify from requests.auth import HTTPBasicAuth from geonode.layers.models import Dataset -from geonode.base.models import ResourceBase +from geonode.base.models import Link, ResourceBase from geonode.layers.enumerations import GXP_PTYPES from geonode.thumbs.thumbnails import create_thumbnail @@ -184,21 +184,23 @@ def get_ogc_wms_url(self, wms_url, version=None): logger.exception(e) return ogc_wms_url - def get_capabilities(self) -> requests.Response: + def wms_call(self, kind="GetCapabilities", override_version=None, additional_params={}) -> requests.Response: params = self._base_wms_parameters.copy() params.update( { - "request": "GetCapabilities", + "request": kind, } ) (wms_url, _service, _version, _request) = self._get_cleaned_url_params(self.remote_url) if _service: params["service"] = _service - if _version: - params["version"] = _version + if override_version or _version: + params["version"] = override_version or _version if wms_url.query: for _param in parse_qsl(wms_url.query): params[_param[0]] = _param[1] + # updating default params with custom ones + params = {**params, **additional_params} # checking if the services is under basic auth # getting the service @@ -214,11 +216,11 @@ def get_capabilities(self) -> requests.Response: service = has_basic_auth.first() basic_auth = HTTPBasicAuth(service.username, service.get_password()) - get_capabilities_response = self.http_session.get( + response = self.http_session.get( self.get_ogc_wms_url(wms_url, version=_version), params=params, auth=basic_auth ) - get_capabilities_response.raise_for_status() - return get_capabilities_response + response.raise_for_status() + return response def get_num_available_resources(self) -> int: data = self._get_data() @@ -251,7 +253,7 @@ def list_resources(self, offset: typing.Optional[int] = 0) -> typing.List[base.B def check_availability(self, timeout_seconds: typing.Optional[int] = 5) -> bool: try: - response = self.get_capabilities() + response = self.wms_call() except (requests.HTTPError, requests.ConnectionError): result = False else: @@ -340,7 +342,7 @@ def get_resource( def _get_data(self) -> typing.Dict: """Return data from the harvester URL in JSON format.""" - get_capabilities_response = self.get_capabilities() + get_capabilities_response = self.wms_call() root = etree.fromstring(get_capabilities_response.content, parser=XML_PARSER) nsmap = _get_nsmap(root.nsmap) @@ -546,6 +548,29 @@ def finalize_resource_update( forced_crs=target_crs, overwrite=True, ) + # ref GeoNode #13010 + # A describeLayer is perfomed to see if we can add the WDS link + # to the resource + response = self.wms_call( + kind="DescribeLayer", override_version="1.1.1", additional_params={"layers": geonode_resource.alternate} + ) + # check if the owsType is WFS + if response: + if ( + etree.fromstring(response.content, parser=XML_PARSER).find("LayerDescription").attrib.get("owsType") + == "WFS" + ): + Link.objects.get_or_create( + resource=geonode_resource, + url=geonode_resource.ows_url, + name=f"OGC WFS: {geonode_resource.workspace} Service", + defaults=dict( + extension="html", + url=geonode_resource.ows_url, + mime="text/html", + link_type="OGC:WFS", + ), + ) def _get_nsmap(original: typing.Dict): diff --git a/geonode/services/models.py b/geonode/services/models.py index 7edca420c69..8107d785de4 100644 --- a/geonode/services/models.py +++ b/geonode/services/models.py @@ -95,7 +95,7 @@ def probe(self): @property def needs_authentication(self): - return self.password and self.username + return self.password is not None and self.username is not None def _get_service_url(self): parsed_url = urlparse(self.base_url)