whosonfirst / go-whosonfirst-spatial-www

Opinionated web application for the go-whosonfirst-spatial packages.
BSD 3-Clause "New" or "Revised" License
3 stars 0 forks source link
golang http whosonfirst whosonfirst-spatial

go-whosonfirst-spatial-www

Opinionated web application for the go-whosonfirst-spatial packages.

Documentation

Documentation is incomplete at this time.

Example

package main

import (
    _ "github.com/whosonfirst/go-reader-cachereader"
)

import (
    "context"
    "github.com/whosonfirst/go-whosonfirst-spatial-www/application/server"
    "log"
)

func main() {

    ctx := context.Background()
    logger := log.Default()

    err := server.Run(ctx, logger)

    if err != nil {
        logger.Fatal(err)
    }
}

The default server implementation uses an in-memory RTree-based spatial index that needs to be populated when the server is started.

There are also server implementations that use SQLite and Protomaps derived spatial databases:

Tools

$> make cli
go build -mod vendor -o bin/server cmd/server/main.go

server

$> ./bin/server -h
  -authenticator-uri string
        A valid sfomuseum/go-http-auth URI. (default "null://")
  -cors-allow-credentials
        Allow HTTP credentials to be included in CORS requests.
  -cors-origin value
        One or more hosts to allow CORS requests from; may be a comma-separated list.
  -custom-placetypes string
        A JSON-encoded string containing custom placetypes defined using the syntax described in the whosonfirst/go-whosonfirst-placetypes repository.
  -enable-cors
        Enable CORS headers for data-related and API handlers.
  -enable-custom-placetypes
        Enable wof:placetype values that are not explicitly defined in the whosonfirst/go-whosonfirst-placetypes repository.
  -enable-geojson
        Enable GeoJSON output for point-in-polygon API calls.
  -enable-gzip
        Enable gzip-encoding for data-related and API handlers.
  -enable-www
        Enable the interactive /debug endpoint to query points and display results.
  -is-wof
        Input data is WOF-flavoured GeoJSON. (Pass a value of '0' or 'false' if you need to index non-WOF documents. (default true)
  -iterator-uri string
        A valid whosonfirst/go-whosonfirst-iterate/v2 URI. Supported schemes are: directory://, featurecollection://, file://, filelist://, geojsonl://, null://, repo://. (default "repo://")
  -leaflet-initial-latitude float
        The initial latitude for map views to use. (default 37.616906)
  -leaflet-initial-longitude float
        The initial longitude for map views to use. (default -122.386665)
  -leaflet-initial-zoom int
        The initial zoom level for map views to use. (default 14)
  -leaflet-max-bounds string
        An optional comma-separated bounding box ({MINX},{MINY},{MAXX},{MAXY}) to set the boundary for map views.
  -log-timings
        Emit timing metrics to the application's logger
  -map-provider-uri string
        A valid aaronland/go-http-maps/provider URI. (default "leaflet://?leaflet-tile-url=https://tile.openstreetmap.org/{z}/{x}/{y}.png")
  -path-api string
        The root URL for all API handlers (default "/api")
  -path-data string
        The URL for data (GeoJSON) handler (default "/data")
  -path-ping string
        The URL for the ping (health check) handler (default "/health/ping")
  -path-pip string
        The URL for the point in polygon web handler (default "/point-in-polygon")
  -path-prefix string
        Prepend this prefix to all assets (but not HTTP handlers). This is mostly for API Gateway integrations.
  -properties-reader-uri string
        A valid whosonfirst/go-reader.Reader URI. Available options are: [cachereader:// fs:// null:// repo:// stdin://]. If the value is {spatial-database-uri} then the value of the '-spatial-database-uri' implements the reader.Reader interface and will be used.
  -server-uri string
        A valid aaronland/go-http-server URI. (default "http://localhost:8080")
  -spatial-database-uri string
        A valid whosonfirst/go-whosonfirst-spatial/data.SpatialDatabase URI. options are: [rtree://] (default "rtree://")

For example:

$> bin/server \
    -spatial-database-uri 'rtree:///?strict=false' \
    -enable-www \   
    /usr/local/data/sfomuseum-data-architecture

11:44:31.902988 [main][index] ERROR 1159157931 failed indexing, (rtreego: improper distance). Strict mode is disabled, so skipping.
11:44:32.073804 [main] STATUS finished indexing in 744.717822ms

When you visit http://localhost:8080 in your web browser you should see something like this:

If you don't need, or want, to expose a user-facing interface simply remove the -enable-www and -nextzen-apikey flags. For example:

$> bin/server \
    -enable-geojson \
    -spatial-database-uri 'rtree:///?strict=false' \
    /usr/local/data/sfomuseum-data-architecture

And then to query the point-in-polygon API you would do something like this:

$> curl -XPOST http://localhost:8080/api/point-in-polygon -d '{"latitude": 37.61701894316063, "longitude": -122.3866653442383}'

{
  "places": [
    {
      "wof:id": 1360665043,
      "wof:parent_id": -1,
      "wof:name": "Central Parking Garage",
      "wof:placetype": "wing",
      "wof:country": "US",
      "wof:repo": "sfomuseum-data-architecture",
      "wof:path": "136/066/504/3/1360665043.geojson",
      "wof:superseded_by": [],
      "wof:supersedes": [
        1360665035
      ],
      "mz:uri": "https://data.whosonfirst.org/136/066/504/3/1360665043.geojson",
      "mz:latitude": 37.616332,
      "mz:longitude": -122.386047,
      "mz:min_latitude": 37.61498599208708,
      "mz:min_longitude": -122.38779093748578,
      "mz:max_latitude": 37.61767331604971,
      "mz:max_longitude": -122.38429192207244,
      "mz:is_current": 0,
      "mz:is_ceased": 1,
      "mz:is_deprecated": 0,
      "mz:is_superseded": 0,
      "mz:is_superseding": 1,
      "wof:lastmodified": 1547232156
    }
    ... and so on
}    

By default, results are returned as a list of "standard places response" (SPR) elements. You can also return results as a GeoJSON FeatureCollection by including a format=geojson query parameter. For example:

$> curl -H 'Accept: application/geo+json' -XPOST http://localhost:8080/api/point-in-polygon -d '{"latitude": 37.61701894316063, "longitude": -122.3866653442383}'

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [ ...omitted for the sake of brevity ]
      },
      "properties": {
        "mz:is_ceased": 1,
        "mz:is_current": 0,
        "mz:is_deprecated": 0,
        "mz:is_superseded": 0,
        "mz:is_superseding": 1,
        "mz:latitude": 37.616332,
        "mz:longitude": -122.386047,
        "mz:max_latitude": 37.61767331604971,
        "mz:max_longitude": -122.38429192207244,
        "mz:min_latitude": 37.61498599208708,
        "mz:min_longitude": -122.38779093748578,
        "mz:uri": "https://data.whosonfirst.org/136/066/504/3/1360665043.geojson",
        "wof:country": "US",
        "wof:id": 1360665043,
        "wof:lastmodified": 1547232156,
        "wof:name": "Central Parking Garage",
        "wof:parent_id": -1,
        "wof:path": "136/066/504/3/1360665043.geojson",
        "wof:placetype": "wing",
        "wof:repo": "sfomuseum-data-architecture",
        "wof:superseded_by": [],
        "wof:supersedes": [
          1360665035
        ]
      }
    }
    ... and so on
  ]
}  

Indexing "plain old" GeoJSON

There is early support for indexing "plain old" GeoJSON, as in GeoJSON documents that do not following the naming conventions for properties that Who's On First documents use. It is very likely there are still bugs or subtle gotchas.

For example, here's how we could index and serve a GeoJSON FeatureCollection of building footprints:

$> bin/server
    -spatial-database-uri 'rtree:///?strict=false' \
    -iterator-uri featurecollection:// \
    /usr/local/data/footprint.geojson

And then:

$> curl -s -XPOST 'http://localhost:8080/api/point-in-polygon '{"latitude": 37.61686957521345, "longitude": -122.3903158758416}' \

| jq '.["places"][]["spr:id"]'

"1014"
"1031"
"1015"
"1026"

Support for returning results in the properties or geojson format is not available for "plain old" GeoJSON records at this time.

See also