Skip to content

Instantly share code, notes, and snippets.

@jgomo3
Last active March 20, 2024 08:32
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jgomo3/73f38cc5a91d85146ccf to your computer and use it in GitHub Desktop.
Save jgomo3/73f38cc5a91d85146ccf to your computer and use it in GitHub Desktop.
Proposal of Python examples for GeoServer REST API Documentation

Python

The examples in this section use the scripting language Python. They will be based en the cURL examples.

We'll be working with Python3 and only with the Python Standard Library exclusively, but I'll mention alternatives and more adequate 3th party libraries when relevant.

Python includes an http module with enough tools to interact with a REST API. Although it is recommended to use the requests library.

Preamble

First we need to import the necessary tools:

import requests
import json
from urllib.parse import urljoin

Then, lets define some variables we will reuse in all the examples as they will not change:

api_entry = 'http://localhost:8080/geoserver/rest/'
credential = ('admin', 'geoserver')

For all the examples, this preamble is assumed.

Adding a new Workspace

The following creates a new workspace named "acme" with a POST request:

resource = 'workspaces'
payload = {'workspace': {'name':'acme'}}
headers = {'content-type': 'application/json'}

request_url = urljoin(api_entry, resource)

r = requests.post(
    request_url,
    data=json.dumps(payload),
    headers=headers,
    auth=credential
)

r.raise_for_status()

The workspace information can be retrieved as JSON with a GET request:

resource = 'workspaces/acme'
headers = {'Accept' : 'application/json'}

request_url = urljoin(api_entry, resource)

r = requests.get(
    request_url,
    headers=headers,
    auth=credential
)

print(r.json())

The response should look like this:

{'workspace':
{'wmsStores': 'http://localhost:8080/geoserver/rest/workspaces/acme/wmsstores.json',
'dataStores': 'http://localhost:8080/geoserver/rest/workspaces/acme/datastores.json',
'coverageStores': 'http://localhost:8080/geoserver/rest/workspaces/acme/coveragestores.json',
'name': 'acme'}}

Uploading a shapefile

In this example a new store will be created by uploading a shapefile.

The following request uploads a zipped shapefile named roads.zip and creates a new store named roads.

resource = 'workspaces/acme/datastores/roads/file.shp'
file_name = 'roads.zip'
headers = {'content-type': 'application/zip'}

request_url = urljoin(api_entry, resource)

with open(file_name, 'rb') as f:
    r = requests.put(
        request_url,
        data=f,
        headers=headers,
        auth=credential
    )

The roads identifier in the URI refers to the name of the store to be created. To create a store named somethingelse, the URI would be http://localhost:8080/geoserver/rest/workspaces/acme/datastores/somethingelse/file.shp

The new sotore information can be retreived with a GET request:

resource = 'workspaces/acme/datastores/roads.json'
headers = {'content-type': 'application/json'}
request_url = urljoin(api_entry, resource)

r = requests.get(
    request_url,
    headers=headers,
    auth=credential
)

print(r.json())

When the shapefile is uploaded, a new feature type is also created. To see the feature type, issue a GET request with the adequate URI:

resource = 'workspaces/acme/datastores/roads/featuretype/roads.xml'
# ... Same code as above ...

Adding an existing shapefile

In the previous example a shapefile was uploaded directly to GeoServer by sending a zip file in the body of a PUT request. This example shows how to publish a shapefile that already exists on the server.

Consider a directory on the server /data/shapefiles/rivers that contains the shapefile rivers.shp. The following adds a new store for the shapefile:

resource = 'workspaces/acme/datastores/rivers/external.shp'
payload = 'file:data/shapefiles/rivers/rivers.shp'
headers = {'content-type': 'text/plain'}

request_url = urljoin(api_entry, resource)

r = requests.put(
    request_url,
    data=payload,
    headers=headers,
    auth=credential
)

r.raise_for_status()

The shapefile will be added to the existing store and published as a layer.

To verify the contents of the store, execute a GET request. Let's try for an HTML response:

resource = 'workspaces/acme/datastores/rivers.html'

request_url = urljoin(api_entry, resource)

r = requests.get(
    request_url,
    auth=credential
)

print(r.text)

Adding a directory of existing shapefiles

This example shows how to load and create a store that contains a number of shapefiles, all with a single operation. This example is very similar to the example above of adding a single shapefile.

Consider a directory on the server /data/shapefiles that contains multiple shapefiles. The following adds a new store for the directory:

resource = 'workspaces/acme/datastores/shapefiles/external.shp?configure=all'
payload = 'file:///data/data/shapefiles'
headers = {'content-type': 'text/plain'}

request_url = urljoin(api_entry, resource)

r = requests.put(
    request_url,
    data=payload,
    headers=headers,
    auth=credential
)

Note the configure=all query string parameter, which sets each shapefile in the directory to be loaded and published.

To verify the contents of the store, execute a GET request. Again, let's try with HTML:

resource = 'workspaces/acme/datastores/shapefiles.html'

request_url = urljoin(api_entry, resource)

r = requests.get(
    request_url,
    auth=credential
)

Creating a layer style

This example will create a new style on the server and populate it the contents of a local SLD file.

The following creates a new style named roads_style:

resource = 'styles'
payload = \
        '<style><name>roads_style</name><filename>roads.sld</filename></style>'
headers = {'content-type': 'text/xml'}


request_url = urljoin(api_entry, resource)

r = requests.post(
    request_url,
    data=payload,
    headers=headers,
    auth=credential
)

This request uploads a file called roads.sld file and populates the roads_style with its contents:

resource = 'styles/roads_style'
file_name = 'roads.sld'
headers = {'conten-type': 'application/vnd.ogc.sld+xml'}

request_url = urljoin(api_entry, resource)

with open(file_name, 'rb') as f:

    r = requests.put(
        request_url,
        data=f,
        headers=headers,
        auth=credential
    )
@MaxiReglisse
Copy link

MaxiReglisse commented Apr 14, 2019

thank you for this work!
a note however: if we run twice the creation of the workspace, we get a 500 error. it is therefore necessary to test the existence of the workspace before actually creating it.

r1 = test-if-workspace-alreary exists
if (r1.status_code == 200):
    the workspace already exists
elif (r1.status_code == 404):
    the workspace does not exist
    you have to create it
else:
    other problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment