Skip to content

Commit

Permalink
Merge pull request #45158 from dmarteau/fix-server-filter-streaming
Browse files Browse the repository at this point in the history
[server] Allow better control of the response flow chain from server filters.
  • Loading branch information
elpaso committed Nov 3, 2021
2 parents 9134854 + bbb8e8f commit dc3e9eb
Show file tree
Hide file tree
Showing 5 changed files with 267 additions and 17 deletions.
61 changes: 58 additions & 3 deletions python/server/auto_generated/qgsserverfilter.sip.in
Expand Up @@ -44,29 +44,84 @@ and must be passed to QgsServerFilter instances.
Returns the :py:class:`QgsServerInterface` instance
%End

virtual void requestReady();
virtual void requestReady() /Deprecated/;
%Docstring
Method called when the :py:class:`QgsRequestHandler` is ready and populated with
parameters, just before entering the main switch for core services.

This method is considered as deprecated and :py:func:`onRequestReady` should
be used instead.

.. deprecated::
Will be removed in QGIS 4.0
%End

virtual void responseComplete();
virtual void responseComplete() /Deprecated/;
%Docstring
Method called when the :py:class:`QgsRequestHandler` processing has done and
the response is ready, just after the main switch for core services
and before final sending response.

This method is considered as deprecated and :py:func:`onResponseComplete` should
be used instead.

.. deprecated::
Will be removed in QGIS 4.0
%End

virtual void sendResponse() /Deprecated/;
%Docstring
Method called when the :py:class:`QgsRequestHandler` sends its data to FCGI stdout.
This normally occurs at the end of core services processing just after
the :py:func:`~QgsServerFilter.responseComplete` plugin hook. For streaming services (like WFS on
getFeature requests, :py:func:`~QgsServerFilter.sendResponse` might have been called several times
before the response is complete: in this particular case, :py:func:`~QgsServerFilter.sendResponse`
is called once for each feature before hitting :py:func:`~QgsServerFilter.responseComplete`

This method is considered as deprecated and :py:func:`onSendResponse` should
be used instead.

.. deprecated::
Will be removed in QGIS 4.0
%End

virtual bool onRequestReady();
%Docstring
Method called when the :py:class:`QgsRequestHandler` is ready and populated with
parameters, just before entering the main switch for core services.

:return: true if the call must propagate to the subsequent filters, false otherwise

.. versionadded:: 3.24
%End

virtual bool onResponseComplete();
%Docstring
Method called when the :py:class:`QgsRequestHandler` processing has done and
the response is ready, just after the main switch for core services
and before final sending response to FCGI stdout.

:return: true if the call must propagate to the subsequent filters, false otherwise

.. versionadded:: 3.24
%End

virtual void sendResponse();
virtual bool onSendResponse();
%Docstring
Method called when the :py:class:`QgsRequestHandler` sends its data to FCGI stdout.
This normally occurs at the end of core services processing just after
the :py:func:`~QgsServerFilter.responseComplete` plugin hook. For streaming services (like WFS on
getFeature requests, :py:func:`~QgsServerFilter.sendResponse` might have been called several times
before the response is complete: in this particular case, :py:func:`~QgsServerFilter.sendResponse`
is called once for each feature before hitting :py:func:`~QgsServerFilter.responseComplete`

:return: true if the call must propagate to the subsequent filters, false otherwise

.. versionadded:: 3.22
%End



};

typedef QMultiMap<int, QgsServerFilter *> QgsServerFiltersMap;
Expand Down
25 changes: 19 additions & 6 deletions src/server/qgsfilterresponsedecorator.cpp
Expand Up @@ -19,7 +19,6 @@

#include "qgsconfig.h"
#include "qgsfilterresponsedecorator.h"
#include "qgsserverexception.h"

QgsFilterResponseDecorator::QgsFilterResponseDecorator( QgsServerFiltersMap filters, QgsServerResponse &response )
: mFilters( filters )
Expand All @@ -33,32 +32,46 @@ void QgsFilterResponseDecorator::start()
QgsServerFiltersMap::const_iterator filtersIterator;
for ( filtersIterator = mFilters.constBegin(); filtersIterator != mFilters.constEnd(); ++filtersIterator )
{
filtersIterator.value()->requestReady();
if ( ! filtersIterator.value()->onRequestReady() )
{
// stop propagation
return;
}
}
#endif
}

void QgsFilterResponseDecorator::finish()
{

#ifdef HAVE_SERVER_PYTHON_PLUGINS
QgsServerFiltersMap::const_iterator filtersIterator;
for ( filtersIterator = mFilters.constBegin(); filtersIterator != mFilters.constEnd(); ++filtersIterator )
{
filtersIterator.value()->responseComplete();
if ( ! filtersIterator.value()->onResponseComplete() )
{
// stop propagation, 'finish' must be called on the wrapped
// response
break;
}
}
#endif
// Will call 'flush'
// Will call internal 'flush'
mResponse.finish();
}


