예제 #1
0
def get_feature_type_elements_xml(title, service_type_version, service_type,
                                  uri, external_auth):
    """ Requests a DescribeFeatureType document

    Args:
        title (str):
        service_type_version (str):
        service_type (str):
        uri (str):
        external_auth (ExternalAuthentication):
    Returns:
         None | str
    """
    from service.helper.common_connector import CommonConnector
    connector = CommonConnector(url=uri, external_auth=external_auth)
    type_name = "typeName"
    if service_type_version == OGCServiceVersionEnum.V_2_0_0 or service_type_version == OGCServiceVersionEnum.V_2_0_2:
        type_name = "typeNames"

    params = {
        "service": service_type,
        "version": service_type_version,
        "request": "DescribeFeatureType",
        type_name: title
    }

    try:
        connector.load(params=params)
        response = connector.content
        response = parse_xml(response)
    except ConnectionError:
        return None
    except ProxyError:
        return None
    return response
예제 #2
0
    def get_category_json(self, category_url, language):
        """ Loads the json response from a connector class

        Args:
            category_url: The uri where the definitions can be loaded from
            language: The language which shall be fetched
        Returns:
             response (str): The response body content
        """
        uri_lang = category_url.format(language)
        if (CommonConnector().url_is_reachable("https://www.google.de/", 10)[0]
                is not True):
            self.stdout.write(
                self.style.NOTICE(
                    "Internet connection test failed! Proxies have to be specified in MrMap/settings.py."
                ))
            self.stdout.write(
                self.style.NOTICE(
                    "Setup will be canceled! Please make sure to have a working internet connection!"
                ))
            exit()

        connector = CommonConnector(uri_lang)
        connector.load()
        return connector.content
예제 #3
0
    def check_status(self,
                     url: str,
                     check_wfs_member: bool = False,
                     check_image: bool = False) -> ServiceStatus:
        """ Check status of ogc service.

        Args:
            url (str): URL to the service that should be checked.
            check_wfs_member (bool): True, if a returned xml should check for a 'member' tag.
            check_image (bool): True, if the returned content should be checked as image.
        Returns:
            ServiceStatus: Status info of service.
        """
        success = False
        duration = None
        connector = CommonConnector(url=url,
                                    timeout=self.monitoring_settings.timeout
                                    if self.monitoring_settings is not None
                                    else MONITORING_REQUEST_TIMEOUT)
        if self.metadata.has_external_authentication:
            connector.external_auth = self.metadata.external_authentication
        try:
            connector.load()
        except Exception as e:
            # handler if server sends no response (e.g. outdated uri)
            response_text = str(e)
            return Monitoring.ServiceStatus(url, success, response_text,
                                            connector.status_code, duration)

        duration = timezone.timedelta(seconds=connector.run_time)
        response_text = connector.content
        if connector.status_code == 200:
            success = True
            try:
                xml = parse_xml(response_text)
                if 'Exception' in xml.getroot().tag:
                    success = False
                if check_wfs_member:
                    if not self.has_wfs_member(xml):
                        success = False
            except AttributeError:
                # handle successful responses that do not return xml
                response_text = None
            if check_image:
                try:
                    Image.open(BytesIO(connector.content))
                    success = True
                except UnidentifiedImageError:
                    success = False
        service_status = Monitoring.ServiceStatus(url, success, response_text,
                                                  connector.status_code,
                                                  duration)
        return service_status
예제 #4
0
    def fetch_validation_document(self):
        """ Fetches the XML document that is to be validated.

        Returns:
            str: document to be validated
        """
        validation_target = self.config.validation_target
        doc_url = getattr(self.metadata, validation_target)
        quality_logger.info(
            f"Retrieving document for validation from {doc_url}")
        connector = CommonConnector(url=doc_url)
        connector.load()
        if connector.status_code != requests.codes.ok:
            raise Exception(
                f"Unexpected HTTP response code {connector.status_code} when "
                f"retrieving document from: {doc_url}")
        return connector.content
