Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[server] Allow better control of the response flow chain from server filters. #45158

Merged
merged 1 commit into from
Nov 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 58 additions & 3 deletions python/server/auto_generated/qgsserverfilter.sip.in
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this specific to FCGI? Maybe better remove the mention to it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it's not specific to FCGI. Removed.

*
* \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
Loading