Skip to content

Commit

Permalink
Enable WMS/WFS publication
Browse files Browse the repository at this point in the history
  • Loading branch information
JakobMiksch committed Aug 29, 2024
1 parent 0cc4b5f commit d091df8
Show file tree
Hide file tree
Showing 3 changed files with 453 additions and 4 deletions.
64 changes: 60 additions & 4 deletions docs/src/qsa-api/endpoints/projects.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,25 @@ empty.
| POST | `/api/projects/{project}/layers` | Add layer to project. See [Layer definition](#layer-definition) for more information. |
| POST | `/api/projects/{project}/layers/{layer}/style` | Add/Update layer's style with `name` (style name) and `current` (`true` or `false`) |
| DELETE | `/api/projects/{project}/layers/{layer}` | Remove layer from project |
| GET | `/api/projects/{project}/layers/wms` | List all published WMS layers |
| GET | `/api/projects/{project}/layers/wms/feature-info`| List WMS Feature Info settings |
| POST | `/api/projects/{project}/layers/wms/feature-info`| Change WMS Feature Info settings |
| GET | `/api/projects/{project}/layers/{layer}/wms` | List a published WMS layer's metadata |
| POST | `/api/projects/{project}/layers/{layer}/wms` | Toggle WMS publication status of an existing layer |
| GET | `/api/projects/{project}/layers/wfs` | List all published WFS layers |
| GET | `/api/projects/{project}/layers/{layer}/wfs` | List a published WFS layer's metadata |
| POST | `/api/projects/{project}/layers/{layer}/wfs` | Toggle WFS publication status of an existing vector layer |

#### Layer definition {#layer-definition}
### Layer definition {#layer-definition}

A layer can be added to a project thanks to the next parameters:

- `type` : `raster` or `vector`
- `name` : the layer's name
- `datasource` : the link to the datasource according to the storage backend
- filesystem : `/tmp/raster.tif`
- AWS S3 : `/vsis3/bucket/raster.tif`
- PostGIS : `service=qsa table=\"public\".\"lines\" (geom)`
- filesystem : `/tmp/raster.tif`
- AWS S3 : `/vsis3/bucket/raster.tif`
- PostGIS : `service=qsa table=\"public\".\"lines\" (geom)`
- `overview` (optional) : automatically build overviews for raster layers stored in S3 buckets
- `crs` (optional) : CRS (automatically detected by default)

Expand All @@ -81,6 +89,54 @@ $ curl "http://localhost/api/projects/my_project/layers" \
}'
````

### WMS

### Publication

QGIS Server publishes WMS layers automatically. These parameters are needed to change the publication status of a layer:

- `published` : If the layer shall be published as boolean. Allowed values: `true`, `false`

```` shell
$ curl "http://localhost/api/projects/my_project/layers/my_layer/wms" \
-X POST \
-H 'Content-Type: application/json' \
-d '{
"published": false
}'
````

### Feature Info

By default QGIS Server does not send the geometry on a WMS Feature Info request. This can be changed with this configuration:

- `publish_geometry`: If WMS Feature Info request shall return the geometry. Allowed values: `true`, `false`

```` shell
$ curl "http://localhost/api/projects/my_project/layers/wms/feature-info" \
-X POST \
-H 'Content-Type: application/json' \
-d '{
"publish_geometry": true
}'
````

### WFS Publication

These parameters are needed to publish an existing vector layer as WFS:

- `published` : If the layer shall be published as boolean. Allowed values: `true`, `false`
- `geometry_precision` (optional) : the geometric precision as integer, default is `8`

```` shell
$ curl "http://localhost/api/projects/my_project/layers/my_layer/wfs" \
-X POST \
-H 'Content-Type: application/json' \
-d '{
"published": true
}'
````

## Style

A QSA style may be used through the `STYLE` OGC web services parameter to
Expand Down
217 changes: 217 additions & 0 deletions qsa-api/qsa_api/api/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,224 @@ def project_info_layer(name, layer_name):
except Exception as e:
logger().exception(str(e))
return {"error": "internal server error"}, 415

@projects.get("/<name>/layers/wms")
def project_layers_wms(name):
"""
Get all published WMS layers
"""
log_request()
try:
psql_schema = request.args.get("schema", default="public")
project = QSAProject(name, psql_schema)
if project.exists():
return jsonify(project.layers_wms), 201
else:
return {"error": "Project does not exist"}, 415
except Exception as e:
logger().exception(str(e))
return {"error": "internal server error"}, 415

