protomaps / go-pmtiles

Single-file executable tool for working with PMTiles archives
https://docs.protomaps.com/pmtiles/cli
BSD 3-Clause "New" or "Revised" License
375 stars 51 forks source link

serve error: 404 path mismatch: archive is type MVT (.mvt) #43

Closed tyrauber closed 1 year ago

tyrauber commented 1 year ago

I spent the weekend trying to get a demo of v3 PMtiles up and running, but ran into an error with my own encoded pmtile.

Here is the pipeline I’ve developed:

osm.pbf -> tilemaker (with openmaptiles config) -> osm.mbtiles -> go_pmtiles -> osm.pmtiles

tilemaker --input hawaii-latest.osm.pbf \
--output hawaii.mbtiles \
--config config-openmaptiles.json \
--process process-openmaptiles.lua
pmtiles hawaii.mbtiles hawaii.pmtiles

This produces the following v3 .pmtile:

$ pmtiles show hawaii.pmtiles 
pmtiles spec version: 3
total size: 14 MB
tile type: Vector Protobuf (MVT)
bounds: -179.848300,10.835750 -137.522800,29.096240
min zoom: 0
max zoom: 14
center: -158.685550,19.965995
center zoom: 7
addressed tiles count: 5189
tile entries count: 5066
tile contents count: 4894
clustered: true
internal compression: 2
tile compression: 2
maxzoom 14
minzoom 0
name Tilemaker to OpenMapTiles schema
type baselayer
vector_layers <object...>
version 3.0
description Tile config based on OpenMapTiles schema
format pbf

Which I serve:

$ pmtiles serve .
2023/02/13 21:25:46 main.go:118: Serving  . on port 8080 with Access-Control-Allow-Origin: 

And then request a pbf over Hawaii with the following url:

http://localhost:8080/hawaii/10/301/384.pbf

The logs print:

2023/02/13 21:26:44 server.go:139: fetching hawaii 0-16384
2023/02/13 21:26:44 server.go:180: fetched hawaii 0-0
2023/02/13 21:26:44 main.go:115: served /hawaii/10/301/384.pbf in 1.64375ms

But in the browser I get a 400 error path mismatch: archive is type MVT (.mvt).

Any idea what that error means? Does the pipeline and process look correct?

Additionally, which frontend codebase is best for testing v3 pmtiles:

wipfli commented 1 year ago

What happens if you call http://localhost:8080/hawaii/10/301/384.mvt in the browser?

wipfli commented 1 year ago

I would recommend to use MapLibre GL JS in the frontend, but I am biased...

bdon commented 1 year ago

@tyrauber that looks correct, you should change the extension you are requesting to .mvt instead of .pbf. We could make either one work, but because many other formats, like fonts and raw OSM, use the .pbf extension I'd prefer to consolidate on .mvt.

I would also recommend MapLibre for your use case. Since you're developing a map based on OpenMapTiles you can find OMT-compatible MapLibre JSON styles at http://github.com/openmaptiles

tyrauber commented 1 year ago

.mtv weirdly produces the same error: path mismatch: archive is type MVT (.mvt)

In the logs

2023/02/14 05:43:59 main.go:115: served /hawaii/10/301/384.mtv in 173.084µs

In the browser:

Request URL: http://localhost:8080/hawaii/10/301/384.mtv
Request Method: GET
Status Code: 400 Bad Request
Remote Address: [::1]:8080
Referrer Policy: strict-origin-when-cross-origin

100%, @wipfli, I am also partial to MapLibre.

@bdon, I believe I am using the OMT-compatible MapLibre JSON style here: tilemaker (with openmaptiles config) for importing. My intention was to use the front-end openmaptiles style with Maplibre.

bdon commented 1 year ago

@tyrauber please double check the extension is .mvt and not .mtv

tyrauber commented 1 year ago

Ha, @bdon, thank you. Too early here. .mvt does resolve the issue. pmtiles serve . --cors="*" in development.

2023/02/14 06:01:19 main.go:115: served /hawaii/10/62/450.mvt in 1.182041ms
2023/02/14 06:01:19 main.go:115: served /hawaii/10/62/449.mvt in 1.713167ms
2023/02/14 06:01:19 main.go:115: served /hawaii/10/61/449.mvt in 176.042µs
2023/02/14 06:01:19 main.go:115: served /hawaii/10/61/450.mvt in 30.25µs
2023/02/14 06:01:19 main.go:115: served /hawaii/10/62/449.mvt in 325.666µs
2023/02/14 06:01:19 main.go:115: served /hawaii/10/62/450.mvt in 124.459µs
2023/02/14 06:01:19 main.go:115: served /hawaii/10/61/449.mvt in 191.167µs
2023/02/14 06:01:19 main.go:115: served /hawaii/10/61/450.mvt in 20.5µs

And, an un-styled map in the browser! Map

Now just to pull in the openmaptiles json with maplibre and I got a demo. :fire:

tyrauber commented 1 year ago

Ok. @bdon, this is very, very cool. Map

MapLibreGL using protomaps/PMTiles/app, with http://localhost:3000/hawaii.pmtiles as the pmtiles. This implementation doesn't use the pmtile server, and handles the /z/x/y/ sourcing on the front-end.

Can you elaborate on when to use pmtiles serve versus serving the pmtile directly as a file and allowing the browser to handle the /z/x/y/ navigation? What is the benefits of one approach versus the other.

bdon commented 1 year ago

pmtiles serve is for niche or backwards-compatibility use cases; if you have a running server and lots of disk to store tiles, you may as well use MBTiles for which plenty of reliable tooling already exists.

The browser decoding use case is designed for simplicity over performance. For faster and edge-cached maps without running a server the official recommendation is CDN deployment: https://protomaps.com/docs/cdn

tyrauber commented 1 year ago

Looks like the serverless CDN implementations here all use the JS code to handle the /z/x/y navigation. Is that correct? For performance both server side and client side, I would think running a cluster of go-pmtiles behind a varnish cache would be far more performant, no? I would assume pmtiles serve performs better than the js implementation.

bdon commented 1 year ago

In isolation, yes the go server is faster at serving tiles over HTTP.

Performance in this context is the end user latency on the public internet. For the design you described, you'd indeed need to run a cluster of go-pmtiles behind dozens or hundreds of geographically distributed Varnish nodes in order to match the edge latency of cache hits on a commodity CDN like AWS or Cloudflare.