Provider

In your Koop server file, the provider must be registered with the Koop instance before the it begins listening.

const Koop = require('koop')
const koop = new Koop()
const provider = require('<provider-npm-package or local-path>')
koop.register(provider, { /* provider options */ })
koop.server.listen(80)
Figure 1. Example of a Koop instance registering a provider.

Options

The provider registration options are summarized below, followed by detailed descriptions and usage examples:

name type description
name String Namespace replacement for the registered provider
before Function A transformation function that is executed before the provider’s getData function and can be used to modify the request object
after Function A transformation function that is executed after the provider’s getData function and can be used to modify the request object or the GeoJSON generated by the provider
routePrefix String A prefix for all provider routes

name

Use the name option to change the namespace of the provider routes:

const koop = new Koop()
const socrata = require('@koopjs/provider-socrata')
koop.register(socrata, { name: 'my-provider' })
Figure 2. Use the name option to change the namespace of a registered provider.

In figure 2, we are able to use the name option to register the same Socrata provider with the namespace my-provider. It will generate routes like /my-provider/:host/:id/FeatureServer/:layer/:method rather than the default /koop-provider-socrata/:host/:id/FeatureServer/:layer/:method. Custom namespacing can be useful if you want to register multiple providers of the same type, but with different transformation functions.

before

The before option allows you to add a “transformation” function to the provider call stack. It is useful if you want to use an existing provider but execute a block of code before the provider’s getData method. It can be used to modify the Express request object.

Arguments

name type description
request Object An Express request object. See the Express documentation for more details.
callback Function An error-only callback function. It functions similiar to the Express next function. If no error, fire the callback with no arguments.

An example of using the before transform might be to reject requests for certain resources:

const koop = new Koop()
const socrata = require('@koopjs/provider-socrata')

koop.register(socrata, {
  before: (request, callback) => {
    
    const { params: { id } } = request

    // Reject any requests with id 'xyz'
    if (id === 'xyz') {
      const error = new Error('Forbidden')
      error.code = 403
      return callback(error)
    }
    callback()
  }
})
Figure 3. Example of using a before function to reject specific requests.

The before function can also be used to modify the request objects. In the example below, we use the before function, to replace the outSR parameter is with its WKT equivalent; this allows Koop to successfully reproject the data to the desired output spatial reference:

const koop = new Koop()
const socrata = require('@koopjs/provider-socrata')

koop.register(socrata, {
  before: (request, callback) => {

    const { query: { outSR } } = request

    if (outSR === 2285) req.query.outSR = `PROJCS["NAD83/WashingtonNorth(ftUS)",GEOGCS["NAD83",DATUM["North_American_Datum_1983",SPHEROID["GRS1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6269"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4269"]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["standard_parallel_1",48.73333333333333],PARAMETER["standard_parallel_2",47.5],PARAMETER["latitude_of_origin",47],PARAMETER["central_meridian",-120.8333333333333],PARAMETER["false_easting",1640416.667],PARAMETER["false_northing",0],UNIT["USsurveyfoot",0.3048006096012192,AUTHORITY["EPSG","9003"]],AXIS["X",EAST],AXIS["Y",NORTH],AUTHORITY["EPSG","2285"]]`

    callback()
  }
})
Figure 4. Example of using an before function to assign a WKT to the outSR parameter.

after

The after option allows you to add a “transformation” function to the provider call stack that executes a code block after the provider’s getData method. It can be used to modify the Express request object and / or the provider-generated GeoJSON object.

Arguments

name type description
request Object An Express request object. Contains route and query parameters for use in building the URL to the remote API. See the Express documentation for more details.
geojson Object The GeoJSON generated by the provider’s getData method
callback Function An error-first callback function. If no error, the second argument should be the geojson object.

An example use of the after function is re-projection of non-WGS84 data, since at present, Koop expects all data supplied by a provider to be WGS84. Let’s say you have data stored on Github that has spatial reference NAD83/Washington North (2285). You could use the existing Github provider with an after function to acquire and transform the data to WGS84 so it can be successfully processed by Koop:

const koop = new Koop()
const reproject = require('reproject')
const proj4 = require('proj4')
const github = require('@koopjs/provider-github')

koop.register(github, {
  after: (request, geojson, callback) => {

    const fromSR = `PROJCS["NAD83/WashingtonNorth(ftUS)",GEOGCS["NAD83",DATUM["North_American_Datum_1983",SPHEROID["GRS1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6269"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4269"]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["standard_parallel_1",48.73333333333333],PARAMETER["standard_parallel_2",47.5],PARAMETER["latitude_of_origin",47],PARAMETER["central_meridian",-120.8333333333333],PARAMETER["false_easting",1640416.667],PARAMETER["false_northing",0],UNIT["USsurveyfoot",0.3048006096012192,AUTHORITY["EPSG","9003"]],AXIS["X",EAST],AXIS["Y",NORTH],AUTHORITY["EPSG","2285"]]`

    try {
      const wgs84Data = reproject(fromSR, proj4.wgs84, geojson)
      callback(null, wg484Data)
    } catch (err) {
      callback(err)
    }
  }
})
Figure 5. Example of using an after function to reproject non-WGS84 data.

Note that like the before function, the after option can be useful for modifying the request object.

routePrefix

If needed, you can add a prefix to all of a registered provider’s routes. For example, if you wanted the fragment /api/v1 prepended to you github provider routes you could register the provider like this:

const provider = require('@koopjs/provider-github')
koop.register(provider, { routePrefix: '/api/v1' })

which results in routes like:

/api/v1/github/:id/FeatureServer

Plugin registration order

The order in which you register plugins can affect functionality. The key points are:

  • Provider data will only be accessible from output-plugin routes if the provider is registered after the output-plugin
  • Provider data will only be secured by an authorization plugin if the provider is registered after the authorization-plugin.

You can therefore micro-manage provider accessibility by adjusting the registration order of various plugins.

Koop CLI

If you are using the Koop CLI, adding a new provider to you Koop application is easy:

> koop add provider <provider-plugin-package-or-path>

See the Koop CLI documentation for additional options and details.


Improve this page