WFS request in Geoserver using Leafletjs
Tags: geoserver, javascript, leafletjs, wfs
Published: 2021-06-30 04:09:16

WFS stands for Web Feature Services. It will provides the features from the input request. Generally, the GeoJSON output format is used for the visualization of features in leafletjs.

Let's come to the point. In Geoserver, When your data is ready, you can see your WFS layer by following steps;

* Goto the Layer Preview tab

* In your layer preview, Inside all formats dropdown button, select WFS>GeoJson

![WFS request](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mi9sh7camvk86qnfrn60.jpeg)

> **Note:** Make sure you select the vector layer. Your raster layer doesn't contain any options for WFS.

This is how we can see the WFS layer in GeoJSON format. Let's connect this layer in the leaflet. You probably think why we have to send WFS request to the server, The WMS was already there and WMS is also very easy. There are lots of advantages to using WFS instate of using WMS. One of the main advantages is that we can have access to the data properties in WFS whereas WMS is just a single tile image nothing more. The main difference between them is that WFS provides us the vector data analysis and we can make vector analysis whereas WMS is the raster layer. We only handle raster operations. You can find out more information about this request [here](https://gis.stackexchange.com/questions/80948/what-are-the-differences-between-wms-wfs-wcs-wps). 

Browser doesn't let you share the data from cross-origin. You can't get the data if you add the GeoJSON data URL in your code. You can easily fetch the GeoJSON data in `Jsonp` format in GeoServer. To enable the `Jsonp` in your GeoServer you have to follow the following steps;

1. Goto the GeoServer installation disk and then ..\webapps\geoserver\WEB-INF
2. Then open the web.xml file in your code editor
3. Uncomment the following code (code may be in line 40) or if you don't have it write it;

```xml
<context-param>
    <param-name>ENABLE_JSONP</param-name>
    <param-value>true</param-value>
</context-param>
```
4. Save it.

Now you can pass the ajax request to the server to fetch the data. For this write the following code and try to understand this;

```js
//Geoserver Web Feature Service
$.ajax('http://localhost:8080/geoserver/wfs',{
  type: 'GET',
  data: {
    service: 'WFS',
    version: '1.1.0',
    request: 'GetFeature',
    typename: 'workspace:layer_name',
    srsname: 'EPSG:4326',
    outputFormat: 'text/javascript',
    },
  dataType: 'jsonp',
  jsonpCallback:'callback:handleJson',
  jsonp:'format_options'
 });

// the ajax callback function
function handleJson(data) {
    selectedArea = L.geoJson(data).addTo(map);
  map.fitBounds(selectedArea.getBounds());
}
```
This is the ajax get request. I make this simpler to understand. Inside your data section, you have to change the type name to your `workspace:layer_to_display`. Also, you can filter (query) the required data by passing `CQL_FILTER` inside your data section. If I am interested in the data column name as a column and value as a demo then I can filter this data by adding `CQL_FILTER: "column:'demo'"` key-value pair in the data section. Also, don't forget to write `outputFormat: 'text/javascript'` in your code. I already mentioned, why we can't fetch the JSON data. Use `Jsonp` as the dataType and set a callback function `handleJson`.

The `handleJson` a function defined below the ajax call will receive the data from URL and `L.GeoJSON` will handle this data through URL and add this data to the leaflet map. If you want to fit the data in a defined bound, you can set it using `map.fitBounds(selectedArea.getBounds);`. Then you can add the popup feature and style feature of the GeoJSON. `onEachFeature` is used to fetch the properties of the GeoJSON.

Finally, you did it. You made a WFS request to the GeoServer and fetch the required data to the leaflet map. If you want to see full code in just one place, then see the following code;

```html
<html>
  <head>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css">
    <style>
      #map {
        width: 100%;
        height: 500px;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"></script>
  </body>
</html>

<script>
var map = L.map("map").setView([38.45, 70.6], 6);
var osm = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
  attribution:
    '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
//Geoserver Web Feature Service
$.ajax('http://localhost:8080/geoserver/wfs',{
  type: 'GET',
  data: {
    service: 'WFS',
    version: '1.1.0',
    request: 'GetFeature',
    typename: 'workspace:layer_name',
    CQL_FILTER: "column='demo'",
    srsname: 'EPSG:4326',
    outputFormat: 'text/javascript',
    },
  dataType: 'jsonp',
  jsonpCallback:'callback:handleJson',
  jsonp:'format_options'
 });
  //Geojson style file
  var myStyle = {
    'color': 'red'
  }
// the ajax callback function
function handleJson(data) {
    selectedArea = L.geoJson(data, {
      style: myStyle,
      onEachFeature: function(feature, layer) {
        layer.bindPopup(`Name: ${feature.properties.name_of_your_property}`)
      }
    }).addTo(map);
  map.fitBounds(selectedArea.getBounds());
}
</script>
```

Congratulations! Finally you are able to make a WFS request from geoserver in leaflet.