-
-
Notifications
You must be signed in to change notification settings - Fork 126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Range requests browser caching not working in Firefox (browser bug) #272
Comments
Thanks for investigating this thoroughly I don't think 3 and 4 are viable options because they would require interacting with the browser's storage APIs. MapLibre will already cache things internally I believe, but not across page loads. If caching across page loads is absolutely mandatory then there is many options such as lambda, cloudflare or caddy deployment to make it work as a ZXY tile endpoint. The best solve here is for Firefox to behave the same way as the other browsers, of course. |
Why is interacting with the browser storage APIs not an option until the browsers catch up and properly cache range requests? Would love to understand your thinking behind this. If we wanted to create a plugin, where would it best go, in the maplibre ecosystem and intercepting And Maplibre does cache tiles internally once they are loaded, but the use cases I'm looking at are e.g.
Hey by the way, it's both Firefox and Chrome that I tested, both have this issue. |
Here is the Firefox bug tracker where there's discussion of how this affects Cloud Optimized GeoTIFF in the same way: |
Quick correction: range request caching in Chrome works fine except in incognito windows (most likely by design). I just re-tested this in a normal Chrome window and it works indeed. Let me change the title to reflect that. |
In js v3 we're planning to move to always sending a conditional request
(substitute in your own file and etag if necessary). if browser cache is enabled in developer mode, at most the first request without if-match succeeds, the 2nd and 3rd will never be returned from browser cache. So this change will effectively make all browsers act like Firefox. The trade-off is that the JS client will work correctly with archives updated in-place, which is useful for many applications. |
Do I get this right - in v3 we want to send the In that case a middleware (e.g. lambda) turning the uncacheable byte-range requests into trivially cacheable
requests will become more and more unavoidable. |
Well, I spent today testing it out and I'm rolling back this change :P It turns out |
(We are still going to use If-Match for Lambda, Cloudflare and go-pmtiles, just not for the browser Fetch API which interacts with CORS and the browser cache) |
I appreciate your work here, this is really tricky and touching browser specific edge cases! 🚀 In terms of preflight CORS we had similar issues with our pmtiles deployment internally where browsers differed and Safari was the only one issuing a preflight CORS request. Definitely a bit tricky to make the setup work for all browsers when the byte-range requests are so finicky. |
JS 3.0.0-alpha.2 is on NPM implementing this, see changelog here: https://github.com/protomaps/PMTiles/blob/main/js/CHANGELOG.md It may require you change from This should be the final RC of 3.0.0, planning to publish the new major version this week. |
I got a strange error "Decoding failed" in Firefox v.124 with .pmtiles files deployed to Firebase hosting, while with Google Chrome or Chromium everything works without any additional configuration. Firefox Response Headers:
Chrome Response Headers:
It seems that I am missing something but changing the response headers in Firebase to different values did not fix the problem: // firebase.json
{
"hosting": {
"target": "atlas-prototype",
"public": "dist/spa",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"headers": [
{
"source": "**/*.pmtiles",
"headers": [
{
"key": "Content-Type",
"value": "application/octet-stream"
},
{
"key": "Access-Control-Allow-Origin",
"value": "*"
}
]
}
]
}
} |
Can you reproduce this on storage that isn’t firebase, like Amazon s3? |
No, I cannot. It seems that in my case problem is only with Firebase web hosting. I have deployed the same web application to Storj cloud (AWS S3 compatible) and everything is fine there for both web browsers. |
Thanks for reporting, this is worth digging into. Since I haven't used Firebase, can you provide a brief explanation as to how we can reproduce this? Are you embedding the pmtiles into a firebase application bundle or using a storage product? |
Sure. I have a single page application developed with Vue.js (Quasar framework) where in Map component I read the .pmtiles file with MapLibre library accordingly to official documentation. File .pmtiles is located just in public folder of the application. To deploy this application to Firebase hosting I used Firebase CLI and GitHub Actions to configure CI/CD. After successful deployment that problem appeared in Firefox. Should I try Firebase storage for storing .pmtiles files? |
Yes, if you can please try it with Firebase Storage that would be helpful. It's possible that including it as a static file in the Firebase app is transforming it somehow but it doesn't explain why Firefox would behave differently (I can also reproduce). |
@bdon thank you for advice! That solved my problem. Now everything works fine: https://atlas-prototype.web.app/#/districts in both web browsers: Firefox and Chrome. The solution in my case was:
sources: {
uatiles: {
type: "vector",
url: "pmtiles://https://firebasestorage.googleapis.com/v0/b/kinburn-land.appspot.com/o/vector-tiles%2Freg_ua.pmtiles?alt=media&token=3aadf1ee-df47-4e50-8006-660e08b0145e",
}
} Important! This part of URL Also, we should keep in mind settings of CORS, AppCheck and Rules while working with Firebase Storage |
I'm encountering this issue in chrome, not able to cache range requests. The example you originally linked to is now gone. What's the status of this issue. I'm curious if it's now generally working or there are some configuration settings that need to be made for it work. For ref, serving pmtiles from cloudflare r2 bucket, it is returning etag. I also tried changing the content type from |
Caching is disabled completely on Chromium-based browsers because of this bug: #442 |
Hey folks, I noticed earlier in my experimentation with maplibre and pmtiles that range requests against a .pmtiles file are not getting cached by browsers (I'm talking about Firefox and Chrome specifically).
I just ran across @bdon's https://bdon.github.io/overture-tiles/places.html#10.28/52.4901/13.3301 on mastodon and used this example to drill further down into what's happening because I can reproduce the issue there.
The summary is that currently neither Firefox nor Chrome can cache the range requests against .pmtiles, not even Chrome even tho it sends an
If-Range
with an ETag and the ETag matches (Firefox sends a regularRange
request).Firefox
Check this out. On second page load (warm cache)
Here are the request and response headers; notice
Range
requestChrome
Check this out. On second page load (warm cache)
Here are the request and response headers; notice
If-Range
request and attached the ETagWhat's happening here?
I looked around it and it seems like both Firefox as well as Chrome's support for caching range requests is very limited.
For example for Firefox
they only allow to cache a range request for the very first byte range starting at byte zero.
How to move forward
With limited support of caching range requests in the browsers, I see the following ways forward
I wanted to flag this with you since you might have thoughts on this and might have encountered this before.
What I wanted to add: pmtiles is such an amazing format for dropping a single file onto a static host that not having caching working by default is a bit unfortunate, because otherwise it shines and is such a cool idea 👌
The text was updated successfully, but these errors were encountered: