QWC FeatureInfo Service¶
Query layers at a geographic position using an API based on WMS GetFeatureInfo.
The query is handled for each layer by its layer info provider configured in the config file.
Layer info providers:
- WMS GetFeatureInfo (default): forward info request to the QGIS Server
- DB Query: execute custom query SQL
- Custom info module: custom Python modules returning layer info
The info results are each rendered into customizable HTML templates and returned as a GetFeatureInfoResponse XML.
Configuration¶
The static config and permission files are stored as JSON files in $CONFIG_PATH with subdirectories for each tenant,
e.g. $CONFIG_PATH/default/*.json. The default tenant name is default.
JSON config¶
- JSON schema
- File location:
$CONFIG_PATH/<tenant>/featureInfoConfig.json
Note: Use the qwc-config-generator to automatically generate the resource configuration. Manually provided configuration is merged into the automatically generated configuration by service and layer name. I.e. the configuration for countries in the example below just specifies the info template, attributes configuration will completed by the config generator.
Example:
{
"$schema": "https://raw.githubusercontent.com/qwc-services/qwc-feature-info-service/master/schemas/qwc-feature-info-service.json",
"service": "feature-info",
"config": {
"default_qgis_server_url": "http://localhost:8001/ows/"
},
"resources": {
"wms_services": [
{
"name": "qwc_demo",
"root_layer": {
"name": "qwc_demo",
"layers": [
{
"name": "edit_demo",
"title": "Edit Demo",
"layers": [
{
"name": "edit_points",
"title": "Edit Points",
"attributes": [
{
"name": "id"
},
{
"name": "name"
},
{
"name": "description"
},
{
"name": "num"
},
{
"name": "value"
},
{
"name": "type"
},
{
"name": "amount"
},
{
"name": "validated",
"format": "{\"t\": \"Yes\", \"f\": \"No\"}"
},
{
"name": "datetime"
},
{
"name": "geometry"
},
{
"name": "maptip"
}
]
}
]
},
{
"name": "countries",
"info_template": {
"type": "wms",
"wms_url": "http://localhost:8001/ows/qwc_demo",
"template": "<div><h2>Demo Template</h2>Pos: {{ x }}, {{ y }}<br>Name: {{ feature.Name }}</div>"
}
}
]
}
}
]
}
}
See the schema definition for the full set of supported config variables.
Example info_template for WMS GetFeatureInfo:
"info_template": {
"type": "wms",
"wms_url": "http://localhost:8001/ows/qwc_demo",
"template": "<div><h2>Demo Template</h2>Pos: {{ x }}, {{ y }}<br>Name: {{ feature.Name }}</div>"
}
Example info_template for WMS GetFeatureInfo with template path:
"info_template": {
"type": "wms",
"wms_url": "http://localhost:8001/ows/qwc_demo",
"template_path": "/info_templates/template.html"
}
Example info_template for DB query:
"info_template": {
"type": "sql",
"db_url": "postgresql:///?service=qwc_geodb",
"sql": "SELECT ogc_fid as _fid_, name, formal_en, pop_est, subregion, ST_AsText(wkb_geometry) as wkt_geom FROM qwc_geodb.ne_10m_admin_0_countries WHERE ST_Intersects(wkb_geometry, ST_GeomFromText(:geom, :srid)) LIMIT :feature_count;",
"template": "<div><h2>Demo Template</h2>Pos: {{ x }}, {{ y }}<br>Name: {{ feature.Name }}</div>"
}
Note: x, y and geom are passed as parameters to the SQL query. If a GetFeatureInfo request is being processed with a filter_geom parameter, geom will correspond to that parameter. Otherwise geom will be POINT(x y).
Example info_template for Custom info module:
"info_template": {
"type": "module",
"module": "example",
"template": "<div><h2>Demo Template</h2>Pos: {{ x }}, {{ y }}<br>Name: {{ feature.Name }}</div>"
}
Note: The following config properties may also be set as Base64 encoded values instead:
- Default HTML info template:
default_info_template_base64 - Formatting expression for converting attribute values:
format_base64 - HTML template for info result:
template_base64 - Query SQL for DB query:
sql_base64
Any plain text properties take precedence over their corresponding Base64 encoded property (e.g. template_base64 is only used if template is not set).
Environment variables¶
Config options in the config file can be overridden by equivalent uppercase environment variables.
In addition, the following environment variables are supported:
| Name | Default | Description |
|---|---|---|
LANG |
C |
Set locale Admin GUI language (see src/translations for available languages). |
Permissions¶
- JSON schema
- File location:
$CONFIG_PATH/<tenant>/permissions.json
Example:
{
"$schema": "https://raw.githubusercontent.com/qwc-services/qwc-services-core/master/schemas/qwc-services-permissions.json",
"users": [
{
"name": "demo",
"groups": ["demo"],
"roles": []
}
],
"groups": [
{
"name": "demo",
"roles": ["demo"]
}
],
"roles": [
{
"role": "public",
"permissions": {
"wms_services": [
{
"name": "qwc_demo",
"ows_type": "WMS",
"layers": [
{
"name": "qwc_demo"
},
{
"name": "edit_demo"
},
{
"name": "edit_points",
"attributes": [
"id", "name", "description", "num", "value", "type", "amount", "validated",
"datetime", "geometry", "maptip"
]
},
{
"name": "countries",
"attributes": ["name", "formal_en", "pop_est", "subregion", "geometry"],
"info_template": true
}
]
}
]
}
}
]
}
Basic Auth¶
The feature info service be configured to accept password authentication using Basic authentication.
Example:
"config": {
"basic_auth_login_url": ["http://qwc-auth-service:9090/verify_login"]
},
HTML template¶
A HTML template can be provided for a layer in the config file.
The template must only contain the body content (without head, script, body).
The HTML can be styled using inline CSS, otherwise the CSS from the QWC viewer is used.
This template can contain attribute value placeholders, in the form
{{ feature.attr }}
which are replaced with the respective values when the template is rendered (using Jinja2). The following values are available in the template:
x,y,crs: Coordinates and CRS of info queryfeature: Feature with attributes from info result as properties, e.g.feature.namefid: Feature ID (if present)bbox: Feature bounding box as[<minx>, <miny>, <maxx>, <maxy>](if present)geometry: Feature geometry as WKT (if present)layer: Layer namerender_value: Function which detects special value formats and renders them accordingly (i.e. hyperlinks and image URLs)locale: The Locale module, allows i.e. locale aware number formattingrequest: The original request, useful for extracting i.e. request origin etc.
Example:
<div>Result at coordinates {{ x }}, {{ y }}</div>
<table>
<tr>
<td>Name:</td>
<td>{{ feature.name }}</td>
</tr>
<tr>
<td>Description:</td>
<td>{{ feature.description }}</td>
</tr>
<tr>
<td>Link:</td>
<td>{{ render_value(feature.link) }}</td>
</tr>
</table>
Default info template¶
A default info template can provided via default_info_template in the config file.
It will be used for all layers with no assigned info templates.
The InfoFeature feature available in the template also provides a list of its attributes:
feature._attributes = [
'name': <attribute name>,
'value': <attribute value>,
'alias': <attribute alias>,
'type': <attribute value data type as string>,
'json_aliases': <JSON attribute aliases as {'json_key': 'value'}>
]
If an attribute value starts with { or [ the service tries to parse it as JSON before rendering it in the template.
DB Query¶
In a DB Query the following values are replaced in the SQL:
:x: X coordinate of query:y: Y coordinate of query:srid: SRID of query coordinates:resolution: Resolution in map units per pixel:FI_POINT_TOLERANCE: Tolerance for picking points, in pixels (default=16):FI_LINE_TOLERANCE: Tolerance for picking lines, in pixels (default=8):FI_POLYGON_TOLERANCE: Tolerance for picking polygons, in pixels (default=4):i: X ordinate of query point on map, in pixels:j: Y ordinate of query point on map, in pixels:height: Height of map output, in pixels:width: Width of map output, in pixels:bbox: 'Bounding box for map extent as minx,miny,maxx,maxy':crs: 'CRS for map extent':feature_count: Max feature count:with_geometry: Whether to return geometries in response (default=1):with_maptip: Whether to return maptip in response (default=1):geom: Thefilter_geompassed to theGetFeatureInforequest, if any, otherwisePOINT(x y)
The query may return the feature ID as _fid_ and the WKT geometry as wkt_geom. All other selected columns are used as feature attributes.
Sample queries:
SELECT ogc_fid as _fid_, name, ...,
ST_AsText(wkb_geometry) as wkt_geom
FROM schema.table
WHERE ST_Intersects(wkb_geometry, ST_GeomFromText('POINT(:x :y)', :srid))
LIMIT :feature_count;
SELECT ogc_fid as _fid_, name, ...,
ST_AsText(wkb_geometry) as wkt_geom
FROM schema.table
WHERE ST_Intersects(
wkb_geometry,
ST_Buffer(
ST_GeomFromText('POINT(:x :y)', :srid),
:resolution * :FI_POLYGON_TOLERANCE
)
)
LIMIT :feature_count;
Custom info modules¶
Custom info modules can be placed in ./info_modules/custom/<module name>/ and must provide the following method:
def layer_info(layer, x, y, crs, params, identity)
Input parameters:
layer(str): Layer namex(float): X coordinate of queryy(float): Y coordinate of querycrs(str): CRS of query coordinates-
params(obj): FeatureInfo service params{ 'i': <X ordinate of query point on map, in pixels>, 'j': <Y ordinate of query point on map, in pixels>, 'height': <Height of map output, in pixels>, 'width': <Width of map output, in pixels>, 'bbox': '<Bounding box for map extent as minx,miny,maxx,maxy>', 'crs': '<CRS for map extent>', 'feature_count': <Max feature count>, 'with_geometry': <Whether to return geometries in response (default=1)>, 'with_maptip': <Whether to return maptip in response (default=1)>, 'FI_POINT_TOLERANCE': <Tolerance for picking points, in pixels (default=16)>, 'FI_LINE_TOLERANCE': <Tolerance for picking lines, in pixels (default=8)>, 'FI_POLYGON_TOLERANCE': <Tolerance for picking polygons, in pixels (default=4)>, 'resolution': <Resolution in map units per pixel> } -
identity(str): User name or Identity dict
Return info result as a dict:
{
'features': [
{
'id': <feature ID>, # optional
'attributes': [
{
'name': '<attribute name>',
'value': <attribute value>
}
],
'bbox': [<minx>, <miny>, <maxx>, <maxy>], # optional
'geometry': '<WKT geometry>' # optional
}
]
}
See ./info_modules/custom/example/ for a sample implementation of a custom layer info module.
The custom info module can then be referenced in the info_template by its name (= directory name) in the service config.
Run locally¶
Install dependencies and run:
export CONFIG_PATH=<CONFIG_PATH>
uv run src/server.py
To use configs from a qwc-docker setup, set CONFIG_PATH=<...>/qwc-docker/volumes/config.
Set FLASK_DEBUG=1 for additional debug output.
Set FLASK_RUN_PORT=<port> to change the default port (default: 5000).
API documentation:
http://localhost:$FLASK_RUN_PORT/api/
Docker usage¶
The Docker image is published on Dockerhub.
See sample docker-compose.yml of qwc-docker.