pmtiles

package module
v1.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 29, 2023 License: BSD-3-Clause Imports: 0 Imported by: 0

README

go-sfomuseum-pmtiles

Opinionated SFO Museum package for working with Protomaps (v3) databases.

Documentation

Go Reference

Tools

$> make cli
go build -ldflags="-s -w" -mod vendor -o bin/server cmd/server/main.go 
server
$> ./bin/server -h
Launch a web server for search Protomaps (v3) tile requests.
Usage:
	 ./bin/server [options]
Valid options are:
  -cache-size int
    	Cache size in megabytes for tiles. (default 64)
  -cors-allow-credentials
    	Enable support for credentials in CORS requests.
  -cors-debug
    	Enable debugging in the rs/cors package.
  -cors-origin value
    	One or more comma-separated lists of hosts to enable CORS support for. If the -enable-cors flag is set and no -cors-origin flags have been assigned then CORS support will be enabled for '*'.
  -enable-cors
    	Enable CORS support.
  -enable-example
    	Enable an example map application at /example for testing database files. 
  -example-database string
    	The name of the database to use in the example map application. Note that this value should be the name of the database without its extension.
  -example-latitude float
    	The starting latitude for the example map application. (default 37.6143)
  -example-longitude float
    	The starting longitude for the example map application. (default -122.3828)
  -example-zoom int
    	The starting zoom for the example map application. (default 13)
  -public-hostname string
    	Public hostname of tile endpoint.
  -server-uri string
    	A valid aaronland/go-http-server URI. (default "http://localhost:8080")
  -strip-prefix string
    	An optional string prefix to strip from HTTP request for tiles.
  -tile-path string
    	A valid gocloud.dev/blob bucket URI where .pmtiles databases are stored.
  -tile-prefix string
    	A prefix to append when fetching tiles.
Examples
localhost

For example:

$> ./bin/server \
	-tile-path file:///usr/local/sfomuseum/tiles \
	-enable-example \
	-example-database sfo

2022/10/11 14:54:31 Listening for requests on http://localhost:8080
2022/10/11 14:54:37 fetching sfo 0-16384
2022/10/11 14:54:37 fetched sfo 0-0
2022/10/11 14:54:37 [200] served /sfo/11/328/792.mvt in 3.025132ms
2022/10/11 14:54:37 [200] served /sfo/11/327/792.mvt in 4.38898ms
2022/10/11 14:54:38 [200] served /sfo/12/656/1585.mvt in 322.892µs
2022/10/11 14:54:38 [200] served /sfo/12/654/1585.mvt in 7.676399ms
2022/10/11 14:54:38 [200] served /sfo/12/655/1585.mvt in 7.976492ms
2022/10/11 14:54:39 [200] served /sfo/13/1311/3170.mvt in 9.82361ms
...and so on

S3

Or, with a PMTiles database hosted on S3:

$> bin/server \
	-tile-path 's3blob://{BUCKET}?region={REGION}&credentials={CREDENTIALS}' \
	-enable-example \
	-example-database \
	sfomuseum

static/embedded

It is also possible to use a PMTiles database embedded in an fs.FS instance. This is functionality specific to the go-sfomuseum-pmtiles package rather than protomaps/go-pmtiles itself.

In order to use an embedded PMTiles database you need to explictly define a fs.FS instance where databases are stored. The contents of the fs.FS filesystem are copied to a gocloud.dev/blob.Bucket at runtime which is then used to initialize a go-pmtiles.Bucket instance for serving tiles.

For example:

package main

import (
	_ "gocloud.dev/blob/fileblob"	
	_ "gocloud.dev/blob/memblob"
)

import (
	"context"
	"log"

	app "github.com/sfomuseum/go-sfomuseum-pmtiles/application/server"
	"github.com/sfomuseum/go-sfomuseum-pmtiles/static"
)

func main() {

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

	flag_fs := app.DefaultFlagSet()

	opts, _ := app.RunOptionsWithFlagSet(flag_fs, logger)
	opts.PMTilesFS = static.FS

	app.RunWithOptions(ctx, opts)
}

Error handling omitted for the sake of brevity.

This functionality is not suitable for very large PMTiles databases but might be useful for applications with small, bounded, maps. To view a working example, run the debug-static Makefile target and then open a web browser at http://localhost:8080/example.

$> make debug-static
go run -mod readonly cmd/server-static/main.go \
		-enable-example \
		-example-database sfo \
		-tile-path mem://
		
2023/10/13 16:25:33 Listening for requests on http://localhost:8080

Screenhost omitted because it looks the same as the screenshot for local hosting.

The relevant bits here are this:

	opts, _ := app.RunOptionsWithFlagSet(flag_fs, logger)
	opts.PMTilesFS = static.FS

And this:

	-example-database sfo

Which tells the code to load a PMTiles database named "sfo.db" from an embedded filesystem defined in static/static.go. The other relevant flag is:

	-tile-path mem://

Which tells the code to copy the files in the embedded filesystem to a new in-memory gocloud.dev/blob.Bucket instance.

