I am developing a webmap application using Leaflet + QGIS Server 3.4 on a Debian platform.
I have my HTML/Leaflet page ready, based on this code. Basically, the user has the choice between several tiled layers from Google Maps or OpenStreetMap and a WMS layer served by my QGIS server. The Javascript code is destined to enable popups when the user clicks on the features of the WMS layer. The data of my WMS layer is currently the data from the QGIS Server training tutorial.
It had some troubleshooting to do due to CRS/SRS problems but it seems solved now. I have put everything in the same CRS (EPSG:3857).
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin=""/>
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="
crossorigin=""></script>
</head>
<body>
<div id="searchmap" style="height: 800px; width: 1200px;"></div>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({
onAdd: function (map) {
// Triggered when the layer is added to a map.
// Register a click listener, then do all the upstream WMS things
L.TileLayer.WMS.prototype.onAdd.call(this, map);
map.on('click', this.getFeatureInfo, this);
},
onRemove: function (map) {
// Triggered when the layer is removed from a map.
// Unregister a click listener, then do all the upstream WMS things
L.TileLayer.WMS.prototype.onRemove.call(this, map);
map.off('click', this.getFeatureInfo, this);
},
getFeatureInfo: function (evt) {
// Make an AJAX request to the server and hope for the best
var url = this.getFeatureInfoUrl(evt.latlng),
showResults = L.Util.bind(this.showGetFeatureInfo, this);
$.ajax({
url: url,
success: function (data, status, xhr) {
var err = typeof data === 'string' ? null : data;
showResults(err, evt.latlng, data);
},
error: function (xhr, status, error) {
showResults(error);
}
});
},
getFeatureInfoUrl: function (latlng) {
// Construct a GetFeatureInfo request URL given a point
var point = this._map.latLngToContainerPoint(latlng, this._map.getZoom()),
size = this._map.getSize(),
params = {
request: 'GetFeatureInfo',
service: 'WMS',
srs: this.wmsParams.srs,
styles: this.wmsParams.styles,
transparent: this.wmsParams.transparent,
version: this.wmsParams.version,
format: this.wmsParams.format,
bbox: this._map.getBounds().toBBoxString(),
height: size.y,
width: size.x,
layers: this.wmsParams.layers,
query_layers: this.wmsParams.layers,
info_format: 'text/html'
};
params[params.version === '1.3.0' ? 'i' : 'x'] = point.x;
params[params.version === '1.3.0' ? 'j' : 'y'] = point.y;
return this._url + L.Util.getParamString(params, this._url, true);
},
showGetFeatureInfo: function (err, latlng, content) {
if (err) { console.log(err); return; } // do nothing if there's an error
// Otherwise show the content in a popup, or something.
L.popup({ maxWidth: 800})
.setLatLng(latlng)
.setContent(content)
.openOn(this._map);
}
});
L.tileLayer.betterWms = function (url, options) {
return new L.TileLayer.BetterWMS(url, options);
};
</script>
<script>
// Leaflet map
var mymap = L.map('searchmap', { crs: L.CRS.EPSG3857 }).setView([ 46.0, 3.0 ], 5) ;
// layers definition
var OSM = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1
}),
googleSat = L.tileLayer('http://{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',{
maxZoom: 20,
subdomains:['mt0','mt1','mt2','mt3']
}),
googleStreets = L.tileLayer('http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}',{
maxZoom: 20,
subdomains:['mt0','mt1','mt2','mt3']
}),
googleHybrid = L.tileLayer('http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}',{
maxZoom: 20,
subdomains:['mt0','mt1','mt2','mt3']
}),
googleTerrain = L.tileLayer('http://{s}.google.com/vt/lyrs=p&x={x}&y={y}&z={z}',{
maxZoom: 20,
subdomains:['mt0','mt1','mt2','mt3']
}),
QGISDemo_Continents = L.tileLayer.betterWms('http://qgis.demo/cgi-bin/qgis_mapserv.fcgi?MAP=/home/qgis/projects/project_cantor/sites.qgs',{
layers: 'continents',
service: 'WMS',
srs: 'EPSG:3857',
format: 'image/png',
version: '1.3.0'
});
// base maps
var basemaps = {
"OpenStreetMap": OSM,
"Google Satellite" : googleSat,
"Google Streets": googleStreets,
"Google Hybrid": googleHybrid,
"Google Terrain": googleTerrain,
"QGIS Server demo - Continents": QGISDemo_Continents
};
// user control
L.control.layers(basemaps).addTo(mymap);
// default base map
basemaps.OpenStreetMap.addTo(mymap);
</script>
</body>
</html>
My problem is now with the GetFeatureInfo request done by the Javascript code, which still does not work.
I can see in /var/log/qgis/qgisserver.log the requests processed by QGIS Server and they seem fine now. The GetMap requests are processed fine, but I cannot get the GetFeatureInfo requests to be working. I see nothing of interest in /var/log/apache2/qgis.demo.access.log or /var/log/apache2/qgis.demo.error.log .
Sample logs from /var/log/qgis/qgisserver.log
:
******************** New request ***************
13:08:19 INFO Server[10951]: SERVER_NAMEqgis.demo
13:08:19 INFO Server[10951]: REQUEST_URI/cgi-bin/qgis_mapserv.fcgi?MAP=/home/qgis/projects/project_cantor/sites.qgs&REQUEST=GetFeatureInfo&SERVICE=WMS&cRS=EPSG%3A3857&STYLES=&TRANSPARENT=false&VERSION=1.3.0&FORMAT=image%2Fpng&BBOX=-20.390625000000004%2C25.918526162075153%2C32.34375000000001%2C52.56299503955803&HEIGHT=800&WIDTH=1200&LAYERS=continents&QUERY_LAYERS=continents&INFO_FORMAT=text%2Fhtml&I=590&J=266&FI_POLYGON_TOLERANCE=50
13:08:19 INFO Server[10951]: REMOTE_ADDR127.0.0.1
13:08:19 INFO Server[10951]: HTTP_USER_AGENTMozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36
13:08:19 INFO Server[10951]: BBOX:-20.390625000000004,25.918526162075153,32.34375000000001,52.56299503955803
13:08:19 INFO Server[10951]: CRS:EPSG:3857
13:08:19 INFO Server[10951]: FI_POLYGON_TOLERANCE:50
13:08:19 INFO Server[10951]: FORMAT:image/png
13:08:19 INFO Server[10951]: HEIGHT:800
13:08:19 INFO Server[10951]: I:590
13:08:19 INFO Server[10951]: INFO_FORMAT:text/html
13:08:19 INFO Server[10951]: J:266
13:08:19 INFO Server[10951]: LAYERS:continents
13:08:19 INFO Server[10951]: MAP:/home/qgis/projects/project_cantor/sites.qgs
13:08:19 INFO Server[10951]: QUERY_LAYERS:continents
13:08:19 INFO Server[10951]: REQUEST:GetFeatureInfo
13:08:19 INFO Server[10951]: SERVICE:WMS
13:08:19 INFO Server[10951]: STYLES:
13:08:19 INFO Server[10951]: TRANSPARENT:false
13:08:19 INFO Server[10951]: VERSION:1.3.0
13:08:19 INFO Server[10951]: WIDTH:1200
13:08:19 INFO Server[10951]: WMS Request parameters:
13:08:19 INFO Server[10951]: - CRS : EPSG:3857
13:08:19 INFO Server[10951]: - WIDTH : 1200
13:08:19 INFO Server[10951]: - HEIGHT : 800
13:08:19 INFO Server[10951]: - BBOX : -20.390625000000004,25.918526162075153,32.34375000000001,52.56299503955803
13:08:19 INFO Server[10951]: - LAYERS : continents
13:08:19 INFO Server[10951]: - QUERY_LAYERS : continents
13:08:19 INFO Server[10951]: - FI_POLYGON_TOLERANCE : 50
13:08:19 INFO Server[10951]: - FORMAT : image/png
13:08:19 INFO Server[10951]: - INFO_FORMAT : text/html
13:08:19 INFO Server[10951]: - I : 590
13:08:19 INFO Server[10951]: - J : 266
13:08:19 INFO Server[10951]: - TRANSPARENT : false
13:08:19 INFO Server[10951]: - VERSION : 1.3.0
13:08:19 WARNING [10951]: mapSettings.destinationCrs(): EPSG:3857
13:08:19 WARNING [10951]: mapSettings.extent(): -20.3906250000000036,25.9185261620751533 : 32.3437500000000071,52.5629950395580323
13:08:19 WARNING [10951]: mapSettings width = 1365 height = 689
13:08:19 WARNING [10951]: mapSettings.mapUnitsPerPixel() = 0.0386712
13:08:19 INFO Server[10951]: Request finished in 25 ms
But nothing happens when I click on the map.
Trying to debug, I copied-paste the request URL parameters in a browser to see the response from QGIS Server and make sure if the problem comes from the Javascript in the HTML page or from the QGIS Server response:
http://qgis.demo/cgi-bin/qgis_mapserv.fcgi?MAP=/home/qgis/projects/project_cantor/sites.qgs&REQUEST=GetFeatureInfo&SERVICE=WMS&cRS=EPSG%3A3857&STYLES=&TRANSPARENT=false&VERSION=1.3.0&FORMAT=image%2Fpng&BBOX=-20.390625000000004%2C25.918526162075153%2C32.34375000000001%2C52.56299503955803&HEIGHT=800&WIDTH=1200&LAYERS=continents&QUERY_LAYERS=continents&INFO_FORMAT=text%2Fhtml&I=590&J=266&FI_POLYGON_TOLERANCE=50
The response I get in the browser is an empty HTML table with no rows except the headers. I changed the format to text/xml and also got an empty response:
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<GetFeatureInfoResponse>
<Layer name="continents"/>
</GetFeatureInfoResponse>
So, for a reason I cannot identify, QGIS server does receive the WMS GetFeatureInfo request but returns an empty response.
However, during my previous debugging of the CRS/SRS problems, at some point, I got some non-empty response, albeit with the wrong location (the feature was in Somalia instead of France).
I added manually to the requested URL the parameter FI_POLYGONE_TOLERANCE=500, hoping it would 'catch' some close feature. That did not work.
I am stuck and don't know how to debug further. I have 2 hypothesis:
- The GetFeatureInfo request is pinpointed to an empty location (no feature there), although I can see the features on my HTML/Leaflet page.
- QGIS Server is somehow configured wrongly and returns an empty response.
Any debugging tips?
getFeatureInfo
request is not in the same CRS that you specify. The magic bit is getting EPSG:3857 coordinates from the EPSG:4326 bounding box, see e.g. github.com/Flexberry/Leaflet-WMS/blob/…The GetFeatureInfo request is pinpointed to an empty location (no feature there), although I can see the features on my HTML/Leaflet page.
~ If you do a GetMap request like : qgis.demo/cgi-bin/qgis_mapserv.fcgi?MAP=/home/qgis/projects/… are there any features at 590 pixels down and 266 pixels across?