Skip to content

Commit 0f3d14a

Browse files
authoredOct 20, 2017
Merge pull request #5408 from rldhont/server-handlerequest-project
[Server][FEATURE] Handle request from QgsServer with a QgsProject
2 parents efb84fd + 7b455d8 commit 0f3d14a

File tree

5 files changed

+70
-11
lines changed

5 files changed

+70
-11
lines changed
 

‎python/server/qgsserver.sip

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class QgsServer
3535
.. versionadded:: 2.14
3636
%End
3737

38-
void handleRequest( QgsServerRequest &request, QgsServerResponse &response );
38+
void handleRequest( QgsServerRequest &request, QgsServerResponse &response, const QgsProject *project = 0 );
3939
%Docstring
4040
Handles the request.
4141
The query string is normally read from environment
@@ -44,6 +44,9 @@ class QgsServer
4444

4545
\param request a QgsServerRequest holding request parameters
4646
\param response a QgsServerResponse for handling response I/O)
47+
\param project a QgsProject or None, if it is None the project
48+
is created from the MAP param specified in request or from
49+
the QGIS_PROJECT_FILE setting
4750
%End
4851

4952

‎src/server/qgsserver.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,7 @@ void QgsServer::putenv( const QString &var, const QString &val )
300300
* @param queryString
301301
* @return response headers and body
302302
*/
303-
304-
void QgsServer::handleRequest( QgsServerRequest &request, QgsServerResponse &response )
303+
void QgsServer::handleRequest( QgsServerRequest &request, QgsServerResponse &response, const QgsProject *project )
305304
{
306305
QgsMessageLog::MessageLevel logLevel = QgsServerLogger::instance()->logLevel();
307306
QTime time; //used for measuring request time if loglevel < 1
@@ -346,16 +345,23 @@ void QgsServer::handleRequest( QgsServerRequest &request, QgsServerResponse &res
346345
printRequestParameters( parameterMap, logLevel );
347346

348347
//Config file path
349-
QString configFilePath = configPath( *sConfigFilePath, parameterMap );
350-
351-
// load the project if needed and not empty
352-
const QgsProject *project = mConfigCache->project( configFilePath );
353348
if ( ! project )
354349
{
355-
throw QgsServerException( QStringLiteral( "Project file error" ) );
356-
}
350+
QString configFilePath = configPath( *sConfigFilePath, parameterMap );
351+
352+
// load the project if needed and not empty
353+
project = mConfigCache->project( configFilePath );
354+
if ( ! project )
355+
{
356+
throw QgsServerException( QStringLiteral( "Project file error" ) );
357+
}
357358

358-
sServerInterface->setConfigFilePath( configFilePath );
359+
sServerInterface->setConfigFilePath( configFilePath );
360+
}
361+
else
362+
{
363+
sServerInterface->setConfigFilePath( project->fileName() );
364+
}
359365

360366
//Service parameter
361367
QString serviceString = parameterMap.value( QStringLiteral( "SERVICE" ) );

‎src/server/qgsserver.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,11 @@ class SERVER_EXPORT QgsServer
7575
*
7676
* \param request a QgsServerRequest holding request parameters
7777
* \param response a QgsServerResponse for handling response I/O)
78+
* \param project a QgsProject or nullptr, if it is nullptr the project
79+
* is created from the MAP param specified in request or from
80+
* the QGIS_PROJECT_FILE setting
7881
*/
79-
void handleRequest( QgsServerRequest &request, QgsServerResponse &response );
82+
void handleRequest( QgsServerRequest &request, QgsServerResponse &response, const QgsProject *project = nullptr );
8083

8184

8285
//! Returns a pointer to the server interface

