7.4 Geographic web services

In an effort to standardize web APIs for accessing spatial data, the Open Geospatial Consortium (OGC) has created a number of specifications for web services (collectively known as OWS, which is short for OGC Web Services).These specifications include the Web Feature Service (WFS), Web Map Service (WMS), Web Map Tile Service (WMTS), the Web Coverage Service (WCS) and even a Wep Processing Service (WPS).Map servers such as PostGIS have adopted these protocols, leading to standardization of queries:Like other web APIs, OWS APIs use a ‘base URL’ and a ‘query string’ proceding a ? to request data.

There are many requests that can be made to a OWS service.One of the most fundamental is getCapabilities, demonstrated with the httr package to show how API queries can be constructed and dispatched, in this case to discover the capabilities of a service providing run by the Food and Agriculture Organization of the United Nations (FAO):

  1. base_url = "http://www.fao.org/figis/geoserver/wfs"
  2. q = list(request = "GetCapabilities")
  3. res = httr::GET(url = base_url, query = q)
  4. res$url
  5. #> [1] "http://www.fao.org/figis/geoserver/wfs?request=GetCapabilities"

The above code chunk demonstrates how API requests can be constructed programmatically with the GET() function, which takes a base URL and a list of query parameters which can easily be extended.The result of the request is saved in res, an object of class response defined in the httr package, which is a list containing information of the request, including the URL.As can be seen by executing browseURL(res$url), the results can also be read directly in a browser.One way of extracting the contents of the request is as follows:

  1. txt = httr::content(res, "text")
  2. xml = xml2::read_xml(txt)
  1. #> {xml_document} ...
  2. #> [1] <ows:ServiceIdentification>\n <ows:Title>GeoServer WFS...
  3. #> [2] <ows:ServiceProvider>\n <ows:ProviderName>Food and Agr...
  4. #> ...

Data can be downloaded from WFS services with the GetFeature request and a specific typeName (as illustrated in the code chunk below).

Available names differ depending on the accessed web feature service.One can extract them programmatically using web technologies (Nolan and Lang 2014) or scrolling manually through the contents of the GetCapabilities output in a browser.

  1. qf = list(request = "GetFeature", typeName = "area:FAO_AREAS")
  2. file = tempfile(fileext = ".gml")
  3. httr::GET(url = base_url, query = qf, httr::write_disk(file))
  4. fao_areas = sf::read_sf(file)

Note the use of write_disc() to ensure that the results are written to disk rather than loaded into memory, allowing them to be imported with sf.This example shows how to gain low-level access to web services using httr, which can be useful for understanding how web services work.For many everyday tasks, however, a higher-level interface may be more appropriate, and a number of R packages, and tutorials, have been developed precisely for this purpose.

Packages ows4R, rwfs and sos4R have been developed for working with OWS services in general, WFS and the sensor observation service (SOS) respectively.As of October 2018, only ows4R is on CRAN.The package’s basic functionality is demonstrated below, in commands that get all FAO_AREAS as we did in the previous code chunk:32

  1. library(ows4R)
  2. wfs = WFSClient$new("http://www.fao.org/figis/geoserver/wfs",
  3. serviceVersion = "1.0.0", logger = "INFO")
  4. fao_areas = wfs$getFeatures("area:FAO_AREAS")

There is much more to learn about web services and much potential for development of R-OWS interfaces, an active area of development.For further information on the topic, we recommend examples from European Centre for Medium-Range Weather Forecasts (ECMWF) services at github.com/OpenDataHack and reading-up on OCG Web Services at opengeospatial.org.