[Server] WMS GetFeatureInfo refactoring

This commit is contained in:
rldhont 2017-07-03 17:58:47 +02:00
parent e61daed979
commit f926033699
10 changed files with 735 additions and 235 deletions

View File

@ -145,6 +145,62 @@ namespace QgsServerProjectUtils
:rtype: bool
%End
bool wmsFeatureInfoAddWktGeometry( const QgsProject &project );
%Docstring
Returns if the geometry is displayed as Well Known Text in GetFeatureInfo request.
\param project the QGIS project
:return: if the geometry is displayed as Well Known Text in GetFeatureInfo request.
:rtype: bool
%End
bool wmsFeatureInfoSegmentizeWktGeometry( const QgsProject &project );
%Docstring
Returns if the geometry has to be segmentize in GetFeatureInfo request.
\param project the QGIS project
:return: if the geometry has to be segmentize in GetFeatureInfo request.
:rtype: bool
%End
int wmsFeatureInfoPrecision( const QgsProject &project );
%Docstring
Returns the geometry precision for GetFeatureInfo request.
\param project the QGIS project
:return: the geometry precision for GetFeatureInfo request.
:rtype: int
%End
QString wmsFeatureInfoDocumentElement( const QgsProject &project );
%Docstring
Returns the document element name for XML GetFeatureInfo request.
\param project the QGIS project
:return: the document element name for XML GetFeatureInfo request.
:rtype: str
%End
QString wmsFeatureInfoDocumentElementNs( const QgsProject &project );
%Docstring
Returns the document element namespace for XML GetFeatureInfo request.
\param project the QGIS project
:return: the document element namespace for XML GetFeatureInfo request.
:rtype: str
%End
QString wmsFeatureInfoSchema( const QgsProject &project );
%Docstring
Returns the schema URL for XML GetFeatureInfo request.
\param project the QGIS project
:return: the schema URL for XML GetFeatureInfo request.
:rtype: str
%End
QHash<QString, QString> wmsFeatureInfoLayerAliasMap( const QgsProject &project );
%Docstring
Returns the mapping between layer name and wms layer name for GetFeatureInfo request.
\param project the QGIS project
:return: the mapping between layer name and wms layer name for GetFeatureInfo request.
:rtype: QHash<str, QString>
%End
bool wmsInspireActivate( const QgsProject &project );
%Docstring
Returns if Inspire is activated.

View File

