cannot set fetch options with maplibre protocol
When using a custom maplibre.addSource to use pmtiles, the PMTiles.getBytes method uses the global fetch method, this is done during the read metadata stage I think.
This means users can not alter the options such as setting credentials
https://github.com/protomaps/PMTiles/blob/main/js/index.ts#L379-L399
Once this has been read maplibre (i think) will then use the loaders.gl fetch methods which does allow the user to override this at a global level.
https://loaders.gl/docs/modules/core/api-reference/fetch-file
Could the pmtiles protocol also use this method so that users can fetch pmtiles using cors + credentials?
You can initialize a FetchSource with CustomHeaders:
https://protomaps.github.io/PMTiles/typedoc/classes/FetchSource.html
Thank you for the quick response, how would that work with addSource?
maplibre expects a string here both for tiles and url
See this example: https://github.com/protomaps/PMTiles/blob/main/js/examples/maplibre.html#L26
You can then reference it in a style via the same Url and it will resolve to the same instance
new pmtiles.PMTiles(fetchSource)
Would this be instead of using the built-in maplibre transformRequest? If pmtiles can use custom headers why noot just use the headers and create a fetch source internally using the existing headers?
And also, if we use this method with the custom FetchSource, does that mean we need a custom PMTiles for each url we want to use, rather than simply adding headers to all pmtiles requests like we can do with transformRequest?
For my use case I am just adding a header from a url query param in the PMTiles class, but would rather not use a custom fork. If you can point me in the direction to using the existing headers that's sent along with the request that would be awesome.
built-in maplibre transformRequest
transformRequest does not apply to custom protocols.
If pmtiles can use custom headers why noot just use the headers and create a fetch source internally using the existing headers?
There is no way to specify headers through MapLibre style URLs, you can only pass a string.
does that mean we need a custom PMTiles for each url we want to use
You need to instantiate a PMTiles javascript object and add it to the protocol for each URL, because there is no other way to specify it though the maplibre style object.
using the existing headers that's sent along with the request
I don't know what this refers to?
I figured out your code after reading it through a few times, so here it is for those looking for how to do this:
const pmtilesProtocol = new Protocol();
maplibregl.addProtocol("pmtiles", pmtilesProtocol.tile);
const authHeaders = new Headers({ Authorization: `Bearer ${userToken}` });
const URL = "https://urltotiles.com/data.pmtiles";
pmtilesProtocol.add(new PMTiles(new FetchSource(URL, authHeaders)));
But with this method I have to do this with all the pmtile urls I want to add. In Maplibre you can add headers to all/any requests via transformRequest, and it would be much simpler to use this method. I think this would have to be defined in the Protocol class instance, as the custom headers are available there, but I'm not familiar enough with the code to know if those would get persisted throughout the code. If you don't want to support this that's fine, but could you something to the docs like PMTiles does not support the transformRequest option in relation to custom headers, use the built-in FetchSource instead.
const map = new maplibregl.Map({
...
transformRequest: (url, resourceType) => {
if (url.includes("pmtiles")) {
return {
url: url,
headers: {
Authorization: `Bearer ${userToken}`
},
};
}
}
})
now that I look at this closer we can add the custom headers from transformRequest like this inside the Protocol class:
const headers = new Headers({ ...(params?.headers || {}) });
const source = new FetchSource(pmtilesUrl, headers);
instance = new PMTiles(source);
Is this something you would be willing to add or accept a PR?
Updated the TypeDoc here:
https://pmtiles.io/typedoc/classes/FetchSource.html https://pmtiles.io/typedoc/classes/Protocol.html
But with this method I have to do this with all the pmtile urls I want to add.
Can you accomplish this using a loop or reusable function?
Custom headers example: https://github.com/protomaps/PMTiles/blob/main/js/examples/maplibre_headers.html