concurrent caching proxy and decoder library for collections of PMTiles

go-pmtiles

A caching proxy for the serverless PMTiles archive format. Resolves several of the limitations of PMTiles by running a minimalistic, single-binary process on a tiny instance:

  • backwards compatibility for map renderers that require {z}/{x}/{y} url endpoints
  • lower latency, multiple fetches for index retrieval not necessary
  • automatic gzip compression for vector tiles

Installation

See Releases for your OS and architecture.

Usage

To serve a local directory containing EXAMPLE.pmtiles:

go-pmtiles EXAMPLE_DIR
> Serving EXAMPLE_DIR on HTTP port: 8077

Will respond to requests at http://localhost:8077/EXAMPLE/{z}/{x}/{y}.pbf

To serve a S3 bucket containing EXAMPLE.pmtiles:

go-pmtiles https://EXAMPLE_BUCKET.s3-us-west-2.amazonaws.com
> Serving https://EXAMPLE_BUCKET.s3-us-west-2.amazonaws.com on HTTP port: 8077

Will respond to requests at http://localhost:8077/EXAMPLE/{z}/{x}/{y}.pbf

Option flags must come before EXAMPLE_DIR or EXAMPLE_BUCKET.

  • -cors ORIGIN set the value of the Access-Control-Allow-Origin. * is a valid value but must be escaped in bash.
  • -cache SIZE_MB set the total size of the successful response cache. Default is 64 MB. Cache entries are evicted in LRU order.