Technically it copies the data to a locally-defined GoCloudBucket instance that wraps the blob.Bucket instance and implements the protomaps/go-pmtiles/pmtiles.Bucket interface. Computers, amirite?

If instead you wanted to copy the embedded filesystem to a local filesystem you would update the -tile-path parameter to specify the relevant "file:///path/to/folder" URI. This might seem counter-intuitive but if used in a frequently-invoked AWS Lambda function context you could take advantage of the fact the function (and its filesystem) will persist across invocations and bundle a PMTiles database that might otherwise be too large to bundle in memory without the need to setup and configure an S3 bucket to store the database(s) you are serving.

The point is not that you should do it this way. The point is that there are circumstances where you might want or need to serve tiles from an embedded filesystem and now you can.

By default the server-static tool supports cloning embedded filesystems to memory or a local filesystem. If you want to copy filesystems to other blob.Bucket implementations you will need to clone the code and add the relevent import statements.

AWS
Lambda (with Function URL integration)
$> make lambda
if test -f bootstrap; then rm -f bootstrap; fi
if test -f server.zip; then rm -f server.zip; fi
GOARCH=arm64 GOOS=linux go build -mod readonly -ldflags="-s -w" -tags lambda.norpc -o bootstrap cmd/server/main.go
zip server.zip bootstrap
  adding: bootstrap (deflated 71%)
rm -f bootstrap

The following environment variables should be configured for use as a Lambda function:

Name Value Notes
SFOMUSEUM_SERVER_URI functionurl://?binary_type=application/x-protobuf Note the ?binary_type parameter. This is important.
SFOMUSEUM_TILE_PATH s3blob://{BUCKET}?prefix={PREFIX}&region={REGION}&credentials=iam: Note the s3blob:// scheme which is different that the default s3:// scheme and supports specifying AWS credentials using the ?credentials parameter.

The rules for assigning flags from envinronment variables are:

  • Replace all instances of "-" in a flag name with "_".
  • Uppercase the flag name.
  • Prepend the new string with "SFOMUSEUM_".

For example the -server-uri flag becomes the SFOMUSEUM_SERVER_URI environment variable.

You will need to configure your Lambda functions with an IAM role that allows the function to read data from the S3 bucket named {BUCKET}.

How you configure access to your Lambda function URL as well as any CORS details is left up to you.

Lambda (with API Gateway proxy integration)
$> make lambda
if test -f bootstrap; then rm -f bootstrap; fi
if test -f server.zip; then rm -f server.zip; fi
GOARCH=arm64 GOOS=linux go build -mod readonly -ldflags="-s -w" -tags lambda.norpc -o bootstrap cmd/server/main.go
zip server.zip bootstrap
  adding: bootstrap (deflated 71%)
rm -f bootstrap

The following environment variables should be configured for use as a Lambda function:

Name Value Notes
SFOMUSEUM_SERVER_URI lambda://?binary_type=application/x-protobuf Note the ?binary_type parameter. This is important.
SFOMUSEUM_TILE_PATH s3blob://{BUCKET}?prefix={PREFIX}&region={REGION}&credentials=iam: Note the s3blob:// scheme which is different that the default s3:// scheme and supports specifying AWS credentials using the ?credentials parameter.
SFOMUSEUM_CORS_ENABLE true

The rules for assigning flags from envinronment variables are:

  • Replace all instances of "-" in a flag name with "_".
  • Uppercase the flag name.
  • Prepend the new string with "SFOMUSEUM_".

For example the -server-uri flag becomes the SFOMUSEUM_SERVER_URI environment variable.

You will need to configure your Lambda functions with an IAM role that allows the function to read data from the S3 bucket named {BUCKET}.

API Gateway
  • Create a new {proxy+} resource on "/".
  • Add a new GET method (on the "/" resource) and point it to your Lambda function.
  • Be sure to add an entry for "application/x-protobuf" in API: {API_NAME} > Settings > Binary Media Types.

See also

Documentation

Overview

Package pmtiles provides opinionated tools specific to SFO Museum for working with Protomaps (v3) databases.

Directories

Path Synopsis
Package application provides code to implement generic applications that may use interfaces for achieving desired functionality without defining specific implementations.
Package application provides code to implement generic applications that may use interfaces for achieving desired functionality without defining specific implementations.
server
Package server implements a web application for serving Protomaps tiles.
Package server implements a web application for serving Protomaps tiles.
cmd
server
server launches a web server for search Protomaps (v3) tile requests.
server launches a web server for search Protomaps (v3) tile requests.
server-static
server-static launches a web server for serving Protomaps (v3) tile requests using an embedded Protomaps database.
server-static launches a web server for serving Protomaps (v3) tile requests using an embedded Protomaps database.
Package example provides an embedded filesystems containing assets for rendering an example map application.
Package example provides an embedded filesystems containing assets for rendering an example map application.
Package http provides methods for creating `net/http.Handler` instances to serve tiles from a Protomaps (v3) database
Package http provides methods for creating `net/http.Handler` instances to serve tiles from a Protomaps (v3) database

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL