mirror of
https://github.com/consbio/mbtileserver.git
synced 2024-07-14 18:30:36 +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)
|
## 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
|
## 0.10.0
|
||||||
|
|
||||||
- supports GCC11 on Ubuntu 22.04 (#166)
|
- 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
|
$ mbtileserver --help
|
||||||
Serve tiles from mbtiles files.
|
Serve tiles from mbtiles files
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
mbtileserver [flags]
|
mbtileserver [flags]
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
-c, --cert string X.509 TLS certificate filename. If present, will be used to enable SSL on the server.
|
--basemap-style-url string Basemap style URL for preview endpoint (can include authorization token parameter if required by host)
|
||||||
-d, --dir string Directory containing mbtiles files. Directory containing mbtiles files. Can be a comma-delimited list of directories. (default "./tilesets")
|
--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
|
||||||
--disable-preview Disable map preview for each tileset (enabled by default)
|
-c, --cert string X.509 TLS certificate filename. If present, will be used to enable SSL on the server.
|
||||||
--disable-svc-list Disable services list endpoint (enabled by default)
|
-d, --dir string Directory containing mbtiles files. Can be a comma-delimited list of directories. (default "./tilesets")
|
||||||
--disable-tilejson Disable TileJSON endpoint for each tileset (enabled by default)
|
--disable-preview Disable map preview for each tileset (enabled by default)
|
||||||
--domain string Domain name of this server. NOTE: only used for AutoTLS.
|
--disable-svc-list Disable services list endpoint (enabled by default)
|
||||||
--dsn string Sentry DSN
|
--disable-tilejson Disable TileJSON endpoint for each tileset (enabled by default)
|
||||||
--enable-arcgis Enable ArcGIS Mapserver endpoints
|
--domain string Domain name of this server. NOTE: only used for AutoTLS.
|
||||||
--enable-fs-watch Enable reloading of tilesets by watching filesystem
|
--dsn string Sentry DSN
|
||||||
--enable-reload-signal Enable graceful reload using HUP signal to the server process
|
--enable-arcgis Enable ArcGIS Mapserver endpoints
|
||||||
--generate-ids Automatically generate tileset IDs instead of using relative path
|
--enable-fs-watch Enable reloading of tilesets by watching filesystem
|
||||||
-h, --help help for mbtileserver
|
--enable-reload-signal Enable graceful reload using HUP signal to the server process
|
||||||
-k, --key string TLS private key
|
--generate-ids Automatically generate tileset IDs instead of using relative path
|
||||||
-p, --port int Server port. Default is 443 if --cert or --tls options are used, otherwise 8000. (default -1)
|
-h, --help help for mbtileserver
|
||||||
-r, --redirect Redirect HTTP to HTTPS
|
--host string IP address to listen on. Default is all interfaces. (default "0.0.0.0")
|
||||||
--root-url string Root URL of services endpoint (default "/services")
|
-k, --key string TLS private key
|
||||||
-s, --secret-key string Shared secret key used for HMAC request authentication
|
--missing-image-tile-404 Return HTTP 404 error code when image tile is misssing instead of default behavior to return blank PNG
|
||||||
--tiles-only Only enable tile endpoints (shortcut for --disable-svc-list --disable-tilejson --disable-preview)
|
-p, --port int Server port. Default is 443 if --cert or --tls options are used, otherwise 8000. (default -1)
|
||||||
-t, --tls Auto TLS via Let's Encrypt
|
-r, --redirect Redirect HTTP to HTTPS
|
||||||
-v, --verbose Verbose logging
|
--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`
|
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.
|
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
|
## TileJSON API
|
||||||
|
|
||||||
`mbtileserver` automatically creates a TileJSON endpoint for each service at `/services/<tileset_id>`.
|
`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
|
// ServiceSetConfig provides configuration options for a ServiceSet
|
||||||
type ServiceSetConfig struct {
|
type ServiceSetConfig struct {
|
||||||
EnableServiceList bool
|
EnableServiceList bool
|
||||||
EnableTileJSON bool
|
EnableTileJSON bool
|
||||||
EnablePreview bool
|
EnablePreview bool
|
||||||
EnableArcGIS bool
|
EnableArcGIS bool
|
||||||
BasemapStyleURL string
|
BasemapStyleURL string
|
||||||
BasemapTilesURL string
|
BasemapTilesURL string
|
||||||
RootURL *url.URL
|
ReturnMissingImageTile404 bool
|
||||||
ErrorWriter io.Writer
|
RootURL *url.URL
|
||||||
|
ErrorWriter io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServiceSet is a group of tilesets plus configuration options.
|
// ServiceSet is a group of tilesets plus configuration options.
|
||||||
@ -28,12 +29,13 @@ type ServiceSetConfig struct {
|
|||||||
type ServiceSet struct {
|
type ServiceSet struct {
|
||||||
tilesets map[string]*Tileset
|
tilesets map[string]*Tileset
|
||||||
|
|
||||||
enableServiceList bool
|
enableServiceList bool
|
||||||
enableTileJSON bool
|
enableTileJSON bool
|
||||||
enablePreview bool
|
enablePreview bool
|
||||||
enableArcGIS bool
|
enableArcGIS bool
|
||||||
basemapStyleURL string
|
basemapStyleURL string
|
||||||
basemapTilesURL string
|
basemapTilesURL string
|
||||||
|
returnMissingImageTile404 bool
|
||||||
|
|
||||||
rootURL *url.URL
|
rootURL *url.URL
|
||||||
errorWriter io.Writer
|
errorWriter io.Writer
|
||||||
@ -48,15 +50,16 @@ func New(cfg *ServiceSetConfig) (*ServiceSet, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s := &ServiceSet{
|
s := &ServiceSet{
|
||||||
tilesets: make(map[string]*Tileset),
|
tilesets: make(map[string]*Tileset),
|
||||||
enableServiceList: cfg.EnableServiceList,
|
enableServiceList: cfg.EnableServiceList,
|
||||||
enableTileJSON: cfg.EnableTileJSON,
|
enableTileJSON: cfg.EnableTileJSON,
|
||||||
enablePreview: cfg.EnablePreview,
|
enablePreview: cfg.EnablePreview,
|
||||||
enableArcGIS: cfg.EnableArcGIS,
|
enableArcGIS: cfg.EnableArcGIS,
|
||||||
basemapStyleURL: cfg.BasemapStyleURL,
|
basemapStyleURL: cfg.BasemapStyleURL,
|
||||||
basemapTilesURL: cfg.BasemapTilesURL,
|
basemapTilesURL: cfg.BasemapTilesURL,
|
||||||
rootURL: cfg.RootURL,
|
returnMissingImageTile404: cfg.ReturnMissingImageTile404,
|
||||||
errorWriter: cfg.ErrorWriter,
|
rootURL: cfg.RootURL,
|
||||||
|
errorWriter: cfg.ErrorWriter,
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
|
@ -219,7 +219,7 @@ func (ts *Tileset) tileHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
if ts == nil || !ts.published {
|
if ts == nil || !ts.published {
|
||||||
// In order to not break any requests from when this tileset was 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.
|
// 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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +255,7 @@ func (ts *Tileset) tileHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if data == nil || len(data) <= 1 {
|
if data == nil || len(data) <= 1 {
|
||||||
tileNotFoundHandler(w, r, ts.tileformat, ts.tilesize)
|
tileNotFoundHandler(w, r, ts.tileformat, ts.tilesize, ts.svc.returnMissingImageTile404)
|
||||||
return
|
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
|
// tileNotFoundHandler is an http.HandlerFunc that writes the default response
|
||||||
// for a non-existing tile of type f to w
|
// 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 {
|
switch f {
|
||||||
case mbtiles.PNG, mbtiles.JPG, mbtiles.WEBP:
|
case mbtiles.PNG, mbtiles.JPG, mbtiles.WEBP:
|
||||||
// Return blank PNG for all image types
|
if returnMissingImageTile404 {
|
||||||
w.Header().Set("Content-Type", "image/png")
|
// Return 404
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
w.Write(BlankPNG(tilesize))
|
} 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:
|
case mbtiles.PBF:
|
||||||
// Return 204
|
// Return 204
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
20
main.go
20
main.go
@ -82,6 +82,7 @@ var (
|
|||||||
tilesOnly bool
|
tilesOnly bool
|
||||||
basemapStyleURL string
|
basemapStyleURL string
|
||||||
basemapTilesURL string
|
basemapTilesURL string
|
||||||
|
missingImageTile404 bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
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(&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.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")
|
flags.BoolVarP(&verbose, "verbose", "v", false, "Verbose logging")
|
||||||
|
|
||||||
if env := os.Getenv("HOST"); env != "" {
|
if env := os.Getenv("HOST"); env != "" {
|
||||||
@ -292,14 +295,15 @@ func serve() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
svcSet, err := handlers.New(&handlers.ServiceSetConfig{
|
svcSet, err := handlers.New(&handlers.ServiceSetConfig{
|
||||||
RootURL: rootURL,
|
RootURL: rootURL,
|
||||||
ErrorWriter: &errorLogger{log: log.New()},
|
ErrorWriter: &errorLogger{log: log.New()},
|
||||||
EnableServiceList: !disableServiceList,
|
EnableServiceList: !disableServiceList,
|
||||||
EnableTileJSON: !disableTileJSON,
|
EnableTileJSON: !disableTileJSON,
|
||||||
EnablePreview: !disablePreview,
|
EnablePreview: !disablePreview,
|
||||||
EnableArcGIS: enableArcGIS,
|
EnableArcGIS: enableArcGIS,
|
||||||
BasemapStyleURL: basemapStyleURL,
|
BasemapStyleURL: basemapStyleURL,
|
||||||
BasemapTilesURL: basemapTilesURL,
|
BasemapTilesURL: basemapTilesURL,
|
||||||
|
ReturnMissingImageTile404: missingImageTile404,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Could not construct ServiceSet")
|
log.Fatalln("Could not construct ServiceSet")
|
||||||
|
Loading…
Reference in New Issue
Block a user