[GIS] Use Geoserver geojson in Leaflet

geojsongeoserverleafletwfs

I am trying to load a GeoJSON layer from my GeoServer WFS and have followed the many question responses but still cannot get it to work.

If i enter the url into a browser the GeoJSON appears with all the data, but the layer will not load in a leaflet map.

I also receive this error in the Google Chrome console:XMLHttpRequest cannot load http://localhost:8080/geoserver/IT_Demo/ows?service=WFS&version=1.0.0&reque…_Demo:states&outputFormat=application/json&format_options=callback:getJson. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'file://' is therefore not allowed access.

Any ideas what may be wrong with my code?

<!DOCTYPE html>
<html>
<head>
  <title>A Leaflet map!</title>
  <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>
  <script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
  <script src="https://code.jquery.com/jquery-2.1.3.js"></script>
  <style>
    #map{ height: 100% }
  </style>
</head>
<body>
  <div id="map"></div>
 <script>
  // initialize the map
  var map = L.map('map').setView([40.7498, -73.999], 13);

  // load a tile layer
  var streets = L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=TOKEN', {
        maxZoom: 18,
        attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' +
            '<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
            'Imagery © <a href="http://mapbox.com">Mapbox</a>',
        id: 'mapbox.light'
    }).addTo(map);

var geojsonLayer = new L.GeoJSON();

function handleJson(data) {
  console.log(data)
  geojsonLayer.addData(data); 
}

$.ajax({
  url : "http://localhost:8080/geoserver/IT_Demo/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=IT_Demo:states&outputFormat=json&format_options=callback:getJson",
  dataType : 'jsonp',
  jsonpCallback: 'getJson',
  success: handleJson
});

map.addLayer(geojsonLayer);

  </script>
</body>
</html>

Best Answer

I would think your issue is the prohibited CORS (cross-origin resource sharing, see https://en.wikipedia.org/wiki/Cross-origin_resource_sharing).

You have to deal with cross-origin resources, because to the browser, you're using a resource from a different URL than your own, even if both localhost:8080 (the geoserver) and localhost:80 (the python simplehttpserver) are running on the same machine.

You need to enable CORS on the underlying servlet container, see http://suite.opengeo.org/docs/latest/sysadmin/cors/index.html for jetty and http://enable-cors.org/server_tomcat.html for tomcat.

It boils down to adding a few lines to the web.xml file akin to

<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>CorsFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

...but read the full documentation for the security implications (with the listed setup anyone on the web will be able to import/use the resources from your geoserver).