Skip to content

Commit 072c1e5

Browse files
committed
Merge pull request #1715 from rldhont/server_wms_getcapabilities_compliance
[QGIS-Server] FIX 10489 QGIS Server getcapabilites response is not WMS c...
2 parents 0fa40a6 + a7de4da commit 072c1e5

9 files changed

+121
-42
lines changed

src/server/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ INSTALL(TARGETS
184184
INSTALL(FILES
185185
admin.sld
186186
wms_metadata.xml
187+
schemaExtension.xsd
187188
DESTINATION ${QGIS_CGIBIN_DIR}
188189
)
189190

src/server/qgshttprequesthandler.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,12 +268,18 @@ void QgsHttpRequestHandler::setGetCapabilitiesResponse( const QDomDocument& doc
268268
setHttpResponse( &ba, "text/xml" );
269269
}
270270

271-
void QgsHttpRequestHandler::setGetStyleResponse( const QDomDocument& doc )
271+
void QgsHttpRequestHandler::setXmlResponse( const QDomDocument& doc )
272272
{
273273
QByteArray ba = doc.toByteArray();
274274
setHttpResponse( &ba, "text/xml" );
275275
}
276276

277+
void QgsHttpRequestHandler::setXmlResponse( const QDomDocument& doc, const QString& mimeType )
278+
{
279+
QByteArray ba = doc.toByteArray();
280+
setHttpResponse( &ba, mimeType );
281+
}
282+
277283
void QgsHttpRequestHandler::setGetFeatureInfoResponse( const QDomDocument& infoDoc, const QString& infoFormat )
278284
{
279285
QByteArray ba;

src/server/qgshttprequesthandler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ class QgsHttpRequestHandler: public QgsRequestHandler
3939
virtual void setGetCapabilitiesResponse( const QDomDocument& doc );
4040
virtual void setGetFeatureInfoResponse( const QDomDocument& infoDoc, const QString& infoFormat );
4141
virtual void setServiceException( QgsMapServiceException ex );
42-
virtual void setGetStyleResponse( const QDomDocument& doc );
42+
virtual void setXmlResponse( const QDomDocument& doc );
43+
virtual void setXmlResponse( const QDomDocument& doc, const QString& mimeType );
4344
virtual void setGetPrintResponse( QByteArray* ba );
4445
virtual bool startGetFeatureResponse( QByteArray* ba, const QString& infoFormat );
4546
virtual void setGetFeatureResponse( QByteArray* ba );

src/server/qgsrequesthandler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ class QgsRequestHandler
5353
virtual void setGetCapabilitiesResponse( const QDomDocument& doc ) = 0;
5454
virtual void setGetFeatureInfoResponse( const QDomDocument& infoDoc, const QString& infoFormat ) = 0;
5555
virtual void setServiceException( QgsMapServiceException ex ) = 0;
56-
virtual void setGetStyleResponse( const QDomDocument& doc ) = 0;
56+
virtual void setXmlResponse( const QDomDocument& doc ) = 0;
57+
virtual void setXmlResponse( const QDomDocument& doc, const QString& mimeType ) = 0;
5758
virtual void setGetPrintResponse( QByteArray* b ) = 0;
5859
virtual bool startGetFeatureResponse( QByteArray* ba, const QString& infoFormat ) = 0;
5960
virtual void setGetFeatureResponse( QByteArray* ba ) = 0;

src/server/qgssoaprequesthandler.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ void QgsSOAPRequestHandler::setGetFeatureInfoResponse( const QDomDocument& infoD
394394
setHttpResponse( &ba, "text/xml" );
395395
}
396396

397-
void QgsSOAPRequestHandler::setGetStyleResponse( const QDomDocument& infoDoc )
397+
void QgsSOAPRequestHandler::setXmlResponse( const QDomDocument& infoDoc )
398398
{
399399
QDomDocument featureInfoResponseDoc;
400400

@@ -415,6 +415,12 @@ void QgsSOAPRequestHandler::setGetStyleResponse( const QDomDocument& infoDoc )
415415
setHttpResponse( &ba, "text/xml" );
416416
}
417417

418+
void QgsSOAPRequestHandler::setXmlResponse( const QDomDocument& infoDoc, const QString& mimeType )
419+
{
420+
Q_UNUSED( mimeType );
421+
setXmlResponse( infoDoc );
422+
}
423+
418424
void QgsSOAPRequestHandler::setGetPrintResponse( QByteArray* ba ) const
419425
{
420426
Q_UNUSED( ba );

src/server/qgssoaprequesthandler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ class QgsSOAPRequestHandler: public QgsHttpRequestHandler
3333
void setGetCapabilitiesResponse( const QDomDocument& doc );
3434
void setGetFeatureInfoResponse( const QDomDocument& infoDoc, const QString& infoFormat );
3535
void setServiceException( const QgsMapServiceException& ex );
36-
void setGetStyleResponse( const QDomDocument& doc );
36+
void setXmlResponse( const QDomDocument& doc );
37+
void setXmlResponse( const QDomDocument& doc, const QString& mimeType );
3738
void setGetPrintResponse( QByteArray* ba ) const;
3839
private:
3940
/**Parses the xml of a getMap request and fills the parameters into the map. Returns 0 in case of success*/

src/server/qgswmsserver.cpp

Lines changed: 91 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "qgsvectordataprovider.h"
3838
#include "qgsvectorlayer.h"
3939
#include "qgslogger.h"
40+
#include "qgsmessagelog.h"
4041
#include "qgsmapserviceexception.h"
4142
#include "qgssldconfigparser.h"
4243
#include "qgssymbolv2.h"
@@ -199,7 +200,20 @@ void QgsWMSServer::executeRequest()
199200
try
200201
{
201202
QDomDocument doc = getContext();
202-
mRequestHandler->setGetStyleResponse( doc );
203+
mRequestHandler->setXmlResponse( doc );
204+
}
205+
catch ( QgsMapServiceException& ex )
206+
{
207+
mRequestHandler->setServiceException( ex );
208+
}
209+
}
210+
//GetSchemaExtension
211+
else if ( request.compare( "GetSchemaExtension", Qt::CaseInsensitive ) == 0 )
212+
{
213+
try
214+
{
215+
QDomDocument doc = getSchemaExtension();
216+
mRequestHandler->setXmlResponse( doc );
203217
}
204218
catch ( QgsMapServiceException& ex )
205219
{
@@ -212,7 +226,7 @@ void QgsWMSServer::executeRequest()
212226
try
213227
{
214228
QDomDocument doc = getStyle();
215-
mRequestHandler->setGetStyleResponse( doc );
229+
mRequestHandler->setXmlResponse( doc );
216230
}
217231
catch ( QgsMapServiceException& ex )
218232
{
@@ -222,23 +236,17 @@ void QgsWMSServer::executeRequest()
222236
//GetStyles
223237
else if ( request.compare( "GetStyles", Qt::CaseInsensitive ) == 0 )
224238
{
225-
// GetStyles is only defined for WMS1.1.1/SLD1.0
226-
if ( version != "1.1.1" )
227-
{
228-
mRequestHandler->setServiceException( QgsMapServiceException( "OperationNotSupported", "GetStyles method is only available in WMS version 1.1.1" ) );
229-
}
230-
else
231-
{
232-
try
233-
{
234-
QDomDocument doc = getStyles();
235-
mRequestHandler->setGetStyleResponse( doc );
236-
}
237-
catch ( QgsMapServiceException& ex )
238-
{
239-
mRequestHandler->setServiceException( ex );
240-
}
241-
}
239+
// GetStyles is defined for WMS1.1.1/SLD1.0
240+
// and in qgis-server WMS1.3.0 extension
241+
try
242+
{
243+
QDomDocument doc = getStyles();
244+
mRequestHandler->setXmlResponse( doc );
245+
}
246+
catch ( QgsMapServiceException& ex )
247+
{
248+
mRequestHandler->setServiceException( ex );
249+
}
242250
}
243251
//GetLegendGraphic
244252
else if ( request.compare( "GetLegendGraphic", Qt::CaseInsensitive ) == 0 ||
@@ -313,6 +321,13 @@ QDomDocument QgsWMSServer::getCapabilities( QString version, bool fullProjectInf
313321
QDomDocument doc;
314322
QDomElement wmsCapabilitiesElement;
315323

324+
//Prepare url
325+
QString hrefString = mConfigParser->serviceUrl();
326+
if ( hrefString.isEmpty() )
327+
{
328+
hrefString = serviceUrl();
329+
}
330+
316331
if ( version == "1.1.1" )
317332
{
318333
doc = QDomDocument( "WMT_MS_Capabilities SYSTEM 'http://schemas.opengis.net/wms/1.1.1/WMS_MS_Capabilities.dtd'" ); //WMS 1.1.1 needs DOCTYPE "SYSTEM http://schemas.opengis.net/wms/1.1.1/WMS_MS_Capabilities.dtd"
@@ -324,8 +339,16 @@ QDomDocument QgsWMSServer::getCapabilities( QString version, bool fullProjectInf
324339
addXMLDeclaration( doc );
325340
wmsCapabilitiesElement = doc.createElement( "WMS_Capabilities"/*wms:WMS_Capabilities*/ );
326341
wmsCapabilitiesElement.setAttribute( "xmlns", "http://www.opengis.net/wms" );
342+
wmsCapabilitiesElement.setAttribute( "xmlns:sld", "http://www.opengis.net/sld" );
343+
wmsCapabilitiesElement.setAttribute( "xmlns:qgs", "http://www.qgis.org/wms" );
327344
wmsCapabilitiesElement.setAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" );
328-
wmsCapabilitiesElement.setAttribute( "xsi:schemaLocation", "http://www.opengis.net/wms http://qgis.org/wms_1_3_0.xsd" );
345+
QString schemaLocation = "http://www.opengis.net/wms";
346+
schemaLocation += " http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd";
347+
schemaLocation += " http://www.opengis.net/sld";
348+
schemaLocation += " http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd";
349+
schemaLocation += " http://www.qgis.org/wms";
350+
schemaLocation += " "+ hrefString +"SERVICE=WMS&REQUEST=GetSchemaExtension";
351+
wmsCapabilitiesElement.setAttribute( "xsi:schemaLocation", schemaLocation );
329352
}
330353
wmsCapabilitiesElement.setAttribute( "version", version );
331354
doc.appendChild( wmsCapabilitiesElement );
@@ -355,14 +378,6 @@ QDomDocument QgsWMSServer::getCapabilities( QString version, bool fullProjectInf
355378
elem.appendChild( dcpTypeElement );
356379
requestElement.appendChild( elem );
357380

358-
//Prepare url
359-
QString hrefString = mConfigParser->serviceUrl();
360-
if ( hrefString.isEmpty() )
361-
{
362-
hrefString = serviceUrl();
363-
}
364-
365-
366381
// SOAP platform
367382
//only give this information if it is not a WMS request to be in sync with the WMS capabilities schema
368383
QMap<QString, QString>::const_iterator service_it = mParameters.find( "SERVICE" );
@@ -411,29 +426,32 @@ QDomDocument QgsWMSServer::getCapabilities( QString version, bool fullProjectInf
411426
requestElement.appendChild( elem );
412427

413428
//wms:GetLegendGraphic
414-
elem = doc.createElement( "GetLegendGraphic"/*wms:GetLegendGraphic*/ );
429+
elem = doc.createElement( ( version == "1.1.1" ? "GetLegendGraphic" : "sld:GetLegendGraphic" )/*wms:GetLegendGraphic*/ );
415430
appendFormats( doc, elem, QStringList() << "image/jpeg" << "image/png" );
416431
elem.appendChild( dcpTypeElement.cloneNode().toElement() ); // this is the same as for 'GetCapabilities'
417432
requestElement.appendChild( elem );
418433

419434
//wms:GetStyles
420-
elem = doc.createElement( "GetStyles"/*wms:GetStyles*/ );
435+
elem = doc.createElement( ( version == "1.1.1" ? "GetStyles" : "qgs:GetStyles" )/*wms:GetStyles*/ );
421436
appendFormats( doc, elem, QStringList() << "text/xml" );
422437
elem.appendChild( dcpTypeElement.cloneNode().toElement() ); //this is the same as for 'GetCapabilities'
423438
requestElement.appendChild( elem );
424439

425-
//wms:GetPrint
426-
elem = doc.createElement( "GetPrint"/*wms:GetPrint*/ );
427-
appendFormats( doc, elem, QStringList() << "svg" << "png" << "pdf" );
428-
elem.appendChild( dcpTypeElement.cloneNode().toElement() ); //this is the same as for 'GetCapabilities'
429-
requestElement.appendChild( elem );
440+
if ( fullProjectInformation ) //remove composer templates from GetCapabilities in the long term
441+
{
442+
//wms:GetPrint
443+
elem = doc.createElement( "GetPrint" /*wms:GetPrint*/ );
444+
appendFormats( doc, elem, QStringList() << "svg" << "png" << "pdf" );
445+
elem.appendChild( dcpTypeElement.cloneNode().toElement() ); //this is the same as for 'GetCapabilities'
446+
requestElement.appendChild( elem );
447+
}
430448

431449
//Exception element is mandatory
432450
elem = doc.createElement( "Exception" );
433451
appendFormats( doc, elem, QStringList() << ( version == "1.1.1" ? "application/vnd.ogc.se_xml" : "text/xml" ) );
434452
capabilityElement.appendChild( elem );
435453

436-
if ( mConfigParser /*&& fullProjectInformation*/ ) //remove composer templates from GetCapabilities in the long term
454+
if ( mConfigParser && fullProjectInformation ) //remove composer templates from GetCapabilities in the long term
437455
{
438456
//Insert <ComposerTemplate> elements derived from wms:_ExtendedCapabilities
439457
mConfigParser->printCapabilities( capabilityElement, doc );
@@ -956,6 +974,42 @@ void QgsWMSServer::legendParameters( double& boxSpace, double& layerSpace, doubl
956974
}
957975
}
958976

977+
QDomDocument QgsWMSServer::getSchemaExtension()
978+
{
979+
QDomDocument xsdDoc;
980+
981+
QFileInfo xsdFileInfo( "schemaExtension.xsd" );
982+
if ( !xsdFileInfo.exists() )
983+
{
984+
QgsMessageLog::logMessage( "Error, xsd file 'schemaExtension.xsd' does not exist", "Server", QgsMessageLog::CRITICAL );
985+
return xsdDoc;
986+
}
987+
988+
QString xsdFilePath = xsdFileInfo.absoluteFilePath();
989+
QFile xsdFile( xsdFilePath );
990+
if ( !xsdFile.exists() )
991+
{
992+
QgsMessageLog::logMessage( "Error, xsd file 'schemaExtension.xsd' does not exist", "Server", QgsMessageLog::CRITICAL );
993+
return xsdDoc;
994+
}
995+
996+
if ( !xsdFile.open( QIODevice::ReadOnly ) )
997+
{
998+
QgsMessageLog::logMessage( "Error, cannot open xsd file 'schemaExtension.xsd' does not exist", "Server", QgsMessageLog::CRITICAL );
999+
return xsdDoc;
1000+
}
1001+
1002+
QString errorMsg;
1003+
int line, column;
1004+
if ( !xsdDoc.setContent( &xsdFile, true, &errorMsg, &line, &column ) )
1005+
{
1006+
QgsMessageLog::logMessage( "Error parsing file 'schemaExtension.xsd" +
1007+
QString( "': parse error %1 at row %2, column %3" ).arg( errorMsg ).arg( line ).arg( column ), "Server", QgsMessageLog::CRITICAL );
1008+
return xsdDoc;
1009+
}
1010+
return xsdDoc;
1011+
}
1012+
9591013
QDomDocument QgsWMSServer::getStyle()
9601014
{
9611015
QDomDocument doc;
@@ -975,7 +1029,7 @@ QDomDocument QgsWMSServer::getStyle()
9751029
return mConfigParser->getStyle( styleName, layerName );
9761030
}
9771031

978-
// GetStyles is only defined for WMS1.1.1/SLD1.0
1032+
// GetStyles is defined for WMS1.1.1/SLD1.0 and in WMS 1.3.0 SLD Extension
9791033
QDomDocument QgsWMSServer::getStyles()
9801034
{
9811035
QDomDocument doc;

src/server/qgswmsserver.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ class QgsWMSServer: public QgsOWSServer
100100

101101
/**Sets configuration parser for administration settings. Does not take ownership*/
102102
void setAdminConfigParser( QgsWMSConfigParser* parser ) { mConfigParser = parser; }
103+
104+
/**Returns the schemaExtension for WMS 1.3.0 capabilities*/
105+
QDomDocument getSchemaExtension();
103106

104107
private:
105108
/**Don't use the default constructor*/

src/server/schemaExtension.xsd

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:wms="http://www.opengis.net/wms" xmlns:qgs="http://www.qgis.org/wms" targetNamespace="http://www.qgis.org/wms" elementFormDefault="qualified" version="1.0.0">
3+
<import namespace="http://www.opengis.net/wms" schemaLocation="http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd"/>
4+
<element name="GetPrint" type="wms:OperationType" substitutionGroup="wms:_ExtendedOperation" />
5+
<element name="GetStyles" type="wms:OperationType" substitutionGroup="wms:_ExtendedOperation" />
6+
</schema>

0 commit comments

Comments
 (0)