Skip to content

Commit

Permalink
Merge pull request #2296 from elpaso/qgsserver-return-pair
Browse files Browse the repository at this point in the history
QgsServer handleRequest now returns QPair of QByteArray with headers and body
  • Loading branch information
elpaso committed Sep 7, 2015
2 parents 5ae2881 + f56054f commit 3043f7f
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 108 deletions.
150 changes: 139 additions & 11 deletions python/server/qgsserver.sip
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,140 @@
***************************************************************************/


%MappedType QPair<QByteArray, QByteArray>
{
%TypeHeaderCode
#include <QPair>
#include <QByteArray>
%End


%TypeCode
// Convenience function for converting a QByteArray to a Python str object. (from QtCore/qbytearray.sip)
static PyObject *QByteArrayToPyStr(QByteArray *ba)
{
char *data = ba->data();

if (data)
// QByteArrays may have embedded '\0's so set the size explicitly.
return SIPBytes_FromStringAndSize(data, ba->size());
return SIPBytes_FromString("");
}

%End


%ConvertFromTypeCode
// Create the tuple.
return Py_BuildValue((char *)"OO", QByteArrayToPyStr( &sipCpp->first ), QByteArrayToPyStr( &sipCpp->second ) );
%End

%ConvertToTypeCode

// See if we are just being asked to check the type of the Python
// object.
if (!sipIsErr)
{
// Checking whether or not None has been passed instead of a list
// has already been done.
if (!PyTuple_Check(sipPy) || PyTuple_Size(sipPy) != 2)
return 0;

// Check the type of each element. We specify SIP_NOT_NONE to
// disallow None because it is a list of QPoint, not of a pointer
// to a QPoint, so None isn't appropriate.
for (int i = 0; i < PyTuple_Size(sipPy); ++i)
if (!sipCanConvertToType(PyTuple_GET_ITEM(sipPy, i),
sipType_QByteArray, SIP_NOT_NONE))
return 0;

// The type is valid.
return 1;
}

// Create the instance on the heap.
QPair<QByteArray, QByteArray> *qp = new QPair<QByteArray, QByteArray>;

QByteArray *qba1;
int state;

// Get the address of the element's C++ instance. Note that, in
// this case, we don't apply any ownership changes to the list
// elements, only to the list itself.
qba1 = reinterpret_cast<QByteArray *>(sipConvertToType(
PyTuple_GET_ITEM(sipPy, 0),
sipType_QByteArray, 0,
SIP_NOT_NONE,
&state, sipIsErr));

// Deal with any errors.
if (*sipIsErr)
{
sipReleaseType(qba1, sipType_QByteArray, state);

// Tidy up.
delete qp;

// There is no temporary instance.
return 0;
}

qp->first = *qba1;

// A copy of the QByteArray was assigned to the pair so we no longer
// need it. It may be a temporary instance that should be
// destroyed, or a wrapped instance that should not be destroyed.
// sipReleaseType() will do the right thing.
sipReleaseType(qba1, sipType_QByteArray, state);

/////////////////////////////////////////////
// Second item

QByteArray *qba2;

// Get the address of the element's C++ instance. Note that, in
// this case, we don't apply any ownership changes to the list
// elements, only to the list itself.
qba2 = reinterpret_cast<QByteArray *>(sipConvertToType(
PyTuple_GET_ITEM(sipPy, 1),
sipType_QByteArray, 0,
SIP_NOT_NONE,
&state, sipIsErr));

// Deal with any errors.
if (*sipIsErr)
{
sipReleaseType(qba1, sipType_QByteArray, state);
sipReleaseType(qba2, sipType_QByteArray, state);

// Tidy up.
delete qp;

// There is no temporary instance.
return 0;
}

qp->second = *qba2;


// A copy of the QByteArray was assigned to the pair so we no longer
// need it. It may be a temporary instance that should be
// destroyed, or a wrapped instance that should not be destroyed.
// sipReleaseType() will do the right thing.
sipReleaseType(qba2, sipType_QByteArray, state);


// Return the instance.
*sipCppPtr = qp;

// The instance should be regarded as temporary (and be destroyed as
// soon as it has been used) unless it has been transferred from
// Python. sipGetState() is a convenience function that implements
// this common transfer behaviour.
return sipGetState(sipTransferObj);

%End
};