@ -117,6 +117,77 @@ bool QgsServerProjectUtils::wmsInfoFormatSia2045( const QgsProject &project )
return false;
}
bool QgsServerProjectUtils::wmsFeatureInfoAddWktGeometry( const QgsProject &project )
{
QString wktGeom = project.readEntry( QStringLiteral( "WMSAddWktGeometry" ), QStringLiteral( "/" ), "" );
if ( wktGeom.compare( QLatin1String( "enabled" ), Qt::CaseInsensitive ) == 0
|| wktGeom.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
{
return true;
}
return false;
}
bool QgsServerProjectUtils::wmsFeatureInfoSegmentizeWktGeometry( const QgsProject &project )
{
QString segmGeom = project.readEntry( QStringLiteral( "WMSSegmentizeFeatureInfoGeometry" ), QStringLiteral( "/" ), "" );
if ( segmGeom.compare( QLatin1String( "enabled" ), Qt::CaseInsensitive ) == 0
|| segmGeom.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
{
return true;
}
return false;
}
int QgsServerProjectUtils::wmsFeatureInfoPrecision( const QgsProject &project )
{
return project.readNumEntry( QStringLiteral( "WMSPrecision" ), QStringLiteral( "/" ), 6 );
}
QString QgsServerProjectUtils::wmsFeatureInfoDocumentElement( const QgsProject &project )
{
return project.readEntry( QStringLiteral( "WMSFeatureInfoDocumentElement" ), QStringLiteral( "/" ), "" );
}
QString QgsServerProjectUtils::wmsFeatureInfoDocumentElementNs( const QgsProject &project )
{
return project.readEntry( QStringLiteral( "WMSFeatureInfoDocumentElementNS" ), QStringLiteral( "/" ), "" );
}
QString QgsServerProjectUtils::wmsFeatureInfoSchema( const QgsProject &project )
{
return project.readEntry( QStringLiteral( "WMSFeatureInfoSchema" ), QStringLiteral( "/" ), "" );
}
QHash<QString, QString> QgsServerProjectUtils::wmsFeatureInfoLayerAliasMap( const QgsProject &project )
{
QHash<QString, QString> aliasMap;
//WMSFeatureInfoAliasLayers
QStringList aliasLayerStringList = project.readListEntry( QStringLiteral( "WMSFeatureInfoAliasLayers" ), QStringLiteral( "/value" ), QStringList() );
if ( aliasLayerStringList.isEmpty() )
{
return aliasMap;
}
//WMSFeatureInfoLayerAliases
QStringList layerAliasStringList = project.readListEntry( QStringLiteral( "WMSFeatureInfoLayerAliases" ), QStringLiteral( "/value" ), QStringList() );
if ( layerAliasStringList.isEmpty() )
{
return aliasMap;
}
int nMapEntries = qMin( aliasLayerStringList.size(), layerAliasStringList.size() );
for ( int i = 0; i < nMapEntries; ++i )
{
aliasMap.insert( aliasLayerStringList.at( i ), layerAliasStringList.at( i ) );
}
return aliasMap;
}
bool QgsServerProjectUtils::wmsInspireActivate( const QgsProject &project )
{
return project.readBoolEntry( QStringLiteral( "WMSInspire" ), QStringLiteral( "/activated" ) );

View File

@ -132,6 +132,48 @@ namespace QgsServerProjectUtils
*/
SERVER_EXPORT bool wmsInfoFormatSia2045( const QgsProject &project );
/** Returns if the geometry is displayed as Well Known Text in GetFeatureInfo request.
* \param project the QGIS project
* \returns if the geometry is displayed as Well Known Text in GetFeatureInfo request.
*/
SERVER_EXPORT bool wmsFeatureInfoAddWktGeometry( const QgsProject &project );
/** Returns if the geometry has to be segmentize in GetFeatureInfo request.
* \param project the QGIS project
* \returns if the geometry has to be segmentize in GetFeatureInfo request.
*/
SERVER_EXPORT bool wmsFeatureInfoSegmentizeWktGeometry( const QgsProject &project );
/** Returns the geometry precision for GetFeatureInfo request.
* \param project the QGIS project
* \returns the geometry precision for GetFeatureInfo request.
*/
SERVER_EXPORT int wmsFeatureInfoPrecision( const QgsProject &project );
/** Returns the document element name for XML GetFeatureInfo request.
* \param project the QGIS project
* \returns the document element name for XML GetFeatureInfo request.
*/
SERVER_EXPORT QString wmsFeatureInfoDocumentElement( const QgsProject &project );
/** Returns the document element namespace for XML GetFeatureInfo request.
* \param project the QGIS project
* \returns the document element namespace for XML GetFeatureInfo request.
*/
SERVER_EXPORT QString wmsFeatureInfoDocumentElementNs( const QgsProject &project );
/** Returns the schema URL for XML GetFeatureInfo request.
* \param project the QGIS project
* \returns the schema URL for XML GetFeatureInfo request.
*/
SERVER_EXPORT QString wmsFeatureInfoSchema( const QgsProject &project );
/** Returns the mapping between layer name and wms layer name for GetFeatureInfo request.
* \param project the QGIS project
* \returns the mapping between layer name and wms layer name for GetFeatureInfo request.
*/
SERVER_EXPORT QHash<QString, QString> wmsFeatureInfoLayerAliasMap( const QgsProject &project );
/** Returns if Inspire is activated.
* \param project the QGIS project
* \returns if Inspire is activated.

View File

@ -191,6 +191,41 @@ namespace QgsWms
};
save( pFormat );
const Parameter pInfoFormat = { ParameterName::INFO_FORMAT,
QVariant::String,
QVariant( "" ),
QVariant()
};
save( pInfoFormat );
const Parameter pI = { ParameterName::I,
QVariant::Int,
QVariant( -1 ),
QVariant()
};
save( pI );
const Parameter pJ = { ParameterName::J,
QVariant::Int,
QVariant( -1 ),
QVariant()
};
save( pJ );
const Parameter pX = { ParameterName::X,
QVariant::Int,
QVariant( -1 ),
QVariant()
};
save( pX );
const Parameter pY = { ParameterName::Y,
QVariant::Int,
QVariant( -1 ),
QVariant()
};
save( pY );
const Parameter pRule = { ParameterName::RULE,
QVariant::String,
QVariant( "" ),
@ -254,6 +289,20 @@ namespace QgsWms
};
save( pLayers );
const Parameter pQueryLayers = { ParameterName::QUERY_LAYERS,
QVariant::String,
QVariant( "" ),
QVariant()
};
save( pQueryLayers );
const Parameter pFeatureCount = { ParameterName::FEATURE_COUNT,
QVariant::Int,
QVariant( 1 ),
QVariant()
};
save( pFeatureCount );
const Parameter pLayerTitle = { ParameterName::LAYERTITLE,
QVariant::Bool,
QVariant( true ),
@ -324,12 +373,26 @@ namespace QgsWms
};
save( pFilter );
const Parameter pFilterGeom = { ParameterName::FILTER_GEOM,
QVariant::String,
QVariant( "" ),
QVariant()
};
save( pFilterGeom );
const Parameter pSelection = { ParameterName::SELECTION,
QVariant::String,
QVariant( "" ),
QVariant()
};
save( pSelection );
const Parameter pWmsPrecision = { ParameterName::WMS_PRECISION,
QVariant::Int,
QVariant( -1 ),
QVariant()
};
save( pWmsPrecision );
}
QgsWmsParameters::QgsWmsParameters( const QgsServerRequest::Parameters &parameters )
@ -341,6 +404,7 @@ namespace QgsWms
{
mRequestParameters = parameters;
log( "load WMS Request parameters:" );
const QMetaEnum metaEnum( QMetaEnum::fromType<ParameterName>() );
foreach ( QString key, parameters.keys() )
{
@ -351,6 +415,7 @@ namespace QgsWms
if ( value.canConvert( mParameters[name].mType ) )
{
mParameters[name].mValue = value;
log( " - " + key + " : " + parameters[key] );
}
else
{
@ -628,9 +693,12 @@ namespace QgsWms
QgsWmsParameters::Format QgsWmsParameters::format() const
{
Format f = Format::PNG;
QString fStr = formatAsString();
if ( fStr.isEmpty() )
return Format::NONE;
Format f = Format::PNG;
if ( fStr.compare( QLatin1String( "jpg" ), Qt::CaseInsensitive ) == 0
|| fStr.compare( QLatin1String( "jpeg" ), Qt::CaseInsensitive ) == 0
|| fStr.compare( QLatin1String( "image/jpeg" ), Qt::CaseInsensitive ) == 0 )
@ -639,6 +707,69 @@ namespace QgsWms
return f;
}
QString QgsWmsParameters::infoFormatAsString() const
{
return value( ParameterName::INFO_FORMAT ).toString();
}
QgsWmsParameters::Format QgsWmsParameters::infoFormat() const
{
QString fStr = infoFormatAsString();
if ( fStr.isEmpty() )
return Format::NONE;
Format f = Format::TEXT;
if ( fStr.startsWith( QLatin1String( "text/xml" ), Qt::CaseInsensitive ) )
f = Format::XML;
else if ( fStr.startsWith( QLatin1String( "text/html" ), Qt::CaseInsensitive ) )
f = Format::HTML;
else if ( fStr.startsWith( QLatin1String( "application/vnd.ogc.gml" ), Qt::CaseInsensitive ) )
f = Format::GML;
return f;
}
QString QgsWmsParameters::i() const
{
return value( ParameterName::I ).toString();
}
QString QgsWmsParameters::j() const
{
return value( ParameterName::J ).toString();
}
int QgsWmsParameters::iAsInt() const
{
return toInt( ParameterName::I );
}
int QgsWmsParameters::jAsInt() const
{
return toInt( ParameterName::J );
}
QString QgsWmsParameters::x() const
{
return value( ParameterName::X ).toString();
}
QString QgsWmsParameters::y() const
{
return value( ParameterName::Y ).toString();
}
int QgsWmsParameters::xAsInt() const
{
return toInt( ParameterName::X );
}
int QgsWmsParameters::yAsInt() const
{
return toInt( ParameterName::Y );
}
QString QgsWmsParameters::rule() const
{
return value( ParameterName::RULE ).toString();
@ -674,6 +805,16 @@ namespace QgsWms
return toBool( ParameterName::SHOWFEATURECOUNT );
}
QString QgsWmsParameters::featureCount() const
{
return value( ParameterName::FEATURE_COUNT ).toString();
}
int QgsWmsParameters::featureCountAsInt() const
{
return toInt( ParameterName::FEATURE_COUNT );
}
QString QgsWmsParameters::boxSpace() const
{
return value( ParameterName::BOXSPACE ).toString();
@ -960,6 +1101,16 @@ namespace QgsWms
return toFloatList( highlightLabelBufferSize(), ParameterName::HIGHLIGHT_LABELBUFFERSIZE );
}
QString QgsWmsParameters::wmsPrecision() const
{
return value( ParameterName::WMS_PRECISION ).toString();
}
int QgsWmsParameters::wmsPrecisionAsInt() const
{
return toInt( ParameterName::WMS_PRECISION );
}
QString QgsWmsParameters::sld() const
{
return value( ParameterName::SLD ).toString();
@ -970,6 +1121,11 @@ namespace QgsWms
return toStringList( ParameterName::FILTER, ';' );
}
QString QgsWmsParameters::filterGeom() const
{
return value( ParameterName::FILTER_GEOM ).toString();
}
QStringList QgsWmsParameters::selections() const
{
return toStringList( ParameterName::SELECTION );
@ -992,6 +1148,11 @@ namespace QgsWms
return layer << layers;
}
QStringList QgsWmsParameters::queryLayersNickname() const
{
return toStringList( ParameterName::QUERY_LAYERS );
}
QStringList QgsWmsParameters::allStyles() const
{
QStringList style = value( ParameterName::STYLE ).toString().split( ",", QString::SkipEmptyParts );

View File

@ -86,6 +86,8 @@ namespace QgsWms
LAYERS,
LAYERSPACE,
LAYERTITLESPACE,
QUERY_LAYERS,
FEATURE_COUNT,
SHOWFEATURECOUNT,
STYLE,
STYLES,
@ -95,7 +97,13 @@ namespace QgsWms
OPACITIES,
SLD,
FILTER,
FILTER_GEOM,
FORMAT,
INFO_FORMAT,
I,
J,
X,
Y,
RULE,
RULELABEL,
SCALE,
@ -108,7 +116,8 @@ namespace QgsWms
HIGHLIGHT_LABELWEIGHT,
HIGHLIGHT_LABELCOLOR,
HIGHLIGHT_LABELBUFFERCOLOR,
HIGHLIGHT_LABELBUFFERSIZE
HIGHLIGHT_LABELBUFFERSIZE,
WMS_PRECISION
};
Q_ENUM( ParameterName )
@ -116,7 +125,11 @@ namespace QgsWms
{
NONE,
JPG,
PNG
PNG,
TEXT,
XML,
HTML,
GML
};
struct Parameter
@ -203,6 +216,11 @@ namespace QgsWms
*/
QStringList filters() const;
/** Returns the filter geometry found in FILTER_GEOM parameter.
* \returns the filter geometry as Well Known Text.
*/
QString filterGeom() const;
/** Returns the list of opacities found in OPACITIES parameter.
* \returns the list of opacities in string
*/
@ -221,6 +239,11 @@ namespace QgsWms
*/
QStringList allLayersNickname() const;
/** Returns nickname of layers found in QUERY_LAYERS parameter.
* \returns nickname of layers
*/
QStringList queryLayersNickname() const;
/** Returns styles found in STYLE and STYLES parameters.
* \returns name of styles
*/
@ -242,6 +265,69 @@ namespace QgsWms
*/
Format format() const;
/** Returns INFO_FORMAT parameter as a string.
* \returns INFO_FORMAT parameter as string
*/
QString infoFormatAsString() const;
/** Returns infoFormat. If the INFO_FORMAT parameter is not used, then the
* default value is text/plain.
* \returns infoFormat
*/
Format infoFormat() const;
/** Returns I parameter or an empty string if not defined.
* \returns i parameter
*/
QString i() const;
/** Returns I parameter as an int or its default value if not
* defined. An exception is raised if I is defined and cannot be
* converted.
* \returns i parameter
* \throws QgsBadRequestException
*/
int iAsInt() const;
/** Returns J parameter or an empty string if not defined.
* \returns j parameter
*/
QString j() const;
/** Returns J parameter as an int or its default value if not
* defined. An exception is raised if J is defined and cannot be
* converted.
* \returns j parameter
* \throws QgsBadRequestException
*/
int jAsInt() const;
/** Returns X parameter or an empty string if not defined.
* \returns x parameter
*/
QString x() const;
/** Returns X parameter as an int or its default value if not
* defined. An exception is raised if X is defined and cannot be
* converted.
* \returns x parameter
* \throws QgsBadRequestException
*/
int xAsInt() const;
/** Returns Y parameter or an empty string if not defined.
* \returns y parameter
*/
QString y() const;
/** Returns Y parameter as an int or its default value if not
* defined. An exception is raised if Y is defined and cannot be
* converted.
* \returns j parameter
* \throws QgsBadRequestException
*/
int yAsInt() const;
/** Returns RULE parameter or an empty string if none is defined
* \returns RULE parameter or an empty string if none is defined
*/
@ -271,6 +357,18 @@ namespace QgsWms
*/
bool showFeatureCountAsBool() const;
/** Returns FEATURE_COUNT parameter or an empty string if none is defined
* \returns FEATURE_COUNT parameter or an empty string if none is defined
*/
QString featureCount() const;
/** Returns FEATURE_COUNT as an integer. An exception is raised if an invalid
* parameter is found.
* \returns FeatureCount
* \throws QgsBadRequestException
*/
int featureCountAsInt() const;
/** Returns SCALE parameter or an empty string if none is defined
* \returns SCALE parameter or an empty string if none is defined
*/
@ -595,6 +693,19 @@ namespace QgsWms
*/
QList<QColor> highlightLabelBufferColorAsColor() const;
/** Returns WMS_PRECISION parameter or an empty string if not defined.
* \returns wms precision parameter
*/
QString wmsPrecision() const;
/** Returns WMS_PRECISION parameter as an int or its default value if not
* defined. An exception is raised if WMS_PRECISION is defined and cannot be
* converted.
* \returns wms precision parameter
* \throws QgsBadRequestException
*/
int wmsPrecisionAsInt() const;
private:
QString name( ParameterName name ) const;
void raiseError( ParameterName name ) const;

View File

@ -644,131 +644,161 @@ namespace QgsWms
QDomDocument QgsRenderer::getFeatureInfo( const QString &version )
{
if ( !mConfigParser )
// Verifying Mandatory parameters
// The INFO_FORMAT parameter is Mandatory
if ( mWmsParameters.infoFormat() == QgsWmsParameters::Format::NONE )
{
throw QgsException( QStringLiteral( "No config parser" ) );
throw QgsBadRequestException( QStringLiteral( "ParameterMissing" ),
QStringLiteral( "INFO_FORMAT parameter is required for GetFeatureInfo" ) );
}
QDomDocument result;
QStringList layersList, stylesList;
bool conversionSuccess;
for ( auto it = mParameters.constBegin(); it != mParameters.constEnd(); ++it )
// The QUERY_LAYERS parameter is Mandatory
QStringList queryLayers = mWmsParameters.queryLayersNickname();
if ( queryLayers.isEmpty() )
{
QgsMessageLog::logMessage( QStringLiteral( "%1 // %2" ).arg( it.key(), it.value() ) );
throw QgsBadRequestException( QStringLiteral( "ParameterMissing" ),
QStringLiteral( "QUERY_LAYERS parameter is required for GetFeatureInfo" ) );
}
readLayersAndStyles( mParameters, layersList, stylesList );
initializeSLDParser( layersList, stylesList );
// The I/J parameters are Mandatory if they are not replaced by X/Y or FILTER or FILTER_GEOM
bool ijDefined = false;
if ( !mWmsParameters.i().isEmpty() && !mWmsParameters.j().isEmpty() )
ijDefined = true;
QgsMapSettings mapSettings;
std::unique_ptr<QImage> outputImage( createImage() );
bool xyDefined = false;
if ( !mWmsParameters.x().isEmpty() && !mWmsParameters.y().isEmpty() )
xyDefined = true;
configureMapSettings( outputImage.get(), mapSettings );
bool filtersDefined = false;
if ( !mWmsParameters.filters().isEmpty() )
filtersDefined = true;
QgsMessageLog::logMessage( "mapSettings.extent(): " + mapSettings.extent().toString() );
QgsMessageLog::logMessage( QStringLiteral( "mapSettings width = %1 height = %2" ).arg( mapSettings.outputSize().width() ).arg( mapSettings.outputSize().height() ) );
QgsMessageLog::logMessage( QStringLiteral( "mapSettings.mapUnitsPerPixel() = %1" ).arg( mapSettings.mapUnitsPerPixel() ) );
bool filterGeomDefined = false;
if ( !mWmsParameters.filterGeom().isEmpty() )
filterGeomDefined = true;
//find out the current scale denominator and set it to the SLD parser
QgsScaleCalculator scaleCalc( ( outputImage->logicalDpiX() + outputImage->logicalDpiY() ) / 2, mapSettings.destinationCrs().mapUnits() );
QgsRectangle mapExtent = mapSettings.extent();
double scaleDenominator = scaleCalc.calculate( mapExtent, outputImage->width() );
mConfigParser->setScaleDenominator( scaleDenominator );
//read FEATURE_COUNT
int featureCount = 1;
if ( mParameters.contains( QStringLiteral( "FEATURE_COUNT" ) ) )
{
featureCount = mParameters[ QStringLiteral( "FEATURE_COUNT" )].toInt( &conversionSuccess );
if ( !conversionSuccess )
{
featureCount = 1;
}
}
//read QUERY_LAYERS
if ( !mParameters.contains( QStringLiteral( "QUERY_LAYERS" ) ) )
{
throw QgsBadRequestException( QStringLiteral( "ParameterMissing" ), QStringLiteral( "No QUERY_LAYERS" ) );
}
QStringList queryLayerList = mParameters[ QStringLiteral( "QUERY_LAYERS" )].split( ',', QString::SkipEmptyParts );
if ( queryLayerList.isEmpty() )
{
throw QgsBadRequestException( QStringLiteral( "InvalidParameterValue" ), QStringLiteral( "Malformed QUERY_LAYERS" ) );
}
//read I,J resp. X,Y
QString iString = mParameters.value( QStringLiteral( "I" ), mParameters.value( QStringLiteral( "X" ) ) );
int i = iString.toInt( &conversionSuccess );
if ( !conversionSuccess )
{
i = -1;
}
QString jString = mParameters.value( QStringLiteral( "J" ), mParameters.value( QStringLiteral( "Y" ) ) );
int j = jString.toInt( &conversionSuccess );
if ( !conversionSuccess )
{
j = -1;
}
//read FILTER_GEOM
std::unique_ptr<QgsGeometry> filterGeom;
if ( mParameters.contains( QStringLiteral( "FILTER_GEOM" ) ) )
{
filterGeom.reset( new QgsGeometry( QgsGeometry::fromWkt( mParameters.value( QStringLiteral( "FILTER_GEOM" ) ) ) ) );
}
//In case the output image is distorted (WIDTH/HEIGHT ratio not equal to BBOX width/height), I and J need to be adapted as well
int widthParam = mParameters.value( "WIDTH", "-1" ).toInt();
int heightParam = mParameters.value( "HEIGHT", "-1" ).toInt();
if ( ( i != -1 && j != -1 && widthParam != -1 && heightParam != -1 ) && ( widthParam != outputImage->width() || heightParam != outputImage->height() ) )
{
i *= ( outputImage->width() / ( double )widthParam );
j *= ( outputImage->height() / ( double )heightParam );
}
//Normally, I/J or X/Y are mandatory parameters.
//However, in order to make attribute only queries via the FILTER parameter, it is allowed to skip them if the FILTER parameter is there
std::unique_ptr<QgsRectangle> featuresRect;
std::unique_ptr<QgsPointXY> infoPoint;
if ( i == -1 || j == -1 )
{
if ( mParameters.contains( QStringLiteral( "FILTER" ) ) )
{
featuresRect.reset( new QgsRectangle() );
}
else if ( !filterGeom.get() )
if ( !ijDefined && !xyDefined && !filtersDefined && !filterGeomDefined )
{
throw QgsBadRequestException( QStringLiteral( "ParameterMissing" ),
QStringLiteral( "I/J parameters are required for GetFeatureInfo" ) );
}
}
// get layers parameters
QList<QgsMapLayer *> layers;
QList<QgsWmsParametersLayer> params = mWmsParameters.layersParameters();
// init layer restorer before doing anything
std::unique_ptr<QgsLayerRestorer> restorer;
restorer.reset( new QgsLayerRestorer( mNicknameLayers.values() ) );
// init stylized layers according to LAYERS/STYLES or SLD
QString sld = mWmsParameters.sld();
if ( !sld.isEmpty() )
layers = sldStylizedLayers( sld );
else
layers = stylizedLayers( params );
// create the mapSettings and the output image
QgsMapSettings mapSettings;
std::unique_ptr<QImage> outputImage( createImage() );
// configure map settings (background, DPI, ...)
configureMapSettings( outputImage.get(), mapSettings );
QgsMessageLog::logMessage( "mapSettings.destinationCrs(): " + mapSettings.destinationCrs().authid() );
QgsMessageLog::logMessage( "mapSettings.extent(): " + mapSettings.extent().toString() );
QgsMessageLog::logMessage( QStringLiteral( "mapSettings width = %1 height = %2" ).arg( mapSettings.outputSize().width() ).arg( mapSettings.outputSize().height() ) );
QgsMessageLog::logMessage( QStringLiteral( "mapSettings.mapUnitsPerPixel() = %1" ).arg( mapSettings.mapUnitsPerPixel() ) );
QgsScaleCalculator scaleCalc( ( outputImage->logicalDpiX() + outputImage->logicalDpiY() ) / 2, mapSettings.destinationCrs().mapUnits() );
QgsRectangle mapExtent = mapSettings.extent();
double scaleDenominator = scaleCalc.calculate( mapExtent, outputImage->width() );
// remove unwanted layers (restricted layers, ...)
removeUnwantedLayers( layers, scaleDenominator );
// remove non identifiable layers
QStringList nonIdentifiableLayers = mProject->nonIdentifiableLayers();
if ( !nonIdentifiableLayers.isEmpty() )
{
QList<QgsMapLayer *> wantedLayers;
Q_FOREACH ( QgsMapLayer *layer, layers )
{
if ( nonIdentifiableLayers.contains( layer->id() ) )
continue;
wantedLayers.append( layer );
}
layers = wantedLayers;
}
Q_FOREACH ( QgsMapLayer *layer, layers )
{
Q_FOREACH ( QgsWmsParametersLayer param, params )
{
if ( param.mNickname == layerNickname( *layer ) )
{
checkLayerReadPermissions( layer );
setLayerFilter( layer, param.mFilter );
setLayerAccessControlFilter( layer );
break;
}
}
}
// add layers to map settings (revert order for the rendering)
std::reverse( layers.begin(), layers.end() );
mapSettings.setLayers( layers );
int featureCount = mWmsParameters.featureCountAsInt();
if ( featureCount < 1 )
{
featureCount = 1;
}
int i = mWmsParameters.iAsInt();
int j = mWmsParameters.jAsInt();
if ( xyDefined && !ijDefined )
{
i = mWmsParameters.xAsInt();
j = mWmsParameters.yAsInt();
}
int width = mWmsParameters.widthAsInt();
int height = mWmsParameters.heightAsInt();
if ( ( i != -1 && j != -1 && width != 0 && height != 0 ) && ( width != outputImage->width() || height != outputImage->height() ) )
{
i *= ( outputImage->width() / ( double )width );
j *= ( outputImage->height() / ( double )height );
}
// init search variables
std::unique_ptr<QgsRectangle> featuresRect;
std::unique_ptr<QgsGeometry> filterGeom;
std::unique_ptr<QgsPointXY> infoPoint;
if ( i != -1 && j != -1 )
{
infoPoint.reset( new QgsPointXY() );
infoPointToMapCoordinates( i, j, infoPoint.get(), mapSettings );
}
else if ( filtersDefined )
{
featuresRect.reset( new QgsRectangle() );
}
else if ( filterGeomDefined )
{
filterGeom.reset( new QgsGeometry( QgsGeometry::fromWkt( mWmsParameters.filterGeom() ) ) );
}
//get the layer registered in QgsMapLayerRegistry and apply possible filters
( void )layerSet( layersList, stylesList, mapSettings.destinationCrs() );
//scoped pointer to restore all original layer filters (subsetStrings) when pointer goes out of scope
//there's LOTS of potential exit paths here, so we avoid having to restore the filters manually
std::unique_ptr< QgsOWSServerFilterRestorer > filterRestorer( new QgsOWSServerFilterRestorer( mAccessControl ) );
applyRequestedLayerFilters( layersList, mapSettings, filterRestorer->originalFilters() );
#ifdef HAVE_SERVER_PYTHON_PLUGINS
applyAccessControlLayersFilters( layersList, filterRestorer->originalFilters() );
#endif
QDomDocument result;
QDomElement getFeatureInfoElement;
QString infoFormat = mParameters.value( QStringLiteral( "INFO_FORMAT" ) );
if ( infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml" ) ) )
QgsWmsParameters::Format infoFormat = mWmsParameters.infoFormat();
if ( infoFormat == QgsWmsParameters::Format::GML )
{
getFeatureInfoElement = result.createElement( QStringLiteral( "wfs:FeatureCollection" ) );
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:wfs" ), QStringLiteral( "http://www.opengis.net/wfs" ) );
@ -782,18 +812,22 @@ namespace QgsWms
}
else
{
QString featureInfoElemName = mConfigParser->featureInfoDocumentElement( QStringLiteral( "GetFeatureInfoResponse" ) );
QString featureInfoElemNS = mConfigParser->featureInfoDocumentElementNS();
if ( featureInfoElemNS.isEmpty() )
QString featureInfoElemName = QgsServerProjectUtils::wmsFeatureInfoDocumentElement( *mProject );
if ( featureInfoElemName.isEmpty() )
{
featureInfoElemName = QStringLiteral( "GetFeatureInfoResponse" );
}
QString featureInfoElemNs = QgsServerProjectUtils::wmsFeatureInfoDocumentElementNs( *mProject );
if ( featureInfoElemNs.isEmpty() )
{
getFeatureInfoElement = result.createElement( featureInfoElemName );
}
else
{
getFeatureInfoElement = result.createElementNS( featureInfoElemNS, featureInfoElemName );
getFeatureInfoElement = result.createElementNS( featureInfoElemNs, featureInfoElemName );
}
//feature info schema
QString featureInfoSchema = mConfigParser->featureInfoSchema();
QString featureInfoSchema = QgsServerProjectUtils::wmsFeatureInfoSchema( *mProject );
if ( !featureInfoSchema.isEmpty() )
{
getFeatureInfoElement.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
@ -802,64 +836,29 @@ namespace QgsWms
}
result.appendChild( getFeatureInfoElement );
QStringList nonIdentifiableLayers = mConfigParser->identifyDisabledLayers();
//Render context is needed to determine feature visibility for vector layers
QgsRenderContext renderContext = QgsRenderContext::fromMapSettings( mapSettings );
bool sia2045 = mConfigParser->featureInfoFormatSIA2045();
bool sia2045 = QgsServerProjectUtils::wmsInfoFormatSia2045( *mProject );
//layers can have assigned a different name for GetCapabilities
QHash<QString, QString> layerAliasMap = mConfigParser->featureInfoLayerAliasMap();
QHash<QString, QString> layerAliasMap = QgsServerProjectUtils::wmsFeatureInfoLayerAliasMap( *mProject );
QList<QgsMapLayer *> layerList;
QgsMapLayer *currentLayer = nullptr;
for ( auto layerIt = queryLayerList.constBegin(); layerIt != queryLayerList.constEnd(); ++layerIt )
Q_FOREACH ( QString queryLayer, queryLayers )
{
//create maplayers from sld parser (several layers are possible in case of feature info on a group)
layerList = mConfigParser->mapLayerFromStyle( *layerIt, QLatin1String( "" ) );
for ( auto layerListIt = layerList.begin() ; layerListIt != layerList.end(); ++layerListIt )
Q_FOREACH ( QgsMapLayer *layer, layers )
{
currentLayer = *layerListIt;
if ( !currentLayer || nonIdentifiableLayers.contains( currentLayer->id() ) )
if ( queryLayer == layerNickname( *layer ) )
{
continue;
}
QgsMapLayer *registeredMapLayer = QgsProject::instance()->mapLayer( currentLayer->id() );
if ( registeredMapLayer )
{
currentLayer = registeredMapLayer;
}
#ifdef HAVE_SERVER_PYTHON_PLUGINS
if ( !mAccessControl->layerReadPermission( currentLayer ) )
{
throw QgsSecurityException( QStringLiteral( "You are not allowed to access to the layer: %1" ).arg( currentLayer->name() ) );
}
#endif
//skip layer if not visible at current map scale
if ( scaleDenominator > 0 && !currentLayer->isInScaleRange( scaleDenominator ) )
{
continue;
}
//switch depending on vector or raster
QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( currentLayer );
QDomElement layerElement;
if ( infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml" ) ) )
if ( infoFormat == QgsWmsParameters::Format::GML )
{
layerElement = getFeatureInfoElement;
}
else
{
layerElement = result.createElement( QStringLiteral( "Layer" ) );
QString layerName = currentLayer->name();
if ( mConfigParser->useLayerIds() )
layerName = currentLayer->id();
else if ( !currentLayer->shortName().isEmpty() )
layerName = currentLayer->shortName();
QString layerName = queryLayer;
//check if the layer is given a different name for GetFeatureInfo output
QHash<QString, QString>::const_iterator layerAliasIt = layerAliasMap.find( layerName );
@ -867,57 +866,62 @@ namespace QgsWms
{
layerName = layerAliasIt.value();
}
layerElement.setAttribute( QStringLiteral( "name" ), layerName );
getFeatureInfoElement.appendChild( layerElement );
if ( sia2045 ) //the name might not be unique after alias replacement
{
layerElement.setAttribute( QStringLiteral( "id" ), currentLayer->id() );
layerElement.setAttribute( QStringLiteral( "id" ), layer->id() );
}
}
if ( layer->type() == QgsMapLayer::VectorLayer )
{
QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer );
if ( vectorLayer )
{
if ( !featureInfoFromVectorLayer( vectorLayer, infoPoint.get(), featureCount, result, layerElement, mapSettings, renderContext, version, infoFormat, featuresRect.get(), filterGeom.get() ) )
if ( !featureInfoFromVectorLayer( vectorLayer, infoPoint.get(), featureCount, result, layerElement, mapSettings, renderContext, version, mWmsParameters.infoFormatAsString(), featuresRect.get(), filterGeom.get() ) )
{
continue;
break;
}
break;
}
}
else //raster layer
else
{
if ( infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml" ) ) )
if ( infoFormat == QgsWmsParameters::Format::GML )
{
layerElement = result.createElement( QStringLiteral( "gml:featureMember" )/*wfs:FeatureMember*/ );
getFeatureInfoElement.appendChild( layerElement );
}
QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( currentLayer );
QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( layer );
if ( rasterLayer )
{
if ( !infoPoint )
{
continue;
break;
}
QgsPointXY layerInfoPoint = mapSettings.mapToLayerCoordinates( currentLayer, *( infoPoint.get() ) );
if ( !featureInfoFromRasterLayer( rasterLayer, mapSettings, &layerInfoPoint, result, layerElement, version, infoFormat ) )
QgsPointXY layerInfoPoint = mapSettings.mapToLayerCoordinates( layer, *( infoPoint.get() ) );
if ( !featureInfoFromRasterLayer( rasterLayer, mapSettings, &layerInfoPoint, result, layerElement, version, mWmsParameters.infoFormatAsString() ) )
{
continue;
break;
}
break;
}
}
else
{
continue;
}
break;
}
}
}
if ( featuresRect )
{
if ( infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml" ) ) )
if ( infoFormat == QgsWmsParameters::Format::GML )
{
QDomElement bBoxElem = result.createElement( QStringLiteral( "gml:boundedBy" ) );
QDomElement boxElem;
int gmlVersion = infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml/3" ) ) ? 3 : 2;
int gmlVersion = mWmsParameters.infoFormatAsString().startsWith( QLatin1String( "application/vnd.ogc.gml/3" ) ) ? 3 : 2;
if ( gmlVersion < 3 )
{
boxElem = QgsOgcUtils::rectangleToGMLBox( featuresRect.get(), result, 8 );
@ -947,16 +951,11 @@ namespace QgsWms
}
}
if ( sia2045 && infoFormat.compare( QLatin1String( "text/xml" ), Qt::CaseInsensitive ) == 0 )
if ( sia2045 && infoFormat == QgsWmsParameters::Format::XML )
{
convertFeatureInfoToSIA2045( result );
}
//force restoration of original filters
filterRestorer.reset();
QgsProject::instance()->removeAllMapLayers();
return result;
}
@ -1288,8 +1287,8 @@ namespace QgsWms
int featureCounter = 0;
layer->updateFields();
const QgsFields &fields = layer->pendingFields();
bool addWktGeometry = mConfigParser && mConfigParser->featureInfoWithWktGeometry();
bool segmentizeWktGeometry = mConfigParser && mConfigParser->segmentizeFeatureInfoWktGeometry();
bool addWktGeometry = QgsServerProjectUtils::wmsFeatureInfoAddWktGeometry( *mProject );
bool segmentizeWktGeometry = QgsServerProjectUtils::wmsFeatureInfoSegmentizeWktGeometry( *mProject );
const QSet<QString> &excludedAttributes = layer->excludeAttributesWms();
QgsFeatureRequest fReq;
@ -1385,17 +1384,13 @@ namespace QgsWms
outputCrs = mapSettings.destinationCrs();
}
if ( infoFormat == QLatin1String( "application/vnd.ogc.gml" ) )
if ( mWmsParameters.infoFormat() == QgsWmsParameters::Format::GML )
{
bool withGeom = layer->wkbType() != QgsWkbTypes::NoGeometry && addWktGeometry;
int version = infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml/3" ) ) ? 3 : 2;
QString typeName = layer->name();
if ( mConfigParser && mConfigParser->useLayerIds() )
typeName = layer->id();
else if ( !layer->shortName().isEmpty() )
typeName = layer->shortName();
int gmlVersion = infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml/3" ) ) ? 3 : 2;
QString typeName = layerNickname( *layer );
QDomElement elem = createFeatureGML(
&feature, layer, infoDocument, outputCrs, mapSettings, typeName, withGeom, version
&feature, layer, infoDocument, outputCrs, mapSettings, typeName, withGeom, gmlVersion
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, &attributes
#endif
@ -1453,14 +1448,14 @@ namespace QgsWms
}
//append feature bounding box to feature info xml
if ( layer->wkbType() != QgsWkbTypes::NoGeometry && hasGeometry && mConfigParser )
if ( layer->wkbType() != QgsWkbTypes::NoGeometry && hasGeometry )
{
QDomElement bBoxElem = infoDocument.createElement( QStringLiteral( "BoundingBox" ) );
bBoxElem.setAttribute( version == QLatin1String( "1.1.1" ) ? "SRS" : "CRS", outputCrs.authid() );
bBoxElem.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( box.xMinimum(), getWMSPrecision( 8 ) ) );
bBoxElem.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( box.xMaximum(), getWMSPrecision( 8 ) ) );
bBoxElem.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( box.yMinimum(), getWMSPrecision( 8 ) ) );
bBoxElem.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( box.yMaximum(), getWMSPrecision( 8 ) ) );
bBoxElem.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( box.xMinimum(), getWMSPrecision() ) );
bBoxElem.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( box.xMaximum(), getWMSPrecision() ) );
bBoxElem.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( box.yMinimum(), getWMSPrecision() ) );
bBoxElem.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( box.yMaximum(), getWMSPrecision() ) );
featureElement.appendChild( bBoxElem );
}
@ -1491,7 +1486,7 @@ namespace QgsWms
}
QDomElement geometryElement = infoDocument.createElement( QStringLiteral( "Attribute" ) );
geometryElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "geometry" ) );
geometryElement.setAttribute( QStringLiteral( "value" ), geom.exportToWkt( getWMSPrecision( 8 ) ) );
geometryElement.setAttribute( QStringLiteral( "value" ), geom.exportToWkt( getWMSPrecision() ) );
geometryElement.setAttribute( QStringLiteral( "type" ), QStringLiteral( "derived" ) );
featureElement.appendChild( geometryElement );
}
@ -1540,7 +1535,7 @@ namespace QgsWms
attributes = layer->dataProvider()->identify( *infoPoint, QgsRaster::IdentifyFormatValue, mapSettings.extent(), mapSettings.outputSize().width(), mapSettings.outputSize().height() ).results();
}
if ( infoFormat == QLatin1String( "application/vnd.ogc.gml" ) )
if ( mWmsParameters.infoFormat() == QgsWmsParameters::Format::GML )
{
QgsFeature feature;
QgsFields fields;
@ -1554,14 +1549,10 @@ namespace QgsWms
feature.setFields( fields );
QgsCoordinateReferenceSystem layerCrs = layer->crs();
int version = infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml/3" ) ) ? 3 : 2;
QString typeName = layer->name();
if ( mConfigParser && mConfigParser->useLayerIds() )
typeName = layer->id();
else if ( !layer->shortName().isEmpty() )
typeName = layer->shortName();
int gmlVersion = infoFormat.startsWith( QLatin1String( "application/vnd.ogc.gml/3" ) ) ? 3 : 2;
QString typeName = layerNickname( *layer );
QDomElement elem = createFeatureGML(
&feature, nullptr, infoDocument, layerCrs, mapSettings, typeName, false, version, nullptr );
&feature, nullptr, infoDocument, layerCrs, mapSettings, typeName, false, gmlVersion, nullptr );
layerElement.appendChild( elem );
}
else
@ -2263,11 +2254,11 @@ namespace QgsWms
QDomElement boxElem;
if ( version < 3 )
{
boxElem = QgsOgcUtils::rectangleToGMLBox( &box, doc, 8 );
boxElem = QgsOgcUtils::rectangleToGMLBox( &box, doc, getWMSPrecision() );
}
else
{
boxElem = QgsOgcUtils::rectangleToGMLEnvelope( &box, doc, 8 );
boxElem = QgsOgcUtils::rectangleToGMLEnvelope( &box, doc, getWMSPrecision() );
}
if ( crs.isValid() )
@ -2291,11 +2282,11 @@ namespace QgsWms
QDomElement gmlElem;
if ( version < 3 )
{
gmlElem = QgsOgcUtils::geometryToGML( geom, doc, 8 );
gmlElem = QgsOgcUtils::geometryToGML( geom, doc, getWMSPrecision() );
}
else
{
gmlElem = QgsOgcUtils::geometryToGML( geom, doc, QStringLiteral( "GML3" ), 8 );
gmlElem = QgsOgcUtils::geometryToGML( geom, doc, QStringLiteral( "GML3" ), getWMSPrecision() );
}
if ( !gmlElem.isNull() )
@ -2388,26 +2379,17 @@ namespace QgsWms
return imageQuality;
}
int QgsRenderer::getWMSPrecision( int defaultValue = 8 ) const
int QgsRenderer::getWMSPrecision() const
{
// First taken from QGIS project
int WMSPrecision = mConfigParser->wmsPrecision();
// First taken from QGIS project and the default value is 6
int WMSPrecision = QgsServerProjectUtils::wmsFeatureInfoPrecision( *mProject );
// Then checks if a parameter is given, if so use it instead
if ( mParameters.contains( QStringLiteral( "WMS_PRECISION" ) ) )
{
bool conversionSuccess;
int WMSPrecisionParameter;
WMSPrecisionParameter = mParameters[ QStringLiteral( "WMS_PRECISION" )].toInt( &conversionSuccess );
if ( conversionSuccess )
{
WMSPrecision = WMSPrecisionParameter;
}
}
if ( WMSPrecision == -1 )
{
WMSPrecision = defaultValue;
}
int WMSPrecisionParameter = mWmsParameters.wmsPrecisionAsInt();
if ( WMSPrecisionParameter > -1 )
return WMSPrecisionParameter;
else
return WMSPrecision;
}