Owner
Protomaps
the map foundry
Protomaps
Comments
  • 404 with some (big?) pmtiles

    404 with some (big?) pmtiles

    TL;DR I can't get tiles out of go-pmtiles v0.5 for some files which work well through pmtiles-js.

    I suspect it is linked with the file having leaf directories.

    | File | Size | JS - test URL | GO - test URL | | --- | -- | -- | -- | | Bugianen_Cervino | 0.2 GB | :ok: | :ok: wtracks C-go | Bugianen | 3.5 GB (sorry!) | :ok: wtracks B-js | :no_entry: wtracks B-go | eslo14_walps | 1.5 G | :ok: | :no_entry:

    Context

    I am integrating some pmtiles maps in https://opoto.github.io/wtracks/

    After merging pmtiles support (opoto/wtracks#21), I have working, but excruciatingly slow pmtiles-js-on-HTTP1 maps (that we discussed in protomaps/PMTiles#16). For example IT Bugianen (find it in More... menu or though the custom link above)

    Now I'm trying to evaluate performance on go-pmtiles on the same map, but it does not work (metadata works 404 on tiles I tried). See the links to download/test the files above. I including a valid file to show that the issue is not how my server setup on montagne.top.

    To test on wtracks, search for a covered area for both maps eg "Aosta". Or test with curl:

    curl -i https://www.montagne.top/maki/Bugianen_Cervino/16/34100/23382.jpg
    HTTP/1.1 200 OK
    curl -i https://www.montagne.top/maki/Bugianen/16/34100/23382.jpg
    HTTP/1.1 404 Not Found
    curl -I https://www.montagne.top/tile/eslo14_walps/16/34100/23382.png
    HTTP/1.1 404 Not Found
    

    I can try to debug it myself at some point, but figured maybe it's a known issue with big files?

  • go-pmtiles docker image on GitHub registry

    go-pmtiles docker image on GitHub registry

    could fix #3 (sorry, first pull request was based on wrong branch)

    some points to extend:

    • [ ] write proper documentation on how to use and modify
    • [ ] add testing pipeline to pass before creating a new image
    • [ ] ..
  • Problem compressed vector tiles in MBTiles

    Problem compressed vector tiles in MBTiles

    Used go-pmtiles to convert a MBTiles with compressed vector tiles. It did not work in maplibre. Then I made the MBTiles with uncompressed vector tiles and converted again. Then it worked just fine. Am I doing something wrong?

  • [feature] Set cache headers

    [feature] Set cache headers

    It seems that tiles are not cached (trying on latest chrome, linux)

    Looking at others they all set cache-control:

    • OpenStreetMap: cache-control: max-age=604800, stale-while-revalidate=604800, stale-if-error=604800
    • OpenTopoMap: Cache-Control: max-age=439803
    • Swisstopo: cache-control: public, must-revalidate, max-age=3600
    • IGN: access-control-max-age: 43200 etc
  • Configure port number

    Configure port number

    I'll admit up front that I am least familiar with Go apps generally, so please excuse any very basic misses here. I love the concept of PMTiles and hope to test, initially focusing on python, but it seems this Go server is the more robust option.

    I had hoped to take a shortcut to free deployment via Heroku for testing (following this workaround for compiled app https://medium.com/ki-labs-engineering/deploying-a-native-go-binary-on-heroku-6d4c955819d8), but the lack of configuration of port seems to be the main blocker. There appears to be no way to utilize a dynamic port currently.

    Please disregard if this is an edge case, or if there is generally a better way to approach deployment of a precompiled Go app such as this. Excited to figure this out...

  • List available commands

    List available commands

    ./pmtiles 
    2022/10/27 14:16:01 main.go:22: Command is required.
    

    There doesn't seem to be any way to get the available commands listed. ./pmtiles --help doesn't work.

  • Feature Request: Env variables to set CLI opts

    Feature Request: Env variables to set CLI opts

    It'd be great if I can configure options using environment variables to have deployments be easily managed via docker, etc.

    PMTILES_PATH=https://storage.googleapis.com/my-tiles
    PMTILES_CORS=*
    PMTILES_CACHE=2000
    
  • Show file spec version

    Show file spec version

    /pmtiles show file:// public/catch.pmtiles 
    total size: 13 MB
    tile type: Vector Protobuf (MVT)
    bounds: 140.962409,-39.136654 149.974995,-33.981390
    min zoom: 0
    max zoom: 15
    center: 142.476196,-38.371809
    center zoom: 15
    addressed tiles count: 322258
    tile entries count: 55994
    tile contents count: 42135
    clustered: true
    

    Surprised it doesn't list what spec version the .pmtiles file is - that would be helpful.

  • Return errors instead of triggering fatal errors in library code

    Return errors instead of triggering fatal errors in library code

    This PR replaces all the calls to log.Fatal or panic in the pmtiles package libraries with error responses. The main.go tool has been updated accordingly. This allows the pmtiles package to be used by other code without having to trap fatal errors.

  • Allow dashes in file name

    Allow dashes in file name

    ... since they are allowed in object names for some providers, and otherwise we get 404 error.

    Also it is quite hard to debug as there is no log at all in this case. Suggestions:

    • Return 400 Bad Request instead of 404
    • Log Malformed URL "foo"

    Note: PR made in the browser, untested, and my first line of Go, if we can call it that :laughing:

  • convert/upgrade does not handle PNG/JPEG/WebP archives

    convert/upgrade does not handle PNG/JPEG/WebP archives

    • Disable the compressor
    • Add an option to disable deduplication (requires prior knowledge)
    • num tile contents data needs to be deduplication-aware
    • Fix header values and reading MBTiles/PMTilesv2 metadata
  • Add `pmtiles extract` command

    Add `pmtiles extract` command

    It would be useful to be able to extract tiles from a pmtiles file for a certain area and put the extracted tiles into a new pmtiles file.

    It could look something like this:

    pmtiles extract input.pmtiles output.pmtiles --bounds "47.5,7.5,48.0,8.5" 
    

    A usecase could be to have a global tileset and allow users to download an extract for a city or so.

  • Use v3 as a library

    Use v3 as a library

    I was using the writer interface of v2 combined with github.com/paulmach/orb to create my pmtiles file.

    	writer := pmtiles.NewWriter("./base.pmtiles")
    	for z := minZoom; z <= maxZoom; z++ {
    		covering := tilecover.Bound(bound, z)
    		for tile := range covering {
    		    layers := mvt.Layers{.....layers.....}
    		    tileData, _ := mvt.Marshal(layers)
        
    		    writer.WriteTile(
    			    pmtiles.Zxy{
    				    Z: uint8(tile.Z),
    				    X: tile.X,
    				    Y: tile.Y,
    			    },
    			    tileData,
    		    )
    		}
    	}
    
    	metadata, err := json.Marshal(pmtiles.Metadata{
               ...metadata...
             })
    	if err != nil {
    		return err
    	}
    	writer.Finalize(metadata)
    

    Is something similar still possible using v3?

    To create a better separation of concerns, it might be a good idea to split the pmtiles folder. The pmtiles folder can hold all the library code for reading and writing pmtiles. Next to a cmd folder that can hold the cli related commands and logic for handling flags, etc.

  • Better optimization around 16,384 byte root directory threshold

    Better optimization around 16,384 byte root directory threshold

    If the directory does not fit in only the root, right now the code defaults to creating a root with leaves of a fixed size 4, 8, 16... kB.

    It should be smart enough for two cases:

    • If the total directory is slightly larger than 16,384, the root should have a mix of tile entries and leaf pointers
    • If the total directory is much larger, it should try to fill as much of the 16,384 as possible.
Related tags
LinkPreview.net Proxy Server with Caching

LinkPreview.net Proxy Server with Caching Description LinkPreview API/Image Proxy Server with Caching written in Go. Features: In-memory caching layer

Nov 19, 2021
🌕 Server application for storing doujinshi, manga, art collections and other galleries with API and user control. Written in Go.

?? Server application for storing doujinshi, manga, art collections and other galleries with API and user control. Written in Go.

Dec 31, 2022
An IPFS bytes exchange for caching and retrieving data from Filecoin

?? go-hop-exchange An IPFS bytes exchange to allow any IPFS node to become a Filecoin retrieval provider and retrieve content from Filecoin Highlights

Aug 25, 2022
Pure Go Brotli encoder and decoder

This package is a brotli compressor and decompressor implemented in Go. It was translated from the reference implementation (https://github.com/google

Dec 28, 2022
An experimental Tor-Proxy serivce written in Go using Go-proxy and Go-libtor.

tor-proxy An experimental standalone tor-proxy service built with Go, using go-proxy, go-libtor and bine. This is a simple replacement to Tor's origin

Nov 9, 2022
IP2Proxy Go package allows users to query an IP address to determine if it was being used as open proxy, web proxy, VPN anonymizer and TOR exits.

IP2Proxy Go Package This package allows user to query an IP address if it was being used as VPN anonymizer, open proxies, web proxies, Tor exits, data

Sep 15, 2022
Battlesnake-logging-proxy - A little proxy between the internet and your battlesnake

battlesnake-logging-proxy a little proxy between the internet and your battlesna

Feb 11, 2022
Go decoder for EU Digital COVID Certificate (EUDCC) QR code data

Go Corona QR Code Decoder This repository contains a decoder for EU Digital COVID Certificate (EUDCC) QR code data, written in Go. If you got vaccinat

Nov 30, 2022
mt-multiserver-proxy is a reverse proxy designed for linking multiple Minetest servers together

mt-multiserver-proxy mt-multiserver-proxy is a reverse proxy designed for linking multiple Minetest servers together. It is the successor to multiserv

Nov 17, 2022
A simple tool to convert socket5 proxy protocol to http proxy protocol

Socket5 to HTTP 这是一个超简单的 Socket5 代理转换成 HTTP 代理的小工具。 如何安装? Golang 用户 # Required Go 1.17+ go install github.com/mritd/s2h@master Docker 用户 docker pull m

Jan 2, 2023
Tcp-proxy - A dead simple reverse proxy server.

tcp-proxy A proxy that forwords from a host to another. Building go build -ldflags="-X 'main.Version=$(git describe --tags $(git rev-list --tags --max

Jan 2, 2022
Proxy - Minimalistic TCP relay proxy.

Proxy Minimalistic TCP relay proxy. Installation ensure you have go >= 1.17 installed clone the repo cd proxy go install main.go Examples Listen on po

May 22, 2022
Http-logging-proxy - A HTTP Logging Proxy For Golang

http-logging-proxy HTTP Logging Proxy Description This project builds a simple r

Aug 1, 2022
Concurrent ssh-tail sessions and sink option
Concurrent ssh-tail sessions and sink option

ssh-tail This project is one of the problems that I generally face while debugging some system. When I am reproducing the issue on the machine i also

Dec 2, 2022
A high-performance concurrent scanner written by go, which can be used for survival detection, tcp port detection, and web service detection.
A high-performance concurrent scanner written by go, which can be used for survival detection, tcp port detection, and web service detection.

aScan A high-performance concurrent scanner written by go, which can be used for survival detection, tcp port detection, and web service detection. Fu

Aug 15, 2022
A quick and dirty concurrent Golang-based port scanner

go-scan-ports A quick and dirty concurrent Golang-based port scanner, this will scan ports 1 through 1024 Usage: Requires 1 command line argument of U

Jan 6, 2022
Concurrent download manager built in Go
Concurrent download manager built in Go

Golang Download Manager - Weekend Project A concurrent download manager written in pure Go without any dependency. I wrote this code for my YouTube vi

Sep 29, 2022
concurrent recursive whois resolution

drwho - concurrent 'whois' queries given a set of ip addresses (v4 and v6), concurrently queries whois servers about them. example populate a file wit

Dec 28, 2021