In this recipe, you implemented WMS and WFS services for a PostGIS layer using the MapServer open source web-mapping engine. WMS and WFS are the two core concepts to consider when you want to develop a web GIS that is interoperable across many organizations. Open Geospatial Consortium (OGC) defined these two standards (and many others) to make web-mapping services exposed in an open, standard way. This way these services can be used by different applications; for example, you have seen in this recipe that a GIS Desktop tool such as QGIS can browse and query those services because it understands these OGC standards (you can get exactly the same results with other tools, such as gvSIG, uDig, OpenJUMP, and ArcGIS Desktop, among others). In the same way, Javascript API libraries, most notably OpenLayers and Leaflet (you will be using these in the other recipes in this chapter), can use these services in a standard way to provide web-mapping features to web applications.
WMS is a service that is used to generate the maps to be displayed by clients. Those maps are generated using image formats, such as PNG, JPEG, and many others. Some of the most typical WMS requests are as follows:
- GetCapabilities: This offers an overview of the services offered by WMS, particularly a list of the available layers and some of the details of each layer (layer extent, coordinate reference systems, URI of the data, and so on).
- GetMap: This returns a map image representing one or more layers for a specified extent and spatial reference, in a specified image file format and size.
- GetFeatureInfo: This is an optional request by WMS that returns, in different formats, the attribute values for the features of a given point in the map. You have seen how to customize the response by introducing a template file that must be set in the mapfile.
WFS provides a convenient, standard way to access the features of a vector layer with a web request. The service response streams to the client the requested features using GML (an XML markup defined by OGC to define geographical features).
Some WFS requests are as follows:
- GetCapabilities: This gives a description of the services and layers offered by the WFS service
- GetFeature: This allows the client to get a set of features of a given layer, corresponding to a given criteria
These WMS and WFS requests can be consumed by the client using the HTTP protocol. You have seen how to query and get a response from the client by typing a URL in a browser with several parameters appended to it. As an example, the following WMS GetMap request will return a map image of the layers (using the LAYERS parameter) in a specified format (using the FORMAT parameter), size (using the WIDTH and HEIGHT parameters), extent (using the BBOX parameter), and spatial reference system (using CRS):
http://localhost/cgi-bin/mapserv?map=/var/www/data/countries.map&&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=-26,-111,36,-38&CRS=EPSG:4326&WIDTH=806&HEIGHT=688&LAYERS=countries&STYLES=&FORMAT=image/png
In MapServer, you can create WMS and WFS services in the mapfile using its directives. The mapfile is a text file that is composed of several sections and is the heart of MapServer. In the beginning of the mapfile, it is necessary to define general properties for the map, such as its title, extent, spatial reference, output-image formats, and dimensions to be returned to the user.
Then, it is possible to define which OWS (OGC web services such as WMS, WFS, and WCS) requests to expose.
Then there is the main section of the mapfile, where the layers are defined (every layer is defined in the LAYER directive). You have seen how to define a PostGIS layer. It is necessary to define its connection information (database, user, password, and so on), the SQL definition in the database (it is possible to use just a PostGIS table name, but you could eventually use a query to define the set of features and attributes defining the layer), the geometric type, and the projection.
A whole directive (CLASS) is used to define how the layer features will be rendered. You may use different classes, as you did in this recipe, to render features differently, based on an attribute defined with the CLASSITEM setting. In this recipe, you defined three different classes, each representing a population class, using different colors.