mirror of
https://github.com/consbio/mbtileserver.git
synced 2024-07-07 03:56:27 +03:00
ENH: Add support for returning missing images as HTTP 404 instead of blank PNGs (#177)
This commit is contained in:
parent
8403335a48
commit
04d08f1258
|
@ -2,6 +2,10 @@
|
|||
|
||||
## 0.11.0 (in development)
|
||||
|
||||
- support returning missing image tiles as HTTP 404 instead of blank tiles using
|
||||
the `--missing-image-tile-404` option (#177).
|
||||
|
||||
|
||||
## 0.10.0
|
||||
|
||||
- supports GCC11 on Ubuntu 22.04 (#166)
|
||||
|
|
58
README.md
58
README.md
|
@ -53,32 +53,36 @@ From within the repository root ($GOPATH/bin needs to be in your $PATH):
|
|||
|
||||
```
|
||||
$ mbtileserver --help
|
||||
Serve tiles from mbtiles files.
|
||||
Serve tiles from mbtiles files
|
||||
|
||||
Usage:
|
||||
mbtileserver [flags]
|
||||
|
||||
Flags:
|
||||
-c, --cert string X.509 TLS certificate filename. If present, will be used to enable SSL on the server.
|
||||
-d, --dir string Directory containing mbtiles files. Directory containing mbtiles files. Can be a comma-delimited list of directories. (default "./tilesets")
|
||||
--disable-preview Disable map preview for each tileset (enabled by default)
|
||||
--disable-svc-list Disable services list endpoint (enabled by default)
|
||||
--disable-tilejson Disable TileJSON endpoint for each tileset (enabled by default)
|
||||
--domain string Domain name of this server. NOTE: only used for AutoTLS.
|
||||
--dsn string Sentry DSN
|
||||
--enable-arcgis Enable ArcGIS Mapserver endpoints
|
||||
--enable-fs-watch Enable reloading of tilesets by watching filesystem
|
||||
--enable-reload-signal Enable graceful reload using HUP signal to the server process
|
||||
--generate-ids Automatically generate tileset IDs instead of using relative path
|
||||
-h, --help help for mbtileserver
|
||||
-k, --key string TLS private key
|
||||
-p, --port int Server port. Default is 443 if --cert or --tls options are used, otherwise 8000. (default -1)
|
||||
-r, --redirect Redirect HTTP to HTTPS
|
||||
--root-url string Root URL of services endpoint (default "/services")
|
||||
-s, --secret-key string Shared secret key used for HMAC request authentication
|
||||
--tiles-only Only enable tile endpoints (shortcut for --disable-svc-list --disable-tilejson --disable-preview)
|
||||
-t, --tls Auto TLS via Let's Encrypt
|
||||
-v, --verbose Verbose logging
|
||||
--basemap-style-url string Basemap style URL for preview endpoint (can include authorization token parameter if required by host)
|
||||
--basemap-tiles-url string Basemap raster tiles URL pattern for preview endpoint (can include authorization token parameter if required by host): https://some.host/{z}/{x}/{y}.png
|
||||
-c, --cert string X.509 TLS certificate filename. If present, will be used to enable SSL on the server.
|
||||
-d, --dir string Directory containing mbtiles files. Can be a comma-delimited list of directories. (default "./tilesets")
|
||||
--disable-preview Disable map preview for each tileset (enabled by default)
|
||||
--disable-svc-list Disable services list endpoint (enabled by default)
|
||||
--disable-tilejson Disable TileJSON endpoint for each tileset (enabled by default)
|
||||
--domain string Domain name of this server. NOTE: only used for AutoTLS.
|
||||
--dsn string Sentry DSN
|
||||
--enable-arcgis Enable ArcGIS Mapserver endpoints
|
||||
--enable-fs-watch Enable reloading of tilesets by watching filesystem
|
||||
--enable-reload-signal Enable graceful reload using HUP signal to the server process
|
||||
--generate-ids Automatically generate tileset IDs instead of using relative path
|
||||
-h, --help help for mbtileserver
|
||||
--host string IP address to listen on. Default is all interfaces. (default "0.0.0.0")
|
||||
-k, --key string TLS private key
|
||||
--missing-image-tile-404 Return HTTP 404 error code when image tile is misssing instead of default behavior to return blank PNG
|
||||
-p, --port int Server port. Default is 443 if --cert or --tls options are used, otherwise 8000. (default -1)
|
||||
-r, --redirect Redirect HTTP to HTTPS
|
||||
--root-url string Root URL of services endpoint (default "/services")
|
||||
-s, --secret-key string Shared secret key used for HMAC request authentication
|
||||
--tiles-only Only enable tile endpoints (shortcut for --disable-svc-list --disable-tilejson --disable-preview)
|
||||
-t, --tls Auto TLS via Let's Encrypt
|
||||
-v, --verbose Verbose logging
|
||||
```
|
||||
|
||||
So hosting tiles is as easy as putting your mbtiles files in the `tilesets`
|
||||
|
@ -306,6 +310,18 @@ These are provided at:
|
|||
|
||||
where `<format>` is one of `png`, `jpg`, `webp`, `pbf` depending on the type of data in the tileset.
|
||||
|
||||
|
||||
### Missing tiles
|
||||
|
||||
Missing vector tiles are always returned as HTTP 204.
|
||||
|
||||
Missing image tiles are returned as blank PNGs with the same dimensions as the tileset to give seamless display of
|
||||
these tiles in interactive maps.
|
||||
|
||||
When serving image tiles that encode data (e.g., terrain) instead of purely for display, this can cause issues. In
|
||||
this case, you can use the `--missing-image-tile-404` option. This behavior will be applied to all image tilesets.
|
||||
|
||||
|
||||
## TileJSON API
|
||||
|
||||
`mbtileserver` automatically creates a TileJSON endpoint for each service at `/services/<tileset_id>`.
|
||||
|
|
|
@ -13,14 +13,15 @@ import (
|
|||
|
||||
// ServiceSetConfig provides configuration options for a ServiceSet
|
||||
type ServiceSetConfig struct {
|
||||
EnableServiceList bool
|
||||
EnableTileJSON bool
|
||||
EnablePreview bool
|
||||
EnableArcGIS bool
|
||||
BasemapStyleURL string
|
||||
BasemapTilesURL string
|
||||
RootURL *url.URL
|
||||
ErrorWriter io.Writer
|
||||
EnableServiceList bool
|
||||
EnableTileJSON bool
|
||||
EnablePreview bool
|
||||
EnableArcGIS bool
|
||||
BasemapStyleURL string
|
||||
BasemapTilesURL string
|
||||
ReturnMissingImageTile404 bool
|
||||
RootURL *url.URL
|
||||
ErrorWriter io.Writer
|
||||
}
|
||||
|
||||
// ServiceSet is a group of tilesets plus configuration options.
|
||||
|
@ -28,12 +29,13 @@ type ServiceSetConfig struct {
|
|||
type ServiceSet struct {
|
||||
tilesets map[string]*Tileset
|
||||
|
||||
enableServiceList bool
|
||||
enableTileJSON bool
|
||||
enablePreview bool
|
||||
enableArcGIS bool
|
||||
basemapStyleURL string
|
||||
basemapTilesURL string
|
||||
enableServiceList bool
|
||||
enableTileJSON bool
|
||||
enablePreview bool
|
||||
enableArcGIS bool
|
||||
basemapStyleURL string
|
||||
basemapTilesURL string
|
||||
returnMissingImageTile404 bool
|
||||
|
||||
rootURL *url.URL
|
||||
errorWriter io.Writer
|
||||
|
@ -48,15 +50,16 @@ func New(cfg *ServiceSetConfig) (*ServiceSet, error) {
|
|||
}
|
||||
|
||||
s := &ServiceSet{
|
||||
tilesets: make(map[string]*Tileset),
|
||||
enableServiceList: cfg.EnableServiceList,
|
||||
enableTileJSON: cfg.EnableTileJSON,
|
||||
enablePreview: cfg.EnablePreview,
|
||||
enableArcGIS: cfg.EnableArcGIS,
|
||||
basemapStyleURL: cfg.BasemapStyleURL,
|
||||
basemapTilesURL: cfg.BasemapTilesURL,
|
||||
rootURL: cfg.RootURL,
|
||||
errorWriter: cfg.ErrorWriter,
|
||||
tilesets: make(map[string]*Tileset),
|
||||
enableServiceList: cfg.EnableServiceList,
|
||||
enableTileJSON: cfg.EnableTileJSON,
|
||||
enablePreview: cfg.EnablePreview,
|
||||
enableArcGIS: cfg.EnableArcGIS,
|
||||
basemapStyleURL: cfg.BasemapStyleURL,
|
||||
basemapTilesURL: cfg.BasemapTilesURL,
|
||||
returnMissingImageTile404: cfg.ReturnMissingImageTile404,
|
||||
rootURL: cfg.RootURL,
|
||||
errorWriter: cfg.ErrorWriter,
|
||||
}
|
||||
|
||||
return s, nil
|
||||
|
|
|
@ -219,7 +219,7 @@ func (ts *Tileset) tileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
if ts == nil || !ts.published {
|
||||
// In order to not break any requests from when this tileset was published
|
||||
// return the appropriate not found handler for the original tile format.
|
||||
tileNotFoundHandler(w, r, ts.tileformat, ts.tilesize)
|
||||
tileNotFoundHandler(w, r, ts.tileformat, ts.tilesize, ts.svc.returnMissingImageTile404)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -255,7 +255,7 @@ func (ts *Tileset) tileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
if data == nil || len(data) <= 1 {
|
||||
tileNotFoundHandler(w, r, ts.tileformat, ts.tilesize)
|
||||
tileNotFoundHandler(w, r, ts.tileformat, ts.tilesize, ts.svc.returnMissingImageTile404)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -327,13 +327,18 @@ func (ts *Tileset) previewHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// tileNotFoundHandler is an http.HandlerFunc that writes the default response
|
||||
// for a non-existing tile of type f to w
|
||||
func tileNotFoundHandler(w http.ResponseWriter, r *http.Request, f mbtiles.TileFormat, tilesize uint32) {
|
||||
func tileNotFoundHandler(w http.ResponseWriter, r *http.Request, f mbtiles.TileFormat, tilesize uint32, returnMissingImageTile404 bool) {
|
||||
switch f {
|
||||
case mbtiles.PNG, mbtiles.JPG, mbtiles.WEBP:
|
||||
// Return blank PNG for all image types
|
||||
w.Header().Set("Content-Type", "image/png")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(BlankPNG(tilesize))
|
||||
if returnMissingImageTile404 {
|
||||
// Return 404
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
} else {
|
||||
// Return blank PNG for all image types
|
||||
w.Header().Set("Content-Type", "image/png")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(BlankPNG(tilesize))
|
||||
}
|
||||
case mbtiles.PBF:
|
||||
// Return 204
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
|
|
20
main.go
20
main.go
|
@ -82,6 +82,7 @@ var (
|
|||
tilesOnly bool
|
||||
basemapStyleURL string
|
||||
basemapTilesURL string
|
||||
missingImageTile404 bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -112,6 +113,8 @@ func init() {
|
|||
flags.StringVar(&basemapStyleURL, "basemap-style-url", "", "Basemap style URL for preview endpoint (can include authorization token parameter if required by host)")
|
||||
flags.StringVar(&basemapTilesURL, "basemap-tiles-url", "", "Basemap raster tiles URL pattern for preview endpoint (can include authorization token parameter if required by host): https://some.host/{z}/{x}/{y}.png")
|
||||
|
||||
flags.BoolVarP(&missingImageTile404, "missing-image-tile-404", "", false, "Return HTTP 404 error code when image tile is misssing instead of default behavior to return blank PNG")
|
||||
|
||||
flags.BoolVarP(&verbose, "verbose", "v", false, "Verbose logging")
|
||||
|
||||
if env := os.Getenv("HOST"); env != "" {
|
||||
|
@ -292,14 +295,15 @@ func serve() {
|
|||
}
|
||||
|
||||
svcSet, err := handlers.New(&handlers.ServiceSetConfig{
|
||||
RootURL: rootURL,
|
||||
ErrorWriter: &errorLogger{log: log.New()},
|
||||
EnableServiceList: !disableServiceList,
|
||||
EnableTileJSON: !disableTileJSON,
|
||||
EnablePreview: !disablePreview,
|
||||
EnableArcGIS: enableArcGIS,
|
||||
BasemapStyleURL: basemapStyleURL,
|
||||
BasemapTilesURL: basemapTilesURL,
|
||||
RootURL: rootURL,
|
||||
ErrorWriter: &errorLogger{log: log.New()},
|
||||
EnableServiceList: !disableServiceList,
|
||||
EnableTileJSON: !disableTileJSON,
|
||||
EnablePreview: !disablePreview,
|
||||
EnableArcGIS: enableArcGIS,
|
||||
BasemapStyleURL: basemapStyleURL,
|
||||
BasemapTilesURL: basemapTilesURL,
|
||||
ReturnMissingImageTile404: missingImageTile404,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalln("Could not construct ServiceSet")
|
||||
|
|
Loading…
Reference in New Issue
Block a user