Content Type
Every tile returned by tilegroxy carries a `Content-Type`, either received from an upstream server or known to the provider that generated it. Content types from upstream servers are validated against an allowlist before being used.
Where the Content Type comes from
Providers that call an external HTTP server, such as proxy and url template, use the Content-Type returned by that server after it passes validation. The cgi provider uses the Content-Type header written by the CGI application.
Providers that generate imagery themselves set the content type unconditionally. blend, crop, effect, and transform always produce image/png. static produces image/png unless its image is a vector tile. postgis mvt and composite mvt always produce application/vnd.mapbox-vector-tile, and composite mlt always produces application/vnd.maplibre-tile. PMTiles uses the tile type declared in the archive header.
Providers that wrap another provider, such as fallback and ref, pass through the content type of whichever provider produced the tile.
A custom provider sets the ContentType field on the Image it returns. Custom providers using the GetTile utility method receive the same validation and rewriting as built-in providers, which is one reason to prefer it over making your own HTTP request.
Validation and rewriting
Two client options control what an external server is allowed to return.
ContentTypes is an allowlist. A response with a Content-Type outside this list is treated as an error and no tile is returned, even if the status code indicates success. The default allows image/png, image/jpg, image/jpeg, application/vnd.mapbox-vector-tile, application/x-protobuf, application/vnd.maplibre-tile, and application/vnd.maplibre-vector-tile. Matching is exact, so a server sending image/png; charset=binary requires that full string be added to the list.
RewriteContentTypes replaces a content type after it passes the allowlist. This is for servers that describe every tile with a generic type. The default maps application/octet-stream to an empty string as described in Empty content types.
Rewriting happens after validation, therefore the original content type must appear in ContentTypes for the rewrite to be reached. Adding an entry to RewriteContentTypes without also adding the key to ContentTypes has no effect.
Empty content types
An empty content type means tilegroxy sets no Content-Type header and lets Go determine one by inspecting the first bytes of the tile. This is accurate for PNG and JPEG which have recognizable file signatures. It is not accurate for vector tiles, which Go sees as arbitrary binary data and reports as application/octet-stream. If your upstream server returns a generic content type for vector tiles, map it explicitly to application/vnd.mapbox-vector-tile for MVT or application/vnd.maplibre-tile for MLT rather than to an empty string.
Caching and downstream use
The content type is stored alongside the tile contents in every cache, so a tile served from cache returns the same Content-Type as when it was first generated.
The content type is also available as the contenttype field in analytics and the content-type validation mode for health checks compares it against an expected value.
Error responses are handled separately. They set a Content-Type based on the configured error mode rather than anything a provider returned.