Skip to content

Commit

Permalink
Server OGC API handler: make it more robust in path matching
Browse files Browse the repository at this point in the history
  • Loading branch information
elpaso authored and nyalldawson committed Nov 1, 2021
1 parent 8bc90ce commit 9990ad2
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 8 deletions.
8 changes: 8 additions & 0 deletions python/server/auto_generated/qgsserverogcapihandler.sip.in
Expand Up @@ -259,6 +259,14 @@ Set the content types to ``contentTypes``
%End


QString handlerPath( const QgsServerApiContext &context ) const;
%Docstring
Returns the handler component of the URL path, i.e. the part of the path that comes
after the API path.

.. versionadded:: 3.22
%End

};

/************************************************************************
Expand Down
18 changes: 16 additions & 2 deletions src/server/qgsserverogcapihandler.cpp
Expand Up @@ -46,7 +46,7 @@ QVariantMap QgsServerOgcApiHandler::values( const QgsServerApiContext &context )
// value() calls the validators and throws an exception if validation fails
result[p.name()] = p.value( context );
}
const auto sanitizedPath { QgsServerOgcApi::sanitizeUrl( context.request()->url() ).path() };
const auto sanitizedPath { QgsServerOgcApi::sanitizeUrl( handlerPath( context ) ).path() };
const auto match { path().match( sanitizedPath ) };
if ( match.hasMatch() )
{
Expand Down Expand Up @@ -139,7 +139,7 @@ std::string QgsServerOgcApiHandler::href( const QgsServerApiContext &context, co
{
QUrl url { context.request()->url() };
QString urlBasePath { context.matchedPath() };
const auto match { path().match( url.path() ) };
const auto match { path().match( handlerPath( context ) ) };
if ( match.captured().count() > 0 )
{
url.setPath( urlBasePath + match.captured( 0 ) );
Expand Down Expand Up @@ -598,3 +598,17 @@ void QgsServerOgcApiHandler::setContentTypes( const QList<QgsServerOgcApi::Conte
{
mContentTypes = contentTypes;
}

QString QgsServerOgcApiHandler::handlerPath( const QgsServerApiContext &context ) const
{
const QUrl url { context.request()->url() };
const QString urlBasePath { context.matchedPath() };
if ( ! urlBasePath.isEmpty() )
{
return url.path().mid( urlBasePath.length() );
}
else
{
return url.path();
}
}
8 changes: 8 additions & 0 deletions src/server/qgsserverogcapihandler.h
Expand Up @@ -387,6 +387,14 @@ class SERVER_EXPORT QgsServerOgcApiHandler
*/
void setContentTypes( const QList<QgsServerOgcApi::ContentType> &contentTypes ) SIP_SKIP;

/**
* Returns the handler component of the URL path, i.e. the part of the path that comes
* after the API path.
*
* \since QGIS 3.22
*/
QString handlerPath( const QgsServerApiContext &context ) const;

private:

//! List of content types this handler can serve, first is the default
Expand Down
11 changes: 5 additions & 6 deletions tests/src/python/test_qgsserver_api.py
Expand Up @@ -1751,7 +1751,7 @@ def templatePath(self, context):
class Handler4(QgsServerOgcApiHandler):

def path(self):
return QtCore.QRegularExpression("/tms/(?P<tilemapid>[^/]+)")
return QtCore.QRegularExpression("/(?P<tilemapid>[^/]+)")

def operationId(self):
return "handler4"
Expand Down Expand Up @@ -2031,16 +2031,15 @@ def testOgcApiHandlerException(self):

def test_path_capture(self):
"""Test issue GH #45439"""
project = QgsProject()

api = QgsServerOgcApi(self.server.serverInterface(),
'/services/api4', 'apifour', 'a fourth api', '1.2')
'/api4', 'apifour', 'a fourth api', '1.2')

h4 = Handler4()
api.registerHandler(h4)

request = QgsBufferServerRequest(
'http://localhost:19876/services/api4/tms/france_parts.json?MAP=france_parts')
'http://localhost:19876/api4/france_parts.json?MAP=france_parts')
response = QgsBufferServerResponse()

server = QgsServer()
Expand All @@ -2051,8 +2050,8 @@ def test_path_capture(self):

self.assertEqual(h4.params, {'tilemapid': 'france_parts.json'})

ctx = QgsServerApiContext(api.rootPath(), request, response, project, iface)
self.assertEqual(h4.href(ctx), 'http://localhost:19876/services/api4/tms/france_parts?MAP=france_parts')
ctx = QgsServerApiContext(api.rootPath(), request, response, None, iface)
self.assertEqual(h4.href(ctx), 'http://localhost:19876/api4/france_parts?MAP=france_parts')


if __name__ == '__main__':
Expand Down

0 comments on commit 9990ad2

Please sign in to comment.