From 762f7c959b2b4c0af6126a16730aea8848399847 Mon Sep 17 00:00:00 2001
From: carderm <7568993+carderm@users.noreply.github.com>
Date: Thu, 11 Nov 2021 02:48:52 +1100
Subject: [PATCH 1/2] Fix for WMS Geoserver API error. Request changed to
include Files. (#17)
* Removed WMS Store from href due to REST error
This is a workaround for a Geoserver issue - including store name in the URL causes a failure in Geoserver (500 error) but works (200) without.
For Geoserver Testing see:
https://docs.geoserver.org/stable/en/api/#1.0.0/wmslayers.yaml
1. PUT for /workspaces/{workspace}/wmslayers/{wmslayer} - WORKS!
2. PUT for /workspaces/{workspace}/wmsstores/{wmsstore}/wmslayers - FAILS!
Sample xml payload to enable/disable a wmslayer:
true
true
* Fix for http_request to allow files to be uploaded. E.g. for importing shapefiles via Importer.
* Fixes editing existing styles - requires recursive flag to get existing format
* Fixes for creating/listing Geoserver styles with recursion.
---
.gitignore | 1 +
examples/layersusing.py | 2 +-
src/geoserver/catalog.py | 44 +++++++++++++++++++++------------------
src/geoserver/resource.py | 4 ++--
4 files changed, 28 insertions(+), 23 deletions(-)
diff --git a/.gitignore b/.gitignore
index 72eda3a..9696627 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ include/
lib/
lib64
doc/_build/
+.idea/
diff --git a/examples/layersusing.py b/examples/layersusing.py
index ff4adaa..d58e380 100644
--- a/examples/layersusing.py
+++ b/examples/layersusing.py
@@ -20,4 +20,4 @@ def has_the_style(l):
return (l.default_style.name == style_to_check or
any(s.name == style_to_check for s in l.styles))
-print [l.name for l in cat.get_layers() if has_the_style(l)]
+print([l.name for l in cat.get_layers() if has_the_style(l)])
diff --git a/src/geoserver/catalog.py b/src/geoserver/catalog.py
index 700023f..c3de207 100644
--- a/src/geoserver/catalog.py
+++ b/src/geoserver/catalog.py
@@ -141,7 +141,7 @@ def setup_connection(self, retries=3, backoff_factor=0.9):
)
self.client.mount("{}://".format(parsed_url.scheme), HTTPAdapter(max_retries=retry))
- def http_request(self, url, data=None, method='get', headers={}):
+ def http_request(self, url, data=None, method='get', headers={}, files=None):
req_method = getattr(self.client, method.lower())
if self.access_token:
@@ -152,14 +152,13 @@ def http_request(self, url, data=None, method='get', headers={}):
params = urlencode(params)
url = "{proto}://{address}{path}?{params}".format(proto=parsed_url.scheme, address=parsed_url.netloc,
path=parsed_url.path, params=params)
-
- resp = req_method(url, headers=headers, data=data)
- else:
+ elif self.username and self.password:
valid_uname_pw = base64.b64encode(
("%s:%s" % (self.username, self.password)).encode("utf-8")).decode("ascii")
headers['Authorization'] = 'Basic {}'.format(valid_uname_pw)
- resp = req_method(url, headers=headers, data=data)
- return resp
+
+ return req_method(url, headers=headers, data=data, files=files)
+
def get_version(self):
'''obtain the version or just 2.2.x if < 2.3.x
@@ -1070,11 +1069,18 @@ def get_styles(self, names=None, workspaces=None, recursive=False):
Will always return an array.
'''
all_styles = []
+
+ # Get Names first to speed up recursive queries
+ if names is None:
+ names = []
+ elif isinstance(names, string_types):
+ names = [s.strip() for s in names.split(',') if s.strip()]
+
if not workspaces:
# Add global styles
url = "{}/styles.xml".format(self.service_url)
styles = self.get_xml(url)
- all_styles += self.__build_style_list(styles, recursive=recursive)
+ all_styles += self.__build_style_list(styles, recursive=recursive, names=names)
workspaces = []
elif isinstance(workspaces, string_types):
workspaces = [s.strip() for s in workspaces.split(',') if s.strip()]
@@ -1098,32 +1104,30 @@ def get_styles(self, names=None, workspaces=None, recursive=False):
continue
else:
raise FailedRequestError("Failed to get styles: {}".format(e))
- all_styles += self.__build_style_list(styles, workspace=ws, recursive=recursive)
-
- if names is None:
- names = []
- elif isinstance(names, string_types):
- names = [s.strip() for s in names.split(',') if s.strip()]
+ all_styles += self.__build_style_list(styles, workspace=ws, recursive=recursive, names=names)
if all_styles and names:
return ([style for style in all_styles if style.name in names])
return all_styles
- def __build_style_list(self, styles_tree, workspace=None, recursive=False):
+ def __build_style_list(self, styles_tree, workspace=None, recursive=False, names=None):
all_styles = []
for s in styles_tree.findall("style"):
try:
+ style_name = s.find('name').text
+ if names and style_name not in names:
+ continue
if recursive:
- style_format = self.get_xml(s[1].attrib.get('href')).find('format').text
- style_version = self.get_xml(s[1].attrib.get('href')).find('languageVersion').find(
- 'version').text.replace('.', '')[:-1]
+ style_xml = self.get_xml(s[1].attrib.get('href'))
+ style_format = style_xml.find('format').text
+ style_version = style_xml.find('languageVersion').find('version').text.replace('.', '')[:-1]
all_styles.append(
- Style(self, s.find("name").text, _name(workspace), style_format + style_version)
+ Style(self, style_name, _name(workspace), style_format + style_version)
)
else:
all_styles.append(
- Style(self, s.find('name').text, _name(workspace))
+ Style(self, style_name, _name(workspace))
)
except Exception:
all_styles.append(
@@ -1142,7 +1146,7 @@ def get_style(self, name, workspace=None, recursive=False):
return self._return_first_item(styles)
def create_style(self, name, data, overwrite=False, workspace=None, style_format="sld10", raw=False):
- styles = self.get_styles(names=name, workspaces=[workspace])
+ styles = self.get_styles(names=name, workspaces=[workspace], recursive=True)
if len(styles) > 0:
style = styles[0]
else:
diff --git a/src/geoserver/resource.py b/src/geoserver/resource.py
index 099c7e8..b4dd92e 100644
--- a/src/geoserver/resource.py
+++ b/src/geoserver/resource.py
@@ -275,11 +275,11 @@ def __init__(self, catalog, workspace, store, name):
@property
def href(self):
+ # Removed Store from this due to error in the Rest API when including store
return urljoin(
"{}/".format(self.catalog.service_url),
- "workspaces/{}/wmsstores/{}/wmslayers/{}.xml".format(
+ "workspaces/{}/wmslayers/{}.xml".format(
self.workspace.name,
- self.store.name,
self.name
)
)
From 422a36beaf2a73f2b49b02f0d6e5d39722d58c81 Mon Sep 17 00:00:00 2001
From: Guillaume Troupel
Date: Wed, 10 Nov 2021 16:49:03 +0100
Subject: [PATCH 2/2] fix python 3.9+ incompatibility (#19)
* fix python 3.9+ incompatibility
https://github.com/GeoNode/geoserver-restconfig/issues/18
* python 3.9+
Co-authored-by: Alessio Fabiani
---
src/geoserver/layer.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/geoserver/layer.py b/src/geoserver/layer.py
index 75dd79b..6dc9f49 100644
--- a/src/geoserver/layer.py
+++ b/src/geoserver/layer.py
@@ -134,7 +134,7 @@ def resource(self):
if self.dom is None:
self.fetch()
name = self.dom.find("resource/name").text
- atom_link = [n for n in self.dom.find("resource").getchildren() if 'href' in n.attrib]
+ atom_link = [n for n in self.dom.find("resource") if 'href' in n.attrib]
ws_name = workspace_from_url(atom_link[0].get('href'))
if self.gs_version >= "2.13":
if ":" in name:
@@ -158,7 +158,7 @@ def _resolve_style(self, element):
else:
style_name = element.find('name').text
ws_name = None
- atom_link = [n for n in element.getchildren() if 'href' in n.attrib]
+ atom_link = [n for n in element if 'href' in n.attrib]
if atom_link and ws_name is None:
ws_name = workspace_from_url(atom_link[0].get("href"))
return self.catalog.get_styles(names=style_name, workspaces=ws_name)[0]