mapbox-gl-js icon indicating copy to clipboard operation
mapbox-gl-js copied to clipboard

Handle 204 No content responses correctly as an empty tile and avoid trying to decode the response

Open candux opened this issue 5 years ago • 8 comments

Tileserver-GL started sending empty 204 responses if a tile is not available. https://github.com/maptiler/tileserver-gl/blob/master/src/serve_data.js#L45 https://github.com/maptiler/tileserver-gl/pull/339

Mapbox-gl-js doesn't handle this very good. It creates an error message every time a tile is fetched and doesn't cache the server response (but the browser maybe does).

mapbox-gl-js version: Since 1.7.0. 1.6.0 is not affected browser: Chrome, Firefox

Steps to Trigger Behavior

  1. Open the Demonstration
  2. See Errors in Console
  3. Scroll in and out. The 204 requests are repeated every time

Link to Demonstration

https://jsbin.com/loyajulodu/edit?html,output

Expected Behavior

  • 204 response don't create a console error
  • 204 response are cached inside mapbox-gl-js

Actual Behavior

  • 204 response create a console error
Error: Could not load image because of The source image could not be decoded.. Please make sure to use a supported image type such as PNG or JPEG. Note that SVGs are not supported.
    at ajax.js:280
  • 204 response are always passed to the Browser. The browser maybe caches it.

candux avatar Feb 17 '20 17:02 candux

It seems we are trying to read the content of a 204 in the same way as a 200. It seems reasonable to me that we treat 204 responses as they should be, as empty content and avoid throwing the error.

Some background in #1800 which backs up this request.

andrewharvey avatar Feb 18 '20 01:02 andrewharvey

We'll need to be careful that any changes in handling 204 errors don't exacerbate the problem of overdrawing in sparse tile sets as in https://github.com/mapbox/mapbox-gl-js/issues/6768. This issue was partially fixed with https://github.com/mapbox/mapbox-gl-js/pull/6803.

GL Native treats 204 and 404 responses as No Content

https://github.com/mapbox/mapbox-gl-native/blob/6ddff19ceedb8f6cb095792b90121330afcc38cf/platform/android/src/http_file_source.cpp#L141-L142

ryanhamley avatar Feb 18 '20 17:02 ryanhamley

204 means No Content, 404 means Not Found. They are two different things. Suppose we have a mbtile storing a tileset. If users request a z/x/y tile, server side query the tile table of the mbtile to get tile data. When the tile table do have the z/x/y record and tile_data is null or zero length blob, then server side should response 204, client side should treat as "OK, I get the tile, but the tile is empty, means this area have nothing to render, so I just need to render the background". On the other side, When tile table do not have the z/x/y record, then server side should response 404, client side should treat as "Ops, I can not get the tile, means the tile is missing and this area may have features to render, I should overzoom the upper level tile to fill this area". In conclusion, empty tile and missing tile are two different things.

jingsam avatar Feb 19 '20 04:02 jingsam

I think I read two bugs here:

  1. No Content (empty content?) shouldn't throw errors.
  2. HTTP 204 and 404 should be differentiated as No Content and Missing Content respectively (and result in different rendering). This is something the native side would also need to change.

cc @mapbox/gl-js @mapbox/gl-native

ahk avatar Feb 25 '20 21:02 ahk

Any updates?

owl1n avatar Apr 13 '20 08:04 owl1n

This is hitting me too using hillshading mbtiles datasets from https://openmaptiles.com/. We're using a custom tile server that responds with 204 No Content if the tile url is valid but no hillshading data is present for that tile.

robinsummerhill avatar Sep 18 '20 12:09 robinsummerhill

Looked around a bit:

JS / web:

  • implemented in mapbox v3.1: https://github.com/mapbox/mapbox-gl-js/commit/cab025020e02dda852eea8478bf7ff4a6e77320e
  • couldn't find code to handle this in mapbox 2.x?
  • couldn't find code to handle this in mapbox 1.x? But 204 vector tiles in mapbox 1.12 aren't refetched in my experiments? raster tiles probably problematic.
    • workaround for raster tile errors (?) in maplibre v4.x (unreleased): https://github.com/maplibre/maplibre-gl-js/commit/4ad19a6d7f3e98605e7e3892a5dd32a5978ee4d7

Native:

  • mapbox seems to treat 204 and 404 as error-less no-content (?): https://github.com/mapbox/mapbox-gl-native/commit/e9302c797f68c7e48b908b87b126045c8c5e5209 and unit-test https://github.com/maplibre/maplibre-native/commit/ca4f0bbcc58046498966daf4c695bc7977c85e44
    • maplibre has inherited this: https://github.com/maplibre/maplibre-native/commit/e9302c797f68c7e48b908b87b126045c8c5e5209 and https://github.com/maplibre/maplibre-native/commit/ca4f0bbcc58046498966daf4c695bc7977c85e44

Looking at the code I don't think 204 is specifically handled and mostly seems to depend on the data being zero length? Most changes seem to be about avoiding errors on empty data, assuming it was a 204.

I was under the impression 204 worked fine (force tile to be empty), but this issue implies there isn't explicit support for this in many clients. I even expected that 404 worked fine (using tiles from other zoom levels to pad the data), but that probably doesn't work correctly - although I did not check?

After briefly looking at the different renderers, I'm not so sure anymore whether it's a good idea to depend on these status code to convey meaning in tile-servers right now..

JannikGM avatar Jan 19 '24 09:01 JannikGM

I have an Nginx server with static tile files in PBF format. Therefore, the assets are vectors, not images. Libraries like MapLibre GL and Mapbox GL can handle missing files (204 or any other response status) and use the vectors below to render them at a higher zoom level. The main difference between a 204 status and others like 4xx or 50xx is that browsers do not throw errors. For instance, if the server sends a 404 response, the browser will throw an error in the console, even though the libraries know what to do to render the missing tile. My server sends a 204 status for all 404 requests and asks the browser to cache it. This makes sense as there are no errors in the console and the 204 status is cached.

sylvio-ruiz avatar Jan 19 '24 11:01 sylvio-ruiz