From 3646e9073bf22bc5fed62c1acc76c33b8d779d04 Mon Sep 17 00:00:00 2001 From: Davey Oldenburg Date: Thu, 10 Apr 2025 12:00:21 +0200 Subject: [PATCH 01/15] WIP: Mapserver 8 update, config en dockerfile updates --- Dockerfile | 8 ++++--- mapserver.conf | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 mapserver.conf diff --git a/Dockerfile b/Dockerfile index c2504846..251e7be1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.04 +FROM ubuntu:24.04 LABEL maintainer="datapunt@amsterdam.nl" ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -y \ @@ -13,12 +13,14 @@ RUN apt-get update -y \ wget \ && apt-get clean - # Enable these Apache modules RUN a2enmod actions cgid headers rewrite # Configure localhost in Apache RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf +COPY mapserver.conf /usr/local/etc/ +RUN echo "SetEnv MAPSERVER_CONFIG_FILE \"/usr/local/etc/mapserver.conf\"" >> /etc/apache2/apache2.conf + RUN rm /etc/apache2/mods-enabled/alias.conf COPY docker/000-default.conf /etc/apache2/sites-available/ COPY docker/docker-entrypoint.sh /bin @@ -36,5 +38,5 @@ RUN rm -rf /srv/mapserver/private EXPOSE 8080 -USER www-data +# USER www-data CMD /bin/docker-entrypoint.sh \ No newline at end of file diff --git a/mapserver.conf b/mapserver.conf new file mode 100644 index 00000000..1a823da2 --- /dev/null +++ b/mapserver.conf @@ -0,0 +1,58 @@ +# +# Sample MapServer 8.0 Config File +# +CONFIG + + # + # Environment variables + # + ENV + # + # Limit Mapfile Access + # + # MS_MAP_NO_PATH "1" + MS_MAP_PATTERN "^/" ## required when referencing mapfiles by path + MS_MAP_BAD_PATTERN "[/\\]{2}|[/\\]?\\.+[/\\]|," + + # + # Global Log/Debug Setup + # + MS_DEBUGLEVEL "5" + # MS_ERRORFILE "/opt/mapserver/logs/mapserver.log" + + # + # Proj Library + # + # PROJ_DATA "/usr/local/share/proj" + + # + # Default Map + # + # MS_MAPFILE "/opt/mapserver/test/test.map" + + # disable POST requests (allowed by default, any value will do) + # MS_NO_POST "1" + + # + # Other Options + # + # MS_ENCRYPTION_KEY "/opt/mapserver/mykey.txt" + # MS_USE_GLOBAL_FT_CACHE 1 # use a global font cache + # MS_PDF_CREATION_DATE "01/02/2022" # PDF create date metadata + # MS_MAPFILE_PATTERN "\.map$" + # MS_XMLMAPFILE_XSLT "/path/to/mapfile.xsl" + # MS_MODE "BROWSE" # default mode for CGI calls + # MS_OPENLAYERS_JS_URL "http://openlayers.org/api/OpenLayers.js" + # MS_TEMPPATH "/tmp" + # MS_MAX_OPEN_FILES 200 # maximum number of open files allowed on Windows + # MS_WMS_ERROR_STATUS_CODE "ON" # enable HTTP status code 4xx and 5xx in case of errors on WMS requests + END + + # + # Map aliases + # + MAPS + TEST_MAPFILE "/opt/mapserver/water.map" + END + +END \ No newline at end of file From e0504770a649b39b71a0705f0e661dbb601cb6c6 Mon Sep 17 00:00:00 2001 From: Davey Oldenburg Date: Thu, 22 May 2025 11:55:11 +0200 Subject: [PATCH 02/15] Update klaar voor testen --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 251e7be1..e0455c12 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,5 +38,5 @@ RUN rm -rf /srv/mapserver/private EXPOSE 8080 -# USER www-data +USER www-data CMD /bin/docker-entrypoint.sh \ No newline at end of file From 17b7ad03156d5c0accfc89792187f25f5d3011b4 Mon Sep 17 00:00:00 2001 From: Davey Oldenburg Date: Thu, 5 Jun 2025 15:58:52 +0200 Subject: [PATCH 03/15] Errors verwijderen en test toevoegen. --- bag.map | 8 +++- gebieden.map | 4 +- test_wfs.py | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 test_wfs.py diff --git a/bag.map b/bag.map index 3001725a..32c4b2b4 100644 --- a/bag.map +++ b/bag.map @@ -37,7 +37,6 @@ MAP TYPE POLYGON MINSCALEDENOM 100 MAXSCALEDENOM 40001 - OPACITY 50 TEMPLATE "fooOnlyForWMSGetFeatureInfo.html" PROJECTION "init=epsg:28992" @@ -60,6 +59,7 @@ MAP COLOR 200 200 200 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 50 END END @@ -71,6 +71,7 @@ MAP COLOR 100 200 255 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 50 END END @@ -82,6 +83,7 @@ MAP COLOR 150 150 150 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 50 END END @@ -93,6 +95,7 @@ MAP COLOR 100 255 100 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 50 END END @@ -104,6 +107,7 @@ MAP COLOR 255 175 100 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 50 END END @@ -115,6 +119,7 @@ MAP COLOR 200 100 255 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 50 END END @@ -126,6 +131,7 @@ MAP COLOR 255 255 100 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 50 END END diff --git a/gebieden.map b/gebieden.map index c6fbef8a..f1f4357a 100644 --- a/gebieden.map +++ b/gebieden.map @@ -266,7 +266,7 @@ MAP TYPE POLYGON MINSCALEDENOM 100 MAXSCALEDENOM 20001 - OPACITY 60 + TEMPLATE "fooOnlyForWMSGetFeatureInfo.html" PROJECTION "init=epsg:28992" @@ -289,6 +289,7 @@ MAP COLOR 255 140 40 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 60 END END @@ -299,6 +300,7 @@ MAP COLOR 255 200 150 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 60 END END diff --git a/test_wfs.py b/test_wfs.py new file mode 100644 index 00000000..c5e2b28b --- /dev/null +++ b/test_wfs.py @@ -0,0 +1,111 @@ +import os +import requests +import xml.etree.ElementTree as ET + +# ✅ Base URL pattern for your MapServer instance +#BASE_URL = "http://localhost:8383/maps" +BASE_URL = "https://map.data.amsterdam.nl/maps" + +# ✅ Automatically use the same directory as the script +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +MAPFILES_DIR = SCRIPT_DIR + + +def get_mapfiles(directory): + """Find all .map files in the directory tree.""" + mapfiles = [] + for root, _, files in os.walk(directory): + for f in files: + if f.endswith(".map"): + mapfiles.append(os.path.join(root, f)) + return mapfiles + + +def check_geometry_present(base_url, typename): + """Do a WFS GetFeature request and check if a geometry exists.""" + params = { + "SERVICE": "WFS", + "VERSION": "2.0.0", + "REQUEST": "GetFeature", + "TYPENAME": typename, + "COUNT": 1, + "OUTPUTFORMAT": "application/gml+xml; version=3.2" + } + try: + response = requests.get(base_url, params=params, timeout=5) + response.raise_for_status() + root = ET.fromstring(response.content) + + # Dynamically get the GML namespace + nsmap = { + k if k else 'gml': v + for k, v in root.attrib.items() + if v.startswith("http://www.opengis.net/gml") + } + + # Search for any known geometry tag + for elem in root.iter(): + tag = elem.tag.lower() + if any(geom in tag for geom in ["polygon", "point", "linestring", "surface", "geometry"]): + return True + + # Fallback: check for boundedBy as minimal geometry presence + for elem in root.iter(): + if "boundedby" in elem.tag.lower(): + return True + + return False + except Exception as e: + print(f" ⚠️ Error checking geometry for {typename}: {e}") + return False + + +def get_wfs_layers(mapfile_path): + """Query WFS GetCapabilities and check each layer for geometry.""" + mapname = os.path.splitext(os.path.basename(mapfile_path))[0] + base_url = f"{BASE_URL}/{mapname}" + capabilities_url = f"{base_url}?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetCapabilities" + + try: + response = requests.get(capabilities_url, timeout=5) + response.raise_for_status() + root = ET.fromstring(response.content) + namespaces = {'wfs': 'http://www.opengis.net/wfs/2.0'} + layers = [] + + for ft in root.findall('.//wfs:FeatureType', namespaces): + name_elem = ft.find('wfs:Name', namespaces) + title_elem = ft.find('wfs:Title', namespaces) + typename = name_elem.text if name_elem is not None else None + title = title_elem.text if title_elem is not None else "(no title)" + + has_geometry = check_geometry_present(base_url, typename) if typename else False + + layers.append({ + "name": typename, + "title": title, + "geometry": has_geometry + }) + + return layers + + except Exception as e: + print(f"❌ Failed to read WFS from {mapname}: {e}") + return [] + + +def main(): + mapfiles = get_mapfiles(MAPFILES_DIR) + for m in mapfiles: + print(f"\n🗂️ Mapfile: {m}") + layers = get_wfs_layers(m) + if layers: + for layer in layers: + status = "✅ geometry found" if layer["geometry"] else "❌ no geometry" + print(f" - {layer['title']} [{layer['name']}] — {status}") + else: + print(" ⚠️ No WFS layers found or error parsing.") + + +if __name__ == "__main__": + main() \ No newline at end of file From 536319ef01ce277c7beb013e7dcef0d19b8f8677 Mon Sep 17 00:00:00 2001 From: Davey Oldenburg Date: Thu, 5 Jun 2025 16:09:59 +0200 Subject: [PATCH 04/15] Update bugfixes en meer --- gebieden.map | 1 - 1 file changed, 1 deletion(-) diff --git a/gebieden.map b/gebieden.map index f1f4357a..66eb33f2 100644 --- a/gebieden.map +++ b/gebieden.map @@ -266,7 +266,6 @@ MAP TYPE POLYGON MINSCALEDENOM 100 MAXSCALEDENOM 20001 - TEMPLATE "fooOnlyForWMSGetFeatureInfo.html" PROJECTION "init=epsg:28992" From 7958f5edbfb315f0322f05022cadec0d668dd09c Mon Sep 17 00:00:00 2001 From: Davey Oldenburg Date: Thu, 5 Jun 2025 16:20:17 +0200 Subject: [PATCH 05/15] Verwijderen test script --- test_wfs.py | 111 ---------------------------------------------------- 1 file changed, 111 deletions(-) delete mode 100644 test_wfs.py diff --git a/test_wfs.py b/test_wfs.py deleted file mode 100644 index c5e2b28b..00000000 --- a/test_wfs.py +++ /dev/null @@ -1,111 +0,0 @@ -import os -import requests -import xml.etree.ElementTree as ET - -# ✅ Base URL pattern for your MapServer instance -#BASE_URL = "http://localhost:8383/maps" -BASE_URL = "https://map.data.amsterdam.nl/maps" - -# ✅ Automatically use the same directory as the script -SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) -MAPFILES_DIR = SCRIPT_DIR - - -def get_mapfiles(directory): - """Find all .map files in the directory tree.""" - mapfiles = [] - for root, _, files in os.walk(directory): - for f in files: - if f.endswith(".map"): - mapfiles.append(os.path.join(root, f)) - return mapfiles - - -def check_geometry_present(base_url, typename): - """Do a WFS GetFeature request and check if a geometry exists.""" - params = { - "SERVICE": "WFS", - "VERSION": "2.0.0", - "REQUEST": "GetFeature", - "TYPENAME": typename, - "COUNT": 1, - "OUTPUTFORMAT": "application/gml+xml; version=3.2" - } - try: - response = requests.get(base_url, params=params, timeout=5) - response.raise_for_status() - root = ET.fromstring(response.content) - - # Dynamically get the GML namespace - nsmap = { - k if k else 'gml': v - for k, v in root.attrib.items() - if v.startswith("http://www.opengis.net/gml") - } - - # Search for any known geometry tag - for elem in root.iter(): - tag = elem.tag.lower() - if any(geom in tag for geom in ["polygon", "point", "linestring", "surface", "geometry"]): - return True - - # Fallback: check for boundedBy as minimal geometry presence - for elem in root.iter(): - if "boundedby" in elem.tag.lower(): - return True - - return False - except Exception as e: - print(f" ⚠️ Error checking geometry for {typename}: {e}") - return False - - -def get_wfs_layers(mapfile_path): - """Query WFS GetCapabilities and check each layer for geometry.""" - mapname = os.path.splitext(os.path.basename(mapfile_path))[0] - base_url = f"{BASE_URL}/{mapname}" - capabilities_url = f"{base_url}?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetCapabilities" - - try: - response = requests.get(capabilities_url, timeout=5) - response.raise_for_status() - root = ET.fromstring(response.content) - namespaces = {'wfs': 'http://www.opengis.net/wfs/2.0'} - layers = [] - - for ft in root.findall('.//wfs:FeatureType', namespaces): - name_elem = ft.find('wfs:Name', namespaces) - title_elem = ft.find('wfs:Title', namespaces) - typename = name_elem.text if name_elem is not None else None - title = title_elem.text if title_elem is not None else "(no title)" - - has_geometry = check_geometry_present(base_url, typename) if typename else False - - layers.append({ - "name": typename, - "title": title, - "geometry": has_geometry - }) - - return layers - - except Exception as e: - print(f"❌ Failed to read WFS from {mapname}: {e}") - return [] - - -def main(): - mapfiles = get_mapfiles(MAPFILES_DIR) - for m in mapfiles: - print(f"\n🗂️ Mapfile: {m}") - layers = get_wfs_layers(m) - if layers: - for layer in layers: - status = "✅ geometry found" if layer["geometry"] else "❌ no geometry" - print(f" - {layer['title']} [{layer['name']}] — {status}") - else: - print(" ⚠️ No WFS layers found or error parsing.") - - -if __name__ == "__main__": - main() \ No newline at end of file From 1a731cb4412909f2d49c539634fae3fe15be63ef Mon Sep 17 00:00:00 2001 From: Davey Oldenburg Date: Thu, 10 Apr 2025 12:00:21 +0200 Subject: [PATCH 06/15] WIP: Mapserver 8 update, config en dockerfile updates --- Dockerfile | 9 +++++--- mapserver.conf | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 mapserver.conf diff --git a/Dockerfile b/Dockerfile index f857521a..b42bd87f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.04 +FROM ubuntu:24.04 LABEL maintainer="datapunt@amsterdam.nl" ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update -y \ @@ -13,13 +13,16 @@ RUN apt-get update -y \ wget \ && apt-get clean -RUN python3 -m pip install --upgrade pip setuptools +RUN python -m pip install --upgrade pip setuptools # Enable these Apache modules RUN a2enmod actions cgid headers rewrite # Configure localhost in Apache RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf +COPY mapserver.conf /usr/local/etc/ +RUN echo "SetEnv MAPSERVER_CONFIG_FILE \"/usr/local/etc/mapserver.conf\"" >> /etc/apache2/apache2.conf + RUN rm /etc/apache2/mods-enabled/alias.conf COPY docker/000-default.conf /etc/apache2/sites-available/ COPY docker/docker-entrypoint.sh /bin @@ -37,5 +40,5 @@ RUN rm -rf /srv/mapserver/private EXPOSE 8080 -USER www-data +# USER www-data CMD /bin/docker-entrypoint.sh \ No newline at end of file diff --git a/mapserver.conf b/mapserver.conf new file mode 100644 index 00000000..1a823da2 --- /dev/null +++ b/mapserver.conf @@ -0,0 +1,58 @@ +# +# Sample MapServer 8.0 Config File +# +CONFIG + + # + # Environment variables + # + ENV + # + # Limit Mapfile Access + # + # MS_MAP_NO_PATH "1" + MS_MAP_PATTERN "^/" ## required when referencing mapfiles by path + MS_MAP_BAD_PATTERN "[/\\]{2}|[/\\]?\\.+[/\\]|," + + # + # Global Log/Debug Setup + # + MS_DEBUGLEVEL "5" + # MS_ERRORFILE "/opt/mapserver/logs/mapserver.log" + + # + # Proj Library + # + # PROJ_DATA "/usr/local/share/proj" + + # + # Default Map + # + # MS_MAPFILE "/opt/mapserver/test/test.map" + + # disable POST requests (allowed by default, any value will do) + # MS_NO_POST "1" + + # + # Other Options + # + # MS_ENCRYPTION_KEY "/opt/mapserver/mykey.txt" + # MS_USE_GLOBAL_FT_CACHE 1 # use a global font cache + # MS_PDF_CREATION_DATE "01/02/2022" # PDF create date metadata + # MS_MAPFILE_PATTERN "\.map$" + # MS_XMLMAPFILE_XSLT "/path/to/mapfile.xsl" + # MS_MODE "BROWSE" # default mode for CGI calls + # MS_OPENLAYERS_JS_URL "http://openlayers.org/api/OpenLayers.js" + # MS_TEMPPATH "/tmp" + # MS_MAX_OPEN_FILES 200 # maximum number of open files allowed on Windows + # MS_WMS_ERROR_STATUS_CODE "ON" # enable HTTP status code 4xx and 5xx in case of errors on WMS requests + END + + # + # Map aliases + # + MAPS + TEST_MAPFILE "/opt/mapserver/water.map" + END + +END \ No newline at end of file From 115201915b8b33c052946343e120f08e09e656b6 Mon Sep 17 00:00:00 2001 From: Davey Oldenburg Date: Thu, 22 May 2025 11:55:11 +0200 Subject: [PATCH 07/15] Update klaar voor testen --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b42bd87f..3eb6706d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,5 +40,5 @@ RUN rm -rf /srv/mapserver/private EXPOSE 8080 -# USER www-data +USER www-data CMD /bin/docker-entrypoint.sh \ No newline at end of file From b15919a04e8ba6239cdc4c4b13708bdb9392819b Mon Sep 17 00:00:00 2001 From: Davey Oldenburg Date: Thu, 5 Jun 2025 15:58:52 +0200 Subject: [PATCH 08/15] Errors verwijderen en test toevoegen. --- bag.map | 8 +++- gebieden.map | 4 +- test_wfs.py | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 test_wfs.py diff --git a/bag.map b/bag.map index 3001725a..32c4b2b4 100644 --- a/bag.map +++ b/bag.map @@ -37,7 +37,6 @@ MAP TYPE POLYGON MINSCALEDENOM 100 MAXSCALEDENOM 40001 - OPACITY 50 TEMPLATE "fooOnlyForWMSGetFeatureInfo.html" PROJECTION "init=epsg:28992" @@ -60,6 +59,7 @@ MAP COLOR 200 200 200 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 50 END END @@ -71,6 +71,7 @@ MAP COLOR 100 200 255 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 50 END END @@ -82,6 +83,7 @@ MAP COLOR 150 150 150 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 50 END END @@ -93,6 +95,7 @@ MAP COLOR 100 255 100 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 50 END END @@ -104,6 +107,7 @@ MAP COLOR 255 175 100 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 50 END END @@ -115,6 +119,7 @@ MAP COLOR 200 100 255 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 50 END END @@ -126,6 +131,7 @@ MAP COLOR 255 255 100 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 50 END END diff --git a/gebieden.map b/gebieden.map index c6fbef8a..f1f4357a 100644 --- a/gebieden.map +++ b/gebieden.map @@ -266,7 +266,7 @@ MAP TYPE POLYGON MINSCALEDENOM 100 MAXSCALEDENOM 20001 - OPACITY 60 + TEMPLATE "fooOnlyForWMSGetFeatureInfo.html" PROJECTION "init=epsg:28992" @@ -289,6 +289,7 @@ MAP COLOR 255 140 40 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 60 END END @@ -299,6 +300,7 @@ MAP COLOR 255 200 150 OUTLINECOLOR 172 172 172 WIDTH 1 + OPACITY 60 END END diff --git a/test_wfs.py b/test_wfs.py new file mode 100644 index 00000000..c5e2b28b --- /dev/null +++ b/test_wfs.py @@ -0,0 +1,111 @@ +import os +import requests +import xml.etree.ElementTree as ET + +# ✅ Base URL pattern for your MapServer instance +#BASE_URL = "http://localhost:8383/maps" +BASE_URL = "https://map.data.amsterdam.nl/maps" + +# ✅ Automatically use the same directory as the script +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +MAPFILES_DIR = SCRIPT_DIR + + +def get_mapfiles(directory): + """Find all .map files in the directory tree.""" + mapfiles = [] + for root, _, files in os.walk(directory): + for f in files: + if f.endswith(".map"): + mapfiles.append(os.path.join(root, f)) + return mapfiles + + +def check_geometry_present(base_url, typename): + """Do a WFS GetFeature request and check if a geometry exists.""" + params = { + "SERVICE": "WFS", + "VERSION": "2.0.0", + "REQUEST": "GetFeature", + "TYPENAME": typename, + "COUNT": 1, + "OUTPUTFORMAT": "application/gml+xml; version=3.2" + } + try: + response = requests.get(base_url, params=params, timeout=5) + response.raise_for_status() + root = ET.fromstring(response.content) + + # Dynamically get the GML namespace + nsmap = { + k if k else 'gml': v + for k, v in root.attrib.items() + if v.startswith("http://www.opengis.net/gml") + } + + # Search for any known geometry tag + for elem in root.iter(): + tag = elem.tag.lower() + if any(geom in tag for geom in ["polygon", "point", "linestring", "surface", "geometry"]): + return True + + # Fallback: check for boundedBy as minimal geometry presence + for elem in root.iter(): + if "boundedby" in elem.tag.lower(): + return True + + return False + except Exception as e: + print(f" ⚠️ Error checking geometry for {typename}: {e}") + return False + + +def get_wfs_layers(mapfile_path): + """Query WFS GetCapabilities and check each layer for geometry.""" + mapname = os.path.splitext(os.path.basename(mapfile_path))[0] + base_url = f"{BASE_URL}/{mapname}" + capabilities_url = f"{base_url}?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetCapabilities" + + try: + response = requests.get(capabilities_url, timeout=5) + response.raise_for_status() + root = ET.fromstring(response.content) + namespaces = {'wfs': 'http://www.opengis.net/wfs/2.0'} + layers = [] + + for ft in root.findall('.//wfs:FeatureType', namespaces): + name_elem = ft.find('wfs:Name', namespaces) + title_elem = ft.find('wfs:Title', namespaces) + typename = name_elem.text if name_elem is not None else None + title = title_elem.text if title_elem is not None else "(no title)" + + has_geometry = check_geometry_present(base_url, typename) if typename else False + + layers.append({ + "name": typename, + "title": title, + "geometry": has_geometry + }) + + return layers + + except Exception as e: + print(f"❌ Failed to read WFS from {mapname}: {e}") + return [] + + +def main(): + mapfiles = get_mapfiles(MAPFILES_DIR) + for m in mapfiles: + print(f"\n🗂️ Mapfile: {m}") + layers = get_wfs_layers(m) + if layers: + for layer in layers: + status = "✅ geometry found" if layer["geometry"] else "❌ no geometry" + print(f" - {layer['title']} [{layer['name']}] — {status}") + else: + print(" ⚠️ No WFS layers found or error parsing.") + + +if __name__ == "__main__": + main() \ No newline at end of file From d921658ef0134ef9f415d569ae17cee427bd2fee Mon Sep 17 00:00:00 2001 From: Davey Oldenburg Date: Thu, 5 Jun 2025 16:09:59 +0200 Subject: [PATCH 09/15] Update bugfixes en meer --- gebieden.map | 1 - 1 file changed, 1 deletion(-) diff --git a/gebieden.map b/gebieden.map index f1f4357a..66eb33f2 100644 --- a/gebieden.map +++ b/gebieden.map @@ -266,7 +266,6 @@ MAP TYPE POLYGON MINSCALEDENOM 100 MAXSCALEDENOM 20001 - TEMPLATE "fooOnlyForWMSGetFeatureInfo.html" PROJECTION "init=epsg:28992" From 047a2bfc1ce0efde3567cda23ebb6b46d077bc46 Mon Sep 17 00:00:00 2001 From: Davey Oldenburg Date: Thu, 5 Jun 2025 16:20:17 +0200 Subject: [PATCH 10/15] Verwijderen test script --- test_wfs.py | 111 ---------------------------------------------------- 1 file changed, 111 deletions(-) delete mode 100644 test_wfs.py diff --git a/test_wfs.py b/test_wfs.py deleted file mode 100644 index c5e2b28b..00000000 --- a/test_wfs.py +++ /dev/null @@ -1,111 +0,0 @@ -import os -import requests -import xml.etree.ElementTree as ET - -# ✅ Base URL pattern for your MapServer instance -#BASE_URL = "http://localhost:8383/maps" -BASE_URL = "https://map.data.amsterdam.nl/maps" - -# ✅ Automatically use the same directory as the script -SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) -MAPFILES_DIR = SCRIPT_DIR - - -def get_mapfiles(directory): - """Find all .map files in the directory tree.""" - mapfiles = [] - for root, _, files in os.walk(directory): - for f in files: - if f.endswith(".map"): - mapfiles.append(os.path.join(root, f)) - return mapfiles - - -def check_geometry_present(base_url, typename): - """Do a WFS GetFeature request and check if a geometry exists.""" - params = { - "SERVICE": "WFS", - "VERSION": "2.0.0", - "REQUEST": "GetFeature", - "TYPENAME": typename, - "COUNT": 1, - "OUTPUTFORMAT": "application/gml+xml; version=3.2" - } - try: - response = requests.get(base_url, params=params, timeout=5) - response.raise_for_status() - root = ET.fromstring(response.content) - - # Dynamically get the GML namespace - nsmap = { - k if k else 'gml': v - for k, v in root.attrib.items() - if v.startswith("http://www.opengis.net/gml") - } - - # Search for any known geometry tag - for elem in root.iter(): - tag = elem.tag.lower() - if any(geom in tag for geom in ["polygon", "point", "linestring", "surface", "geometry"]): - return True - - # Fallback: check for boundedBy as minimal geometry presence - for elem in root.iter(): - if "boundedby" in elem.tag.lower(): - return True - - return False - except Exception as e: - print(f" ⚠️ Error checking geometry for {typename}: {e}") - return False - - -def get_wfs_layers(mapfile_path): - """Query WFS GetCapabilities and check each layer for geometry.""" - mapname = os.path.splitext(os.path.basename(mapfile_path))[0] - base_url = f"{BASE_URL}/{mapname}" - capabilities_url = f"{base_url}?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetCapabilities" - - try: - response = requests.get(capabilities_url, timeout=5) - response.raise_for_status() - root = ET.fromstring(response.content) - namespaces = {'wfs': 'http://www.opengis.net/wfs/2.0'} - layers = [] - - for ft in root.findall('.//wfs:FeatureType', namespaces): - name_elem = ft.find('wfs:Name', namespaces) - title_elem = ft.find('wfs:Title', namespaces) - typename = name_elem.text if name_elem is not None else None - title = title_elem.text if title_elem is not None else "(no title)" - - has_geometry = check_geometry_present(base_url, typename) if typename else False - - layers.append({ - "name": typename, - "title": title, - "geometry": has_geometry - }) - - return layers - - except Exception as e: - print(f"❌ Failed to read WFS from {mapname}: {e}") - return [] - - -def main(): - mapfiles = get_mapfiles(MAPFILES_DIR) - for m in mapfiles: - print(f"\n🗂️ Mapfile: {m}") - layers = get_wfs_layers(m) - if layers: - for layer in layers: - status = "✅ geometry found" if layer["geometry"] else "❌ no geometry" - print(f" - {layer['title']} [{layer['name']}] — {status}") - else: - print(" ⚠️ No WFS layers found or error parsing.") - - -if __name__ == "__main__": - main() \ No newline at end of file From 59481910f41de0a477f6ecc99d043244da83dfcd Mon Sep 17 00:00:00 2001 From: Yashar Robert Date: Mon, 16 Jun 2025 13:28:34 +0200 Subject: [PATCH 11/15] Remove setuptools upgrade --- Dockerfile | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3eb6706d..4c205c21 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,8 +13,6 @@ RUN apt-get update -y \ wget \ && apt-get clean -RUN python -m pip install --upgrade pip setuptools - # Enable these Apache modules RUN a2enmod actions cgid headers rewrite @@ -22,18 +20,18 @@ RUN a2enmod actions cgid headers rewrite RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf COPY mapserver.conf /usr/local/etc/ RUN echo "SetEnv MAPSERVER_CONFIG_FILE \"/usr/local/etc/mapserver.conf\"" >> /etc/apache2/apache2.conf - + RUN rm /etc/apache2/mods-enabled/alias.conf COPY docker/000-default.conf /etc/apache2/sites-available/ COPY docker/docker-entrypoint.sh /bin -COPY . /srv/mapserver/ +COPY . /srv/mapserver/ COPY epsg /usr/share/proj # set apache user id matching ctr user id RUN usermod --non-unique --uid 999 www-data RUN groupmod -o -g 999 www-data -RUN mkdir /var/lock/apache2 && mkdir /var/run/apache2 +RUN mkdir /var/lock/apache2 && mkdir /var/run/apache2 RUN chown -R 999:999 /var/lock/apache2 && chown -R 999:999 /var/run/apache2 && chown -R 999:999 /var/log/apache2/ RUN chown -R 999:999 /srv/ && chown -R 999:999 /etc/apache2/ RUN rm -rf /srv/mapserver/private @@ -41,4 +39,4 @@ RUN rm -rf /srv/mapserver/private EXPOSE 8080 USER www-data -CMD /bin/docker-entrypoint.sh \ No newline at end of file +CMD /bin/docker-entrypoint.sh From f029651e676cc38f5268a7dd99d5b82bf84b9cc1 Mon Sep 17 00:00:00 2001 From: Davey Oldenburg Date: Tue, 27 Jan 2026 10:38:38 +0100 Subject: [PATCH 12/15] Making this ready for acc/prd, adding setuptools --- Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Dockerfile b/Dockerfile index 2c24e464..e464ebc7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,11 +13,15 @@ RUN apt-get update -y \ wget \ && apt-get clean +RUN python3 -m pip install --upgrade pip setuptools + # Enable these Apache modules RUN a2enmod actions cgid headers rewrite # Configure localhost in Apache RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf + +#config file COPY mapserver.conf /usr/local/etc/ RUN echo "SetEnv MAPSERVER_CONFIG_FILE \"/usr/local/etc/mapserver.conf\"" >> /etc/apache2/apache2.conf From 9d41e75d58bd6a07b0512305ddb42436affc610a Mon Sep 17 00:00:00 2001 From: Davey Oldenburg Date: Tue, 27 Jan 2026 11:10:45 +0100 Subject: [PATCH 13/15] Dit moet er toch uit.. --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e464ebc7..4d55339b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,6 @@ RUN apt-get update -y \ wget \ && apt-get clean -RUN python3 -m pip install --upgrade pip setuptools # Enable these Apache modules RUN a2enmod actions cgid headers rewrite From 0690be580abf0c34536ab805877bd0ef18aad985 Mon Sep 17 00:00:00 2001 From: Davey Oldenburg Date: Tue, 27 Jan 2026 11:23:31 +0100 Subject: [PATCH 14/15] Na overleg met ergu toch de setuptools laten zitten. --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 4d55339b..e464ebc7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,7 @@ RUN apt-get update -y \ wget \ && apt-get clean +RUN python3 -m pip install --upgrade pip setuptools # Enable these Apache modules RUN a2enmod actions cgid headers rewrite From 7e87a5b70d24a3ec8f0f78aba5c93798e9afb6df Mon Sep 17 00:00:00 2001 From: Davey Oldenburg Date: Tue, 27 Jan 2026 14:18:30 +0100 Subject: [PATCH 15/15] Erin eruit erin eruit. --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e464ebc7..4d55339b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,6 @@ RUN apt-get update -y \ wget \ && apt-get clean -RUN python3 -m pip install --upgrade pip setuptools # Enable these Apache modules RUN a2enmod actions cgid headers rewrite