From b0114024c76bba11c35e54479509e1bfcd37681f Mon Sep 17 00:00:00 2001 From: mpeltriaux Date: Sun, 1 Nov 2026 11:26:15 +0100 Subject: [PATCH] # Parcel fetcher improvements * switch from custom auth header to standard 'Authorization' bearer token header * drops definition of custom schneider authentication header from settings * refactors ParcelFetcher geom-shrinking code into own method for better maintainability --- .env.sample | 1 - konova/sub_settings/schneider_settings.py | 1 - konova/utils/schneider/fetcher.py | 55 ++++++++++++++--------- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/.env.sample b/.env.sample index be782996..a99d0173 100644 --- a/.env.sample +++ b/.env.sample @@ -31,7 +31,6 @@ GEOPORTAL_RLP_PASSWORD=CHANGE_ME # Schneider SCHNEIDER_BASE_URL=https://schneider.naturschutz.rlp.de SCHNEIDER_AUTH_TOKEN=CHANGE_ME -SCHNEIDER_AUTH_HEADER=auth # SSO SSO_SERVER_BASE_URL=https://login.naturschutz.rlp.de diff --git a/konova/sub_settings/schneider_settings.py b/konova/sub_settings/schneider_settings.py index 920a0c3f..11846803 100644 --- a/konova/sub_settings/schneider_settings.py +++ b/konova/sub_settings/schneider_settings.py @@ -8,5 +8,4 @@ Created on: 14.12.22 from konova.sub_settings.django_settings import env base_url = env("SCHNEIDER_BASE_URL") -auth_header = env("SCHNEIDER_AUTH_HEADER") auth_header_token = env("SCHNEIDER_AUTH_TOKEN") diff --git a/konova/utils/schneider/fetcher.py b/konova/utils/schneider/fetcher.py index 14718495..e07c519e 100644 --- a/konova/utils/schneider/fetcher.py +++ b/konova/utils/schneider/fetcher.py @@ -9,16 +9,14 @@ import json from json import JSONDecodeError import requests -from django.contrib.gis import gdal +from django.contrib.gis.geos import GEOSGeometry from konova.sub_settings import schneider_settings -from konova.sub_settings.lanis_settings import DEFAULT_SRID from konova.sub_settings.proxy_settings import PROXIES class ParcelFetcher: base_url = schneider_settings.base_url - auth_header = schneider_settings.auth_header auth_header_token = schneider_settings.auth_header_token geometry = None @@ -30,30 +28,47 @@ class ParcelFetcher: raise AssertionError("Geometry must not be none") self.geometry = geometry - # Reduce size of geometry to avoid "intersections" because of exact border matching - buffer_threshold = 0.001 - geom = geometry.geom.buffer(-buffer_threshold) - if geom.area < buffer_threshold: - # Fallback for malicious geometries which are way too small and would disappear on negative buffering - geom = geometry.geom - try: - geom.transform(DEFAULT_SRID) - except gdal.GDALException as e: - raise ValueError(f"{str(e)}\nCould not transform geometry (id: {geometry.id}) to {DEFAULT_SRID}:\n {geom.geojson}") - self.geojson = geom.ewkt + geom = self._shrink_geometry(geometry.geom) + + self.geojson = geom.geojson self.results = [] - def get_parcels(self, url: str = None): - post_url = url - if post_url is None: - post_url = f"{self.base_url}/parcel/intersect/" + def _shrink_geometry(self, geometry: GEOSGeometry) -> GEOSGeometry: + """ Shrink geometry by a minimal factor to avoid intersections with neighboring features due to + exact outline match. + + Args: + geometry (GEOSGeometry): geometry to shrink + + Returns: + geom (GEOSGeometry): Shrinked geometry + """ + # Reduce size of geometry to avoid "intersections" because of exact border matching + buffer_threshold = 0.001 + return_geom = geometry.buffer(-buffer_threshold) + if return_geom.area < buffer_threshold: + # Fallback for malicious geometries which are way too small and would disappear on negative buffering + return_geom = geometry + return return_geom + + def get_parcels(self, url: str = None) -> list: + """ Perform parcel fetching + + Args: + url (None|str): (optional) Provide an alternative url for fetching parcels. Default will be used if None + + Returns: + results (list): List of fetched parcels + """ + if url is None: + url = f"{self.base_url}/parcel/intersect/" response = requests.post( - url=post_url, + url=url, proxies=PROXIES, data=self.geojson, headers={ - self.auth_header: self.auth_header_token + "Authorization": f"Bearer {self.auth_header_token}" } )