Skip to content

Commit

Permalink
Add OGC API Features support
Browse files Browse the repository at this point in the history
  • Loading branch information
llienher committed Nov 14, 2024
1 parent 830fadf commit a49e452
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 1 deletion.
17 changes: 16 additions & 1 deletion geoportal/c2cgeoportal_geoportal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ def handle(event: InvalidateCacheEvent) -> None:
pregenerator=C2CPregenerator(role=True),
request_method="POST",
)
# The tow next views are used to serve the application on the URL /mapserv_proxy/<ogc server name>
# The two next views are used to serve the application on the URL /mapserv_proxy/<ogc server name>
# instead of /mapserv_proxy?ogcserver=<ogc server name>, required for QGIS server landing page
config.add_route(
"mapserverproxy_get_path",
Expand All @@ -677,6 +677,21 @@ def handle(event: InvalidateCacheEvent) -> None:
pregenerator=C2CPregenerator(role=True),
request_method="POST",
)
# OGC Api routes
config.add_route(
"mapserverproxy_ogcapi_mapserver",
"/mapserv_proxy/{ogcserver}/ogcapi/*path",
mapserverproxy=True,
pregenerator=C2CPregenerator(role=True),
request_method="GET",
)
config.add_route(
"mapserverproxy_ogcapi_qgisserver",
"/mapserv_proxy/{ogcserver}/wfs3/*path",
mapserverproxy=True,
pregenerator=C2CPregenerator(role=True),
request_method="GET",
)
add_cors_route(config, "/mapserv_proxy", "mapserver")

# Add route to the tinyows proxy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ services:
environment:
- PGOPTIONS
- MAPSERVER_CONFIG_FILE=/etc/mapserver/mapserver.conf
- MAPSERVER_BASE_PATH=/mapserv_proxy/mapserver
- OGCAPI_HTML_TEMPLATE_DIRECTORY=/usr/local/share/mapserver/ogcapi/templates/html-bootstrap4/
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- AWS_DEFAULT_REGION
Expand Down
82 changes: 82 additions & 0 deletions geoportal/c2cgeoportal_geoportal/views/mapserverproxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@


import logging
import urllib.parse

from typing import Any

from pyramid.httpexceptions import HTTPForbidden, HTTPFound, HTTPInternalServerError, HTTPUnauthorized
Expand Down Expand Up @@ -165,6 +167,86 @@ def proxy(self) -> Response:

return response


@view_config(route_name="mapserverproxy_ogcapi_mapserver") # type: ignore
def proxy_ogcapi_mapserver(self) -> Response:
return self.proxy_ogcapi('ogcapi')

@view_config(route_name="mapserverproxy_ogcapi_qgisserver") # type: ignore
def proxy_ogcapi_qgisserver(self) -> Response:
return self.proxy_ogcapi('wfs3')

def proxy_ogcapi(self, subpath) -> Response:
if self.user is None and "authentication_required" in self.request.params:
_LOG.debug("proxy() detected authentication_required")
if self.request.registry.settings.get("basicauth", "False").lower() == "true":
raise HTTPUnauthorized(
headers={"WWW-Authenticate": 'Basic realm="Access to restricted layers"'}
)
raise HTTPForbidden("Basic auth is not enabled")

# We have a user logged in. We need to set group_id and possible layer_name in the params. We set
# layer_name when either QUERY_PARAMS or LAYERS is set in the WMS params, i.e. for GetMap and
# GetFeatureInfo requests. For GetLegendGraphic requests we do not send layer_name, but MapServer
# should not use the DATA string for GetLegendGraphic.

if self.ogc_server.auth == main.OGCSERVER_AUTH_STANDARD:
self.params["role_ids"] = ",".join([str(e) for e in get_roles_id(self.request)])

# In some application we want to display the features owned by a user than we need his id.
self.params["user_id"] = self.user.id if self.user is not None else "-1"

# Do not allows direct variable substitution
for k in list(self.params.keys()):
if len(k) > 1 and k[:2].capitalize() == "S_":
_LOG.warning("Direct substitution not allowed (%s=%s).", k, self.params[k])
del self.params[k]

if (
self.ogc_server.auth == main.OGCSERVER_AUTH_STANDARD
and self.ogc_server.type == main.OGCSERVER_TYPE_MAPSERVER
):
# Add functionalities params
self.params.update(get_mapserver_substitution_params(self.request))

# Get method
method = self.request.method

# we want the browser to cache GetLegendGraphic and
# DescribeFeatureType requests
use_cache = False

errors: set[str] = set()

_url = self._get_wfs_url(errors)
_url.path = '/'.join([_url.path.rstrip('/'), subpath, *self.request.matchdict['path']])
_LOG.warning("URL: %s", _url)
_LOG.warning(self.request.matchdict)

if _url is None:
_LOG.error("Error getting the URL:\n%s", "\n".join(errors))
raise HTTPInternalServerError()

cache_control = Cache.PRIVATE_NO

headers = self.get_headers()
# Add headers for Geoserver
if self.ogc_server.auth == main.OGCSERVER_AUTH_GEOSERVER and self.user is not None:
headers["sec-username"] = self.user.username
headers["sec-roles"] = ";".join(get_roles_name(self.request))

response = self._proxy_callback(
cache_control,
url=_url,
params=self.params,
cache=use_cache,
headers=headers,
body=self.request.body,
)

return response


def _proxy_callback(
self, cache_control: Cache, url: Url, params: dict[str, str], **kwargs: Any
) -> Response:
Expand Down

0 comments on commit a49e452

Please sign in to comment.