‎tests/src/python/test_qgsserver.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,17 @@ def _execute_request(self, qs, requestMethod=QgsServerRequest.GetMethod, data=No
214214
headers.append(("%s: %s" % (k, rh[k])).encode('utf-8'))
215215
return b"\n".join(headers) + b"\n\n", bytes(response.body())
216216

217+
def _execute_request_project(self, qs, project, requestMethod=QgsServerRequest.GetMethod, data=None):
218+
request = QgsBufferServerRequest(qs, requestMethod, {}, data)
219+
response = QgsBufferServerResponse()
220+
self.server.handleRequest(request, response, project)
221+
headers = []
222+
rh = response.headers()
223+
rk = sorted(rh.keys())
224+
for k in rk:
225+
headers.append(("%s: %s" % (k, rh[k])).encode('utf-8'))
226+
return b"\n".join(headers) + b"\n\n", bytes(response.body())
227+
217228

218229
class TestQgsServerTestBase(unittest.TestCase):
219230

@@ -285,6 +296,16 @@ def test_requestHandler(self):
285296
self.assertEqual(response.headers(), {'Content-Length': '54', 'Content-Type': 'text/xml; charset=utf-8'})
286297
self.assertEqual(response.statusCode(), 500)
287298

299+
def test_requestHandlerProject(self):
300+
"""Test request handler with none project"""
301+
headers = {'header-key-1': 'header-value-1', 'header-key-2': 'header-value-2'}
302+
request = QgsBufferServerRequest('http://somesite.com/somepath', QgsServerRequest.GetMethod, headers)
303+
response = QgsBufferServerResponse()
304+
self.server.handleRequest(request, response, None)
305+
self.assertEqual(bytes(response.body()), b'<ServerException>Project file error</ServerException>\n')
306+
self.assertEqual(response.headers(), {'Content-Length': '54', 'Content-Type': 'text/xml; charset=utf-8'})
307+
self.assertEqual(response.statusCode(), 500)
308+
288309
def test_api(self):
289310
"""Using an empty query string (returns an XML exception)
290311
we are going to test if headers and body are returned correctly"""

‎tests/src/python/test_qgsserver_wms.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import osgeo.gdal # NOQA
3333

3434
from test_qgsserver import QgsServerTestBase
35+
from qgis.core import QgsProject
3536

3637
# Strip path and content length because path may vary
3738
RE_STRIP_UNCHECKABLE = b'MAP=[^"]+|Content-Length: \d+'
@@ -196,6 +197,31 @@ def test_wms_getschemaextension(self):
196197
'',
197198
'getschemaextension')
198199

200+
def wms_request_compare_project(self, request, extra=None, reference_file=None):
201+
projectPath = self.testdata_path + "test_project.qgs"
202+
assert os.path.exists(projectPath), "Project file not found: " + projectPath
203+
204+
project = QgsProject()
205+
project.read(projectPath)
206+
207+
query_string = 'https://www.qgis.org/?SERVICE=WMS&VERSION=1.3&REQUEST=%s' % (request)
208+
if extra is not None:
209+
query_string += extra
210+
header, body = self._execute_request_project(query_string, project)
211+
response = header + body
212+
reference_path = self.testdata_path + (request.lower() if not reference_file else reference_file) + '.txt'
213+
self.store_reference(reference_path, response)
214+
f = open(reference_path, 'rb')
215+
expected = f.read()
216+
f.close()
217+
response = re.sub(RE_STRIP_UNCHECKABLE, b'*****', response)
218+
expected = re.sub(RE_STRIP_UNCHECKABLE, b'*****', expected)
219+
220+
self.assertXMLEqual(response, expected, msg="request %s failed.\nQuery: %s\nExpected file: %s\nResponse:\n%s" % (query_string, request, reference_path, response.decode('utf-8')))
221+
222+
def test_wms_getcapabilities_project(self):
223+
self.wms_request_compare_project('GetCapabilities')
224+
199225
def wms_inspire_request_compare(self, request):
200226
"""WMS INSPIRE tests"""
201227
project = self.testdata_path + "test_project_inspire.qgs"

0 commit comments

Comments
 (0)
Please sign in to comment.