class QgsServer
{
Expand All @@ -31,21 +165,15 @@ class QgsServer
//void init( int argc, char* argv[] );
// init for python bindings:
void init( );
QByteArray handleRequest( const QString queryString = QString( ) );
// TODO: if HAVE_SERVER_PYTHON
QByteArray handleRequest( const QString queryString,
const bool returnHeaders,
const bool returnBody );
QByteArray handleRequestGetBody( const QString queryString = QString( ) );
QByteArray handleRequestGetHeaders( const QString queryString = QString( ) );
//QgsServerContext& serverContext ( ) /KeepReference/;
QPair<QByteArray, QByteArray> handleRequest( const QString queryString = QString( ) );
/* The following code was used to test type conversion in python bindings
QPair<QByteArray, QByteArray> testQPair( QPair<QByteArray, QByteArray> pair );
*/
%If (HAVE_SERVER_PYTHON_PLUGINS)
QgsServerInterface* serverInterface( );
// Needs %MethodCode
//QMultiMap<int, QgsServerFilter*> pluginFilters( );
%End

// The following is needed because otherwise SIP fails trying to create copy
// The following is needed because otherwise SIP fails trying to create copy
// ctor
private:
QgsServer( const QgsServer& );
Expand Down
18 changes: 4 additions & 14 deletions src/server/qgshttprequesthandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,21 +218,11 @@ void QgsHttpRequestHandler::sendResponse()
clearBody();
}

QByteArray QgsHttpRequestHandler::getResponse( const bool returnHeaders,
const bool returnBody )
QPair<QByteArray, QByteArray> QgsHttpRequestHandler::getResponse()
{
if ( ! returnHeaders )
{
return mResponseBody;
}
else if ( ! returnBody )
{
return mResponseHeader;
}
else
{
return mResponseHeader.append( mResponseBody );
}
// TODO: check that this is not an evil bug!
QPair<QByteArray, QByteArray> response( mResponseHeader, mResponseBody );
return response;
}

QString QgsHttpRequestHandler::formatToMimeType( const QString& format ) const
Expand Down
6 changes: 1 addition & 5 deletions src/server/qgshttprequesthandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,8 @@ class QgsHttpRequestHandler: public QgsRequestHandler
#ifdef HAVE_SERVER_PYTHON_PLUGINS
virtual void setPluginFilters( QgsServerFiltersMap pluginFilters ) override;
#endif
// TODO: if HAVE_SERVER_PYTHON
QByteArray getResponseHeader( ) override { return mResponseHeader; }
QByteArray getResponseBody( ) override { return mResponseBody; }
/** Return the response if capture output is activated */
QByteArray getResponse( const bool returnHeaders = TRUE,
const bool returnBody = TRUE ) override;
QPair<QByteArray, QByteArray> getResponse( ) override;

protected:
virtual void sendHeaders( ) override;
Expand Down
7 changes: 2 additions & 5 deletions src/server/qgsrequesthandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <QMap>
#include <QString>
#include <QStringList>
#include <QPair>

#ifdef HAVE_SERVER_PYTHON_PLUGINS
#include "qgsserverfilter.h"
Expand Down Expand Up @@ -113,11 +114,7 @@ class QgsRequestHandler
*/
virtual void setPluginFilters( QgsServerFiltersMap pluginFilters ) = 0;
#endif
// TODO: if HAVE_SERVER_PYTHON
virtual QByteArray getResponseHeader( ) = 0;
virtual QByteArray getResponseBody( ) = 0;
virtual QByteArray getResponse( const bool returnHeaders = TRUE,
const bool returnBody = TRUE ) = 0;
virtual QPair<QByteArray, QByteArray> getResponse( ) = 0;

protected:
virtual void sendHeaders( ) = 0;
Expand Down
50 changes: 11 additions & 39 deletions src/server/qgsserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,47 +403,14 @@ bool QgsServer::init( int & argc, char ** argv )
}


/**
* Handles the request
*/
QByteArray QgsServer::handleRequest( const QString queryString /*= QString( )*/ )
{
return handleRequest( queryString, TRUE, TRUE );
}