예제 #5
0
def get_metadata_legend(request: HttpRequest, metadata_id, style_id: int):
    """ Calls the legend uri of a special style inside the metadata (<LegendURL> element) and returns the response to the user

    This function has to be public available (no check_session decorator)

    Args:
        request (HttpRequest): The incoming HttpRequest
        metadata_id: The metadata id
        style_id (int): The style id
    Returns:
        HttpResponse
    """
    style = get_object_or_404(Style, id=style_id)
    uri = style.legend_uri
    con = CommonConnector(uri)
    con.load()
    response = con.content
    return HttpResponse(response, content_type="")
예제 #6
0
    def get_capabilities(self):
        """ Start a network call to retrieve the original capabilities xml document.

        Using the connector class, this function will GET the capabilities xml document as string.
        No file will be downloaded and stored on the storage. The string will be stored in the OGCWebService instance.

        Returns:
             nothing
        """
        params = {
            "request":
            OGCOperationEnum.GET_CAPABILITIES.value,
            "version":
            self.service_version.value
            if self.service_version is not None else "",
            "service": (self.service_type.value
                        if self.service_type is not None else "").upper(),
        }
        concat = "&" if self.service_connect_url[-1] != "&" else ""
        self.service_connect_url = "{}{}{}".format(self.service_connect_url,
                                                   concat, urlencode(params))
        ows_connector = CommonConnector(
            url=self.service_connect_url,
            external_auth=self.external_authentification,
            connection_type=ConnectionEnum.REQUESTS)
        ows_connector.http_method = 'GET'
        try:
            ows_connector.load()
            if ows_connector.status_code != 200:
                raise ConnectionError(ows_connector.status_code)
        except ReadTimeout:
            raise ConnectionError(
                CONNECTION_TIMEOUT.format(self.service_connect_url))

        tmp = ows_connector.content.decode("UTF-8")
        # check if tmp really contains an xml file
        xml = xml_helper.parse_xml(tmp)

        if xml is None:
            raise Exception(tmp)

        self.service_capabilities_xml = tmp
        self.connect_duration = ows_connector.run_time
        self.descriptive_document_encoding = ows_connector.encoding
예제 #7
0
    def get_metadata(self):
        """ Start a network call to retrieve the original capabilities xml document.

        Using the connector class, this function will GET the capabilities xml document as string.
        No file will be downloaded and stored on the storage. The string will be stored in the OGCWebService instance.

        Returns:
             nothing
        """
        ows_connector = CommonConnector(
            url=self.uri,
            external_auth=None,
            connection_type=ConnectionEnum.REQUESTS)
        ows_connector.http_method = 'GET'
        ows_connector.load()
        if ows_connector.status_code != 200:
            raise ConnectionError(ows_connector.status_code)

        self.raw_metadata = ows_connector.content.decode("UTF-8")
예제 #8
0
    def _get_harvest_response(self,
                              result_type: str = "results") -> (bytes, int):
        """ Fetch a response for the harvesting (GetRecords)

        Args:
            result_type (str): Which resultType should be used (hits|results)
        Returns:
             harvest_response (bytes): The response content
             status_code (int): The response status code
        """
        from service.helper.common_connector import CommonConnector
        connector = CommonConnector(url=self.harvest_url)
        if self.method.upper() == "GET":
            params = {
                "service": "CSW",
                "typeNames": "gmd:MD_Metadata",
                "resultType": result_type,
                "startPosition": self.start_position,
                "outputFormat": self.output_format,
                "maxRecords": self.max_records_per_request,
                "version": self.version,
                "request": OGCOperationEnum.GET_RECORDS.value,
                "outputSchema": HARVEST_GET_REQUEST_OUTPUT_SCHEMA,
            }
            connector.load(params=params)
            harvest_response = connector.content
        elif self.method.upper() == "POST":
            post_body = self._generate_request_POST_body(
                self.start_position, result_type=result_type)
            connector.post(data=post_body)
            harvest_response = connector.content
        else:
            raise NotImplementedError()

        return harvest_response, connector.status_code