void QgsFilterResponseDecorator::flush()
{
#ifdef HAVE_SERVER_PYTHON_PLUGINS
QgsServerFiltersMap::const_iterator filtersIterator;

for ( filtersIterator = mFilters.constBegin(); filtersIterator != mFilters.constEnd(); ++filtersIterator )
{
filtersIterator.value()->sendResponse();
if ( ! filtersIterator.value()->onSendResponse() )
{
// Stop propagation
return;
}
}
#endif
mResponse.flush();
Expand Down
28 changes: 27 additions & 1 deletion src/server/qgsserverfilter.cpp
Expand Up @@ -19,6 +19,7 @@

#include "qgsserverfilter.h"
#include "qgslogger.h"
#include "qgis.h"

/**
* QgsServerFilter
Expand All @@ -42,8 +43,33 @@ void QgsServerFilter::responseComplete()
QgsDebugMsg( QStringLiteral( "QgsServerFilter plugin default responseComplete called" ) );
}


void QgsServerFilter::sendResponse()
{
QgsDebugMsg( QStringLiteral( "QgsServerFilter plugin default sendResponse called" ) );
}

bool QgsServerFilter::onRequestReady()
{
Q_NOWARN_DEPRECATED_PUSH
requestReady();
Q_NOWARN_DEPRECATED_POP
return true;
}

bool QgsServerFilter::onResponseComplete()
{
Q_NOWARN_DEPRECATED_PUSH
responseComplete();
Q_NOWARN_DEPRECATED_POP
return true;
}

bool QgsServerFilter::onSendResponse()
{
Q_NOWARN_DEPRECATED_PUSH
sendResponse();
Q_NOWARN_DEPRECATED_POP
return true;
}


63 changes: 57 additions & 6 deletions src/server/qgsserverfilter.h
Expand Up @@ -59,16 +59,62 @@ class SERVER_EXPORT QgsServerFilter

/**
* Method called when the QgsRequestHandler is ready and populated with
* parameters, just before entering the main switch for core services.
*/
virtual void requestReady();
* parameters, just before entering the main switch for core services.
*
* This method is considered as deprecated and \see onRequestReady should
* be used instead.
*
* \deprecated Will be removed in QGIS 4.0
*/
Q_DECL_DEPRECATED virtual void requestReady() SIP_DEPRECATED;

/**
* Method called when the QgsRequestHandler processing has done and
* the response is ready, just after the main switch for core services
* and before final sending response.
*
* This method is considered as deprecated and \see onResponseComplete should
* be used instead.
*
* \deprecated Will be removed in QGIS 4.0
*/
Q_DECL_DEPRECATED virtual void responseComplete() SIP_DEPRECATED;

/**
* Method called when the QgsRequestHandler sends its data to FCGI stdout.
* This normally occurs at the end of core services processing just after
* the responseComplete() plugin hook. For streaming services (like WFS on
* getFeature requests, sendResponse() might have been called several times
* before the response is complete: in this particular case, sendResponse()
* is called once for each feature before hitting responseComplete()
*
* This method is considered as deprecated and \see onSendResponse should
* be used instead.
*
* \deprecated Will be removed in QGIS 4.0
*/
Q_DECL_DEPRECATED virtual void sendResponse() SIP_DEPRECATED;

/**
* Method called when the QgsRequestHandler is ready and populated with
* parameters, just before entering the main switch for core services.
*
* \return true if the call must propagate to the subsequent filters, false otherwise
*
* \since QGIS 3.24
*/
virtual bool onRequestReady();

/**
* Method called when the QgsRequestHandler processing has done and
* the response is ready, just after the main switch for core services
* and before final sending response to FCGI stdout.
*
* \return true if the call must propagate to the subsequent filters, false otherwise
*
* \since QGIS 3.24
*/
virtual void responseComplete();
virtual bool onResponseComplete();

/**
* Method called when the QgsRequestHandler sends its data to FCGI stdout.
Expand All @@ -77,11 +123,16 @@ class SERVER_EXPORT QgsServerFilter
* getFeature requests, sendResponse() might have been called several times
* before the response is complete: in this particular case, sendResponse()
* is called once for each feature before hitting responseComplete()
*
* \return true if the call must propagate to the subsequent filters, false otherwise
*
* \since QGIS 3.22
*/
virtual void sendResponse();
virtual bool onSendResponse();

private:


private:
QgsServerInterface *mServerInterface = nullptr;

};
Expand Down

0 comments on commit dc3e9eb

Please sign in to comment.