Skip to content

Commit c2b5da3

Browse files
committedDec 4, 2014
[QGIS-Server] FIX 10489 QGIS Server getcapabilites response is not WMS compliant
To be fully compliant with WMS 1.3.0 standard, I propose to add : * SLD namespace for GetLegendGraphic element * schemaExtension.xsd distributed with QGIS-Server for GetStyles and GetPrint * GetSchemaExtension to retrieve schemaExtension.xsd like MapServer The solution was inspired by http://demo.mapserver.org/cgi-bin/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities And the standard description Styled Layer Descriptor profile of the Web Map Service Implementation Specification http://portal.opengeospatial.org/files/?artifact_id=22364
1 parent 0fa40a6 commit c2b5da3

9 files changed

+113
-37
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: 83 additions & 32 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,19 +426,19 @@ 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

425440
//wms:GetPrint
426-
elem = doc.createElement( "GetPrint"/*wms:GetPrint*/ );
441+
elem = doc.createElement( ( version == "1.1.1" ? "GetPrint" : "qgs:GetPrint" ) /*wms:GetPrint*/ );
427442
appendFormats( doc, elem, QStringList() << "svg" << "png" << "pdf" );
428443
elem.appendChild( dcpTypeElement.cloneNode().toElement() ); //this is the same as for 'GetCapabilities'
429444
requestElement.appendChild( elem );
@@ -956,6 +971,42 @@ void QgsWMSServer::legendParameters( double& boxSpace, double& layerSpace, doubl
956971
}
957972
}
958973

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

978-
// GetStyles is only defined for WMS1.1.1/SLD1.0
1029+
// GetStyles is defined for WMS1.1.1/SLD1.0 and in WMS 1.3.0 SLD Extension
9791030
QDomDocument QgsWMSServer::getStyles()
9801031
{
9811032
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)
Please sign in to comment.