예제 #9
0
def check_uri_provides_ogc_capabilities(value) -> ValidationError:
    """ Checks whether a proper XML OGC Capabilities document can be found at the given url.

    Args:
        value: The url parameter
    Returns:
         None|ValidationError: None if the checks are valid, ValidationError else
    """
    connector = CommonConnector(url=value)
    connector.load()
    if connector.status_code == 401:
        # This means the resource needs authentication to be called. At this point we can not check whether this is
        # a proper OGC capabilities or not. Skip this check.
        return None
    try:
        xml_response = xml_helper.parse_xml(connector.content)
        root_elem = xml_response.getroot()
        tag_text = root_elem.tag
        if "Capabilities" not in tag_text:
            return ValidationError(_("This is no capabilities document."))
    except AttributeError:
        # No xml found!
        return ValidationError(_("No XML found."))
예제 #10
0
def check_uri_is_reachable(value) -> (bool, bool, int):
    """ Performs a check on the URL.

    Returns whether it's reachable or not

    Args:
        value: The url to be checked
    Returns:
         reachable (bool)
         needs_authentication (bool)
         status_code (int)
    """
    connector = CommonConnector(url=value)
    is_reachable, status_code = connector.url_is_reachable()
    if not is_reachable:
        if status_code < 0:
            # Not even callable!
            msg_suffix = "URL could not be resolved to a server. Please check your input!"
        else:
            msg_suffix = "Status code was {}".format(status_code)
        return ValidationError(message="URL not valid! {}".format(msg_suffix))
    needs_authentication = status_code == 401
    return is_reachable, needs_authentication, status_code
예제 #11
0
def capabilities_are_different(cap_url_1, cap_url_2):
    """ Loads two capabilities documents using uris and checks if they differ

    Args:
        cap_url_1: First capabilities url
        cap_url_2: Second capabilities url
    Returns:
         bool: True if they differ, false if they are equal
    """
    # load xmls
    connector = CommonConnector(cap_url_1)
    connector.load()
    xml_1 = connector.content
    connector = CommonConnector(cap_url_2)
    connector.load()
    xml_2 = connector.content

    sec_handler = CryptoHandler()

    # hash both and compare hashes
    xml_1_hash = sec_handler.sha256(xml_1)
    xml_2_hash = sec_handler.sha256(xml_2)

    return xml_1_hash != xml_2_hash
예제 #12
0
    def test_new_service_check_capabilities_uri(self):
        return
        """ Tests whether capabilities uris for the service and layers are set.

        Performs a retrieve check: Connects to the given uri and checks if the received xml matches with the persisted
        capabilities document.
        Checks for the service.
        Checks for each layer.

        Returns:

        """
        service = self.service_wms
        layers = service.get_subelements()

        cap_doc = self.cap_doc_wms.content
        cap_uri = service.metadata.capabilities_original_uri
        connector = CommonConnector(url=cap_uri)
        connector.load()

        # Only check if the uri is valid and can be used to receive some data
        self.assertEqual(
            connector.status_code,
            200,
            msg="URL '{}' didn't respond with status code 200".format(cap_uri))
        for layer in layers:
            cap_uri_layer = layer.metadata.capabilities_original_uri
            if cap_uri == cap_uri_layer:
                # we assume that the same uri in a layer will receive the same xml document. ONLY if the uri would be different
                # we run another check. We can be sure that this check will fail, since a capabilities document
                # should only be available using a unique uri - but you never know...
                continue
            connector = CommonConnector(url=cap_uri)
            self.assertEqual(
                connector.status_code,
                200,
                msg="URL '{}' didn't respond with status code 200".format(
                    cap_uri))