From 258d4454035b51c0306b6a2e2852f46b49ac9651 Mon Sep 17 00:00:00 2001 From: rng Date: Wed, 7 Jan 2026 10:27:55 +1100 Subject: [PATCH] Rewrite url when missing workspace --- .../ogcapi/server/core/service/CacheWarm.java | 4 +- .../server/core/service/wms/WmsServer.java | 48 ++++++++++++++++++- .../core/service/wms/WmsServerTest.java | 29 +++++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/service/CacheWarm.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/service/CacheWarm.java index 03b3b687..d90abd58 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/service/CacheWarm.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/service/CacheWarm.java @@ -27,6 +27,8 @@ public class CacheWarm { "https://www.cmar.csiro.au/geoserver/ereefs/wms", "https://www.cmar.csiro.au/geoserver/ea-be/wms", "https://www.cmar.csiro.au/geoserver/gsfm/wms", + "https://www.cmar.csiro.au/geoserver/local/wms", + "https://www.cmar.csiro.au/geoserver/mnf/wms", "https://www.cmar.csiro.au/geoserver/nerp/wms", "https://www.cmar.csiro.au/geoserver/AusSeabed/wms", "https://geoserver.apps.aims.gov.au/aims/wms", @@ -78,7 +80,7 @@ protected void evictGetCapabilities(String key){ ); } - @Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000)) + @Retryable(maxAttempts = 5, backoff = @Backoff(delay = 1000)) protected void warmGetCapabilities(String url) { try { // Call and warm cache diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/service/wms/WmsServer.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/service/wms/WmsServer.java index 26986807..9d095f18 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/service/wms/WmsServer.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/service/wms/WmsServer.java @@ -311,7 +311,44 @@ protected List createMapDescribeUrl(String url, String uuid, FeatureRequ } return null; } + /** + * Some URL provided will miss the workspace in url event the layername is xxx:yyy where xxx is workspace + * it is a typo in the metadata but manual fix will be very time consuming, so we can safely assume rewrite + * the URL will work as it is a geoserver standard. + * @param url - URl that may or may not missing the work space + * @param request - Request that contains layer name + * @return - A rewrite URL or original URL depends on logic + */ + protected static String rewriteUrlWithWorkSpace(String url, FeatureRequest request) { + if(request.getLayerName().contains(":")) { + String workspace = request.getLayerName().split(":")[0]; + UriComponents components = UriComponentsBuilder.fromUriString(url).build(); + String workspacePatternInURL = String.format("/%s/", workspace); + if(components.getPath() != null && !components.getPath().contains(workspacePatternInURL)) { + // Need rewrite, get a writable list + List segments = new ArrayList<>(components.getPathSegments()); + segments.add(segments.size() - 1, workspace); + + return UriComponentsBuilder.newInstance() + .scheme(components.getScheme()) + .host(components.getHost()) + .path("/" + String.join("/", segments)) + .queryParams(components.getQueryParams()) + .build() + .toUriString(); + } + } + return url; + } + /** + * Create the URL to WMS to get the map feature, in this case it will be the content of the popup when you click + * the map. + * @param url - URL to WMS + * @param uuid - UUID of record + * @param request - Feature requested + * @return - List of URL point to the wms queuing map features + */ protected List createMapFeatureQueryUrl(String url, String uuid, FeatureRequest request) { try { UriComponents components = UriComponentsBuilder.fromUriString(url).build(); @@ -490,7 +527,6 @@ public DescribeLayerResponse describeLayer(String collectionId, FeatureRequest r } return null; } - /** * Get the wms image/png tile * @@ -602,7 +638,13 @@ public List fetchCapabilitiesLayersByUrl(String wmsServerUrl) { * Get filtered layers from WMS GetCapabilities for a specific collection, we use this function because we do not * trust the WMS layer value because it can be wrong, we use the WFS link to infer the layer and therefore the layer * name return will be operational with WFS function. + *

* First fetches all layers (cached by URL), then filters by WFS links (cached by UUID) + *

+ * Sometimes the URL provided by WMS link is not optimal, for example + * ... + * will result in timeout due to too big query, if layername inside request have format xxx:yyyy then + * we can use xxx as the workspace name and rewrite the URL to https://www.cmar.csiro.au/geoserver/xxx/wms * * @param collectionId - The uuid * @param request - The request param @@ -613,7 +655,9 @@ public List getCapabilitiesLayers(String collectionId, FeatureRequest if (mapServerUrl.isPresent()) { // Fetch all layers from GetCapabilities (this call is cached by URL) - List allLayers = self.fetchCapabilitiesLayersByUrl(mapServerUrl.get()); + // Special rewrite to speed up query + String url = rewriteUrlWithWorkSpace(mapServerUrl.get(), request); + List allLayers = self.fetchCapabilitiesLayersByUrl(url); if (!allLayers.isEmpty()) { // Filter layers based on WFS link matching diff --git a/server/src/test/java/au/org/aodn/ogcapi/server/core/service/wms/WmsServerTest.java b/server/src/test/java/au/org/aodn/ogcapi/server/core/service/wms/WmsServerTest.java index d6ad334f..6fe78f58 100644 --- a/server/src/test/java/au/org/aodn/ogcapi/server/core/service/wms/WmsServerTest.java +++ b/server/src/test/java/au/org/aodn/ogcapi/server/core/service/wms/WmsServerTest.java @@ -599,4 +599,33 @@ public void verifyCreateCQLRangeDateTimeWithCQL() { assertEquals("CQL_FILTER=start_juld >= 2023-01-01 AND end_juld <= 2023-12-31 AND set_code=1234", result); } + + @Test + void testRewriteUrlWithWorkSpace() { + FeatureRequest req = FeatureRequest.builder() + .layerName("xxx:yyy") + .build(); + + // Case 1: Layer with workspace, URL without workspace + String url1 = "https://example.com/geoserver/wms?service=WMS"; + String result1 = WmsServer.rewriteUrlWithWorkSpace(url1, req); + assertEquals("https://example.com/geoserver/xxx/wms?service=WMS", result1); + + // Case 2: No workspace in layer name + req.setLayerName("yyy"); + String result2 = WmsServer.rewriteUrlWithWorkSpace(url1, req); + assertEquals(url1, result2); + + // Case 3: Workspace already in URL + req.setLayerName("xxx:yyy"); + String url3 = "https://example.com/geoserver/xxx/wms"; + String result3 = WmsServer.rewriteUrlWithWorkSpace(url3, req); + assertEquals(url3, result3); + + // Case 4: Different service (wfs) + req.setLayerName("xxx:yyy"); + String url4 = "https://example.com/geoserver/wfs"; + String result4 = WmsServer.rewriteUrlWithWorkSpace(url4, req); + assertEquals("https://example.com/geoserver/xxx/wfs", result4); + } }