From a9f2acc57ebf85fd1e894ea78cac0512f141f057 Mon Sep 17 00:00:00 2001 From: elpaso Date: Sat, 5 Sep 2015 23:20:30 +0200 Subject: [PATCH] [SERVER] QgsRequestHandler now returns a QPair Much simpler GUI with a single method for all cases. handleRequest now returns both headers and body in a QPair. Python binding returns a tuple of QByteArray. --- python/server/qgsserver.sip | 55 ++++++++++++++++++++++------ src/server/qgshttprequesthandler.cpp | 17 ++------- src/server/qgshttprequesthandler.h | 6 +-- src/server/qgsrequesthandler.h | 7 +--- src/server/qgsserver.cpp | 40 ++------------------ src/server/qgsserver.h | 27 ++------------ tests/src/python/test_qgsserver.py | 19 +++++----- 7 files changed, 67 insertions(+), 104 deletions(-) diff --git a/python/server/qgsserver.sip b/python/server/qgsserver.sip index 4bb69350dba..fdeb46f7c5c 100644 --- a/python/server/qgsserver.sip +++ b/python/server/qgsserver.sip @@ -17,6 +17,48 @@ ***************************************************************************/ +%MappedType QPair +{ +%TypeHeaderCode +#include +#include +%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 + // Check the type if that is all that is required. + if (sipIsErr == NULL) + return (PyTuple_Size(sipPy) == 2); + + QPair *qp = new QPair; + + qp->first = SIPLong_AsLong(PyTuple_GET_ITEM(sipPy, 0)); + qp->second = SIPLong_AsLong(PyTuple_GET_ITEM(sipPy, 1)); + + *sipCppPtr = qp; + + return sipGetState(sipTransferObj); +%End +}; class QgsServer { @@ -31,21 +73,12 @@ 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 handleRequest( const QString queryString = QString( ) ); %If (HAVE_SERVER_PYTHON_PLUGINS) QgsServerInterface* serverInterface( ); - // Needs %MethodCode - //QMultiMap 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& ); diff --git a/src/server/qgshttprequesthandler.cpp b/src/server/qgshttprequesthandler.cpp index 95358fba81b..3331f22b150 100644 --- a/src/server/qgshttprequesthandler.cpp +++ b/src/server/qgshttprequesthandler.cpp @@ -218,21 +218,10 @@ void QgsHttpRequestHandler::sendResponse() clearBody(); } -QByteArray QgsHttpRequestHandler::getResponse( const bool returnHeaders, - const bool returnBody ) +QPair QgsHttpRequestHandler::getResponse() { - if ( ! returnHeaders ) - { - return mResponseBody; - } - else if ( ! returnBody ) - { - return mResponseHeader; - } - else - { - return mResponseHeader.append( mResponseBody ); - } + QPair response( mResponseHeader, mResponseBody ); + return response; } QString QgsHttpRequestHandler::formatToMimeType( const QString& format ) const diff --git a/src/server/qgshttprequesthandler.h b/src/server/qgshttprequesthandler.h index 1442b5edff0..c4fdb0a814d 100644 --- a/src/server/qgshttprequesthandler.h +++ b/src/server/qgshttprequesthandler.h @@ -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 getResponse( ) override; protected: virtual void sendHeaders( ) override; diff --git a/src/server/qgsrequesthandler.h b/src/server/qgsrequesthandler.h index 0b2799f131b..a1e03bd750f 100644 --- a/src/server/qgsrequesthandler.h +++ b/src/server/qgsrequesthandler.h @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef HAVE_SERVER_PYTHON_PLUGINS #include "qgsserverfilter.h" @@ -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 getResponse( ) = 0; protected: virtual void sendHeaders( ) = 0; diff --git a/src/server/qgsserver.cpp b/src/server/qgsserver.cpp index 27508b76d42..cf0d4a6d091 100644 --- a/src/server/qgsserver.cpp +++ b/src/server/qgsserver.cpp @@ -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 body and headers */ -QByteArray QgsServer::handleRequest( const QString queryString , - bool returnHeaders, - bool returnBody ) +QPair QgsServer::handleRequest( const QString queryString /*= QString( )*/ ) { - // Run init if handleRequest was called without previously initialising // the server if ( ! mInitialised ) @@ -603,6 +570,7 @@ QByteArray QgsServer::handleRequest( const QString queryString , } // TODO: if HAVE_SERVER_PYTHON // Returns the response bytestream - return theRequestHandler->getResponse( returnHeaders , returnBody ); + return theRequestHandler->getResponse( ); + } diff --git a/src/server/qgsserver.h b/src/server/qgsserver.h index 43604693ece..1012ea7bb85 100644 --- a/src/server/qgsserver.h +++ b/src/server/qgsserver.h @@ -61,36 +61,15 @@ 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 handleRequest( const QString queryString = QString( ) ); /** Returns a pointer to the server interface */ #ifdef HAVE_SERVER_PYTHON_PLUGINS diff --git a/tests/src/python/test_qgsserver.py b/tests/src/python/test_qgsserver.py index f989a520890..36af946c9a3 100644 --- a/tests/src/python/test_qgsserver.py +++ b/tests/src/python/test_qgsserver.py @@ -53,17 +53,15 @@ class TestQgsServer(unittest.TestCase): """Using an empty query string (returns an XML exception) we are going to test if headers and body are returned correctly""" # Test as a whole - response = str(self.server.handleRequest()) + header, body = [str(_v) for _v in self.server.handleRequest()] + response = header + body expected = 'Content-Length: 206\nContent-Type: text/xml; charset=utf-8\n\n\n Service unknown or unsupported\n\n' self.assertEqual(response, expected) - # Test header - response = str(self.server.handleRequestGetHeaders()) expected = 'Content-Length: 206\nContent-Type: text/xml; charset=utf-8\n\n' - self.assertEqual(response, expected) + self.assertEqual(header, expected) # Test body - response = str(self.server.handleRequestGetBody()) expected = '\n Service unknown or unsupported\n\n' - self.assertEqual(response, expected) + self.assertEqual(body, expected) def test_pluginfilters(self): """Test python plugins filters""" @@ -122,7 +120,8 @@ class TestQgsServer(unittest.TestCase): self.assertTrue(filter2 in serverIface.filters()[100]) self.assertEqual(filter1, serverIface.filters()[101][0]) self.assertEqual(filter2, serverIface.filters()[200][0]) - response = str(self.server.handleRequest('service=simple')) + header, body = [str(_v) for _v in self.server.handleRequest('service=simple')] + response = header + body expected = 'Content-type: text/plain\n\nHello from SimpleServer!Hello from Filter1!Hello from Filter2!' self.assertEqual(response, expected) @@ -133,7 +132,8 @@ class TestQgsServer(unittest.TestCase): self.assertTrue(filter2 in serverIface.filters()[100]) self.assertEqual(filter1, serverIface.filters()[101][0]) self.assertEqual(filter2, serverIface.filters()[200][0]) - response = str(self.server.handleRequest('service=simple')) + header, body = [str(_v) for _v in self.server.handleRequest('service=simple')] + response = header + body expected = 'Content-type: text/plain\n\nHello from SimpleServer!Hello from Filter1!Hello from Filter2!' self.assertEqual(response, expected) @@ -143,7 +143,8 @@ class TestQgsServer(unittest.TestCase): assert os.path.exists(project), "Project file not found: " + project query_string = 'MAP=%s&SERVICE=WMS&VERSION=1.3&REQUEST=%s' % (urllib.quote(project), request) - response = str(self.server.handleRequest(query_string)) + header, body = [str(_v) for _v in self.server.handleRequest(query_string)] + response = header + body f = open(self.testdata_path + request.lower() + '.txt') expected = f.read() f.close()