@projects.get("/<name>/layers/wms/feature-info")
def project_wms_feature_info(name):
"""
Information about the WMS Feature Info settings
"""
log_request()
try:
psql_schema = request.args.get("schema", default="public")
project = QSAProject(name, psql_schema)
if project.exists():
return jsonify(project.project_wms_feature_info), 201
else:
return {"error": "Project does not exist"}, 415
except Exception as e:
logger().exception(str(e))
return {"error": "internal server error"}, 415


@projects.get("/<name>/layers/wfs")
def project_layers_wfs(name):
"""
Get all published WFS layers
"""
log_request()
try:
psql_schema = request.args.get("schema", default="public")
project = QSAProject(name, psql_schema)
if project.exists():
return jsonify(project.layers_wfs_info), 201
else:
return {"error": "Project does not exist"}, 415
except Exception as e:
logger().exception(str(e))
return {"error": "internal server error"}, 415

@projects.get("/<name>/layers/<layer_name>/wfs")
def project_info_layer_wfs(name, layer_name):
"""
Get information about a single WFS layer
"""
log_request()
try:
psql_schema = request.args.get("schema", default="public")
project = QSAProject(name, psql_schema)
if project.exists():
return jsonify(project.layer_wfs(layer_name)), 201
else:
return {"error": "Project does not exist"}, 415
except Exception as e:
logger().exception(str(e))
return {"error": "internal server error"}, 415

@projects.get("/<name>/layers/<layer_name>/wms")
def project_info_layer_wms(name, layer_name):
"""
Get information about a single WMS layer
"""
log_request()
try:
psql_schema = request.args.get("schema", default="public")
project = QSAProject(name, psql_schema)
if project.exists():
return jsonify(project.layer_wms(layer_name)), 201
else:
return {"error": "Project does not exist"}, 415
except Exception as e:
logger().exception(str(e))
return {"error": "internal server error"}, 415

@projects.post("/<name>/layers/<layer_name>/wfs")
def project_publish_wfs_layer(name, layer_name):
"""
Change WFS publication status of an vector layer
"""
log_request()
try:
json_schema = {
"type": "object",
"required": ["published"],
"properties": {
"published": {"type": "boolean"},
"geometry_precision": {"type": "integer"}
},
}

psql_schema = request.args.get("schema", default="public")
project = QSAProject(name, psql_schema)

if project.exists():
data = request.get_json()
try:
validate(data, json_schema)
except ValidationError as e:
return {"error": e.message}, 415

published = data["published"]

geometry_precision = 8 # default value in QGIS Server

if "geometry_precision" in data:
geometry_precision = data["geometry_precision"]

project = QSAProject(name, psql_schema)

rc, err = project.publish_wfs_layer(layer_name, published, geometry_precision)

if err:
return {"error": err}, 415
return jsonify(rc), 201

else:
return {"error": "Project does not exist"}, 415

except Exception as e:
logger().exception(str(e))
return {"error": "internal server error"}, 415

@projects.post("/<name>/layers/<layer_name>/wms")
def project_publish_wms_layer(name, layer_name):
"""
Change WMS publication status of an vector layer
"""
log_request()
try:
json_schema = {
"type": "object",
"required": ["published"],
"properties": {
"published": {"type": "boolean"}
},
}

psql_schema = request.args.get("schema", default="public")
project = QSAProject(name, psql_schema)

if project.exists():
data = request.get_json()
try:
validate(data, json_schema)
except ValidationError as e:
return {"error": e.message}, 415

published = data["published"]

project = QSAProject(name, psql_schema)

rc, err = project.publish_wms_layer(layer_name, published)

if err:
return {"error": err}, 415
return jsonify(rc), 201

else:
return {"error": "Project does not exist"}, 415

except Exception as e:
logger().exception(str(e))
return {"error": "internal server error"}, 415

@projects.post("/<name>/layers/wms/feature-info")
def project_wms_adjust_feature_info(name):
"""
Adjust the WMS Feature Info settings
"""
log_request()
try:
json_schema = {
"type": "object",
"required": ["publish_geometry"],
"properties": {
"publish_geometry": {"type": "boolean"}
},
}

psql_schema = request.args.get("schema", default="public")
project = QSAProject(name, psql_schema)

if project.exists():
data = request.get_json()
try:
validate(data, json_schema)
except ValidationError as e:
return {"error": e.message}, 415

publish_geometry = data["publish_geometry"]

project = QSAProject(name, psql_schema)

rc, err = project.wms_adjust_feature_info(publish_geometry)

if err:
return {"error": err}, 415
return jsonify(rc), 201

else:
return {"error": "Project does not exist"}, 415

except Exception as e:
logger().exception(str(e))
return {"error": "internal server error"}, 415

@projects.delete("/<name>/layers/<layer_name>")
def project_del_layer(name, layer_name):
Expand Down
Loading

0 comments on commit d091df8

Please sign in to comment.