View File

@ -334,7 +334,7 @@ namespace QgsWms
int getImageQuality() const;
//! Return precision to use for GetFeatureInfo request
int getWMSPrecision( int defaultValue ) const;
int getWMSPrecision() const;
};

View File

@ -453,6 +453,33 @@ class TestQgsServerAccessControl(unittest.TestCase):
str(response).find("<qgs:color>red</qgs:color>") != -1, # spellok
"No color in result of GetFeatureInfo\n%s" % response)
response, headers = self._get_restricted(query_string)
self.assertEqual(
headers.get("Content-Type"), "text/xml; charset=utf-8",
"Content type for GetFeatureInfo is wrong: %s" % headers.get("Content-Type"))
self.assertTrue(
str(response).find('<ServiceException code="Security">') != -1,
"Not allowed do a GetFeatureInfo on Country"
)
query_string = "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetFeatureInfo",
"LAYERS": "Hello",
"QUERY_LAYERS": "Hello",
"STYLES": "",
"FORMAT": "image/png",
"BBOX": "-16817707,-6318936.5,5696513,16195283.5",
"HEIGHT": "500",
"WIDTH": "500",
"SRS": "EPSG:3857",
"FEATURE_COUNT": "10",
"INFO_FORMAT": "application/vnd.ogc.gml",
"X": "56",
"Y": "144"
}.items())])
response, headers = self._get_restricted(query_string)
self.assertTrue(
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
@ -1053,6 +1080,33 @@ class TestQgsServerAccessControl(unittest.TestCase):
str(response).find("<qgs:pk>1</qgs:pk>") != -1,
"No good result in GetFeatureInfo Hello/1\n%s" % response)
response, headers = self._get_restricted(query_string)
self.assertEqual(
headers.get("Content-Type"), "text/xml; charset=utf-8",
"Content type for GetFeatureInfo is wrong: %s" % headers.get("Content-Type"))
self.assertTrue(
str(response).find('<ServiceException code="Security">') != -1,
"Not allowed do a GetFeatureInfo on Country"
)
query_string = "&".join(["%s=%s" % i for i in list({
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetFeatureInfo",
"LAYERS": "Hello_SubsetString",
"QUERY_LAYERS": "Hello_SubsetString",
"STYLES": "",
"FORMAT": "image/png",
"BBOX": "-16817707,-6318936.5,5696513,16195283.5",
"HEIGHT": "500",
"WIDTH": "500",
"SRS": "EPSG:3857",
"FEATURE_COUNT": "10",
"INFO_FORMAT": "application/vnd.ogc.gml",
"X": "56",
"Y": "144",
"MAP": urllib.parse.quote(self.projectPath)
}.items())])
response, headers = self._get_restricted(query_string)
self.assertTrue(
str(response).find("<qgs:pk>") != -1,

View File

@ -69,7 +69,16 @@ class TestQgsServerWMS(QgsServerTestBase):
for request in ('GetCapabilities', 'GetProjectSettings', 'GetContext'):
self.wms_request_compare(request)
# Test getfeatureinfo response
# Test getfeatureinfo response xml (default info_format)
self.wms_request_compare('GetFeatureInfo',
'&layers=testlayer%20%C3%A8%C3%A9&styles=&' +
'info_format=text%2Fxml&transparent=true&' +
'width=600&height=400&srs=EPSG%3A3857&bbox=913190.6389747962%2C' +
'5606005.488876367%2C913235.426296057%2C5606035.347090538&' +
'query_layers=testlayer%20%C3%A8%C3%A9&X=190&Y=320',
'wms_getfeatureinfo-text-xml')
# Test getfeatureinfo response html
self.wms_request_compare('GetFeatureInfo',
'&layers=testlayer%20%C3%A8%C3%A9&styles=&' +
'info_format=text%2Fhtml&transparent=true&' +
@ -78,10 +87,10 @@ class TestQgsServerWMS(QgsServerTestBase):
'query_layers=testlayer%20%C3%A8%C3%A9&X=190&Y=320',
'wms_getfeatureinfo-text-html')
# Test getfeatureinfo default info_format
# Test getfeatureinfo response text
self.wms_request_compare('GetFeatureInfo',
'&layers=testlayer%20%C3%A8%C3%A9&styles=&' +
'transparent=true&' +
'info_format=text%2Fplain&transparent=true&' +
'width=600&height=400&srs=EPSG%3A3857&bbox=913190.6389747962%2C' +
'5606005.488876367%2C913235.426296057%2C5606035.347090538&' +
'query_layers=testlayer%20%C3%A8%C3%A9&X=190&Y=320',

View File

@ -0,0 +1,14 @@
*****
Content-Type: text/xml; charset=utf-8
<GetFeatureInfoResponse>
<Layer name="testlayer èé">
<Feature id="2">
<Attribute value="3" name="id"/>
<Attribute value="three" name="name"/>
<Attribute value="three èé↓" name="utf8nameè"/>
<BoundingBox maxy="5606011.4565" maxx="913204.9128" miny="5606011.4565" CRS="EPSG:3857" minx="913204.9128"/>
<Attribute type="derived" value="Point (913204.9128 5606011.4565)" name="geometry"/>
</Feature>
</Layer>
</GetFeatureInfoResponse>