/**
* @brief Handles the request, returning only the body
* @param queryString
* @return response body if mCaptureOutput is set, empty QByteArray if not
*/
QByteArray QgsServer::handleRequestGetBody( const QString queryString /*= QString( )*/ )
{
return handleRequest( queryString, FALSE, TRUE );
}

/**
* @brief Handles the request, returning only the headers
* @param queryString
* @return response headers if mCaptureOutput is set, empty QByteArray if not
*/
QByteArray QgsServer::handleRequestGetHeaders( const QString queryString /*= QString( )*/ )
{
return handleRequest( queryString, TRUE, FALSE );
}

/**
* @brief Handles the request
* @param queryString
* @param returnBody
* @param returnHeaders
* @return response body and headers if mCaptureOutput is set and the
* flags are set, empty QByteArray if not
* @return response headers and body
*/
QByteArray QgsServer::handleRequest( const QString queryString ,
bool returnHeaders,
bool returnBody )
QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString queryString /*= QString( )*/ )
{

// Run init if handleRequest was called without previously initialising
// the server
if ( ! mInitialised )
Expand Down Expand Up @@ -501,7 +468,6 @@ QByteArray QgsServer::handleRequest( const QString queryString ,
//Pass the filters to the requestHandler, this is needed for the following reasons:
// 1. allow core services to access plugin filters and implement thir own plugin hooks
// 2. allow requestHandler to call sendResponse plugin hook

theRequestHandler->setPluginFilters( mServerInterface->filters() );
#endif

Expand Down Expand Up @@ -601,8 +567,14 @@ QByteArray QgsServer::handleRequest( const QString queryString ,
{
QgsMessageLog::logMessage( "Request finished in " + QString::number( time.elapsed() ) + " ms", "Server", QgsMessageLog::INFO );
}
// TODO: if HAVE_SERVER_PYTHON
// Returns the response bytestream
return theRequestHandler->getResponse( returnHeaders , returnBody );
// Returns the header and response bytestreams (to be used in Python bindings)
return theRequestHandler->getResponse( );
}

/* The following code was used to test type conversion in python bindings
QPair<QByteArray, QByteArray> QgsServer::testQPair(QPair<QByteArray, QByteArray> pair)
{
return pair;
}
*/

30 changes: 6 additions & 24 deletions src/server/qgsserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,36 +61,18 @@ class SERVER_EXPORT QgsServer
/** Handles the request. The output is normally printed trough FCGI printf
* by the request handler or, in case the server has been invoked from python
* bindings, a flag is set that captures all the output headers and body, instead
* of printing it returns the output as a QByteArray.
* When calling handleRequest() from python bindings an additional argument
* specify if we only want the headers or the body back, this is mainly useful
* for testing purposes.
* of printing it returns the output as a QPair of QByteArray.
* The query string is normally read from environment
* but can be also passed in args and in this case overrides the environment
* variable
*
* @param queryString optional QString containing the query string
* @return the response QByteArray if called from python bindings, empty otherwise
* @return the response headers and body QPair of QByteArray if called from python bindings, empty otherwise
*/
QByteArray handleRequest( const QString queryString = QString( ) );
QByteArray handleRequest( const QString queryString,
const bool returnHeaders,
const bool returnBody );
/**
* Handles the request and returns only the body
*
* @param queryString optional QString containing the query string
* @return the response body QByteArray if called from python bindings, empty otherwise
*/
QByteArray handleRequestGetBody( const QString queryString = QString( ) );

/**
* Handles the request and returns only the headers
*
* @param queryString optional QString containing the query string
* @return the response headers QByteArray if called from python bindings, empty otherwise
*/
QByteArray handleRequestGetHeaders( const QString queryString = QString( ) );
QPair<QByteArray, QByteArray> handleRequest( const QString queryString = QString( ) );
/* The following code was used to test type conversion in python bindings
QPair<QByteArray, QByteArray> testQPair( QPair<QByteArray, QByteArray> pair );
*/

/** Returns a pointer to the server interface */
#ifdef HAVE_SERVER_PYTHON_PLUGINS
Expand Down
Loading

0 comments on commit 3043f7f

Please sign in to comment.