Switch to shortbread style with absolute URLs
This style and associated assets are served with CORS headers that allow use by openstreetmap.org or 127.0.0.1.
This has been tested with rails server and the CORS headers for openstreetmap.org were tested with cURL
Part of https://github.com/openstreetmap/operations/issues/1263
I can't explain it but this is failing for me with a CORS error loading https://vector.openstreetmap.org/styles/shortbread/colorful.json.
The requests look identical to me with and without this but the old code seems to get an Access-Control-Allow-Origin: * header back and the new code doesn't.
Are you getting the error in a local development environment? Does the CORS configuration also need to exempt localhost explicitly, or does the exception for 127.0.0.1 already cover that?
I'm seeing the same as @tomhughes:
Confusingly, sometimes the Firefox network inspector shows the error, and sometimes it doesn't, loads the data from cache, and pretends that all is ok, but the map still doesn't load (it's completely blank). All I see in the console is two CSP warnings that I think are unrelated.
My recollection of how CORS works is sketchy, but I can't see any Access-Control-* headers?
$ curl --silent -i https://vector.openstreetmap.org/styles/shortbread/colorful.json | head -n 50
HTTP/2 200
server: nginx
content-type: application/json
last-modified: Sun, 07 Dec 2025 22:15:43 GMT
etag: "6935fc8f-4a18d"
cache-control: public,max-age=300,stale-while-revalidate=3600,stale-if-error=86400
x-rendered-by: cmok.openstreetmap.org
accept-ranges: bytes
age: 196
date: Mon, 08 Dec 2025 15:55:52 GMT
via: 1.1 varnish
x-served-by: cache-lcy-eglc8600024-LCY
x-cache: HIT
x-cache-hits: 0
x-timer: S1765209353.940283,VS0,VE2
vary: Origin, Accept-Encoding
strict-transport-security: max-age=31557600
alt-svc: h3=":443";ma=86400,h3-29=":443";ma=86400,h3-27=":443";ma=86400
content-length: 303501
{
"version": 8,
"name": "versatiles-colorful",
...
It was my test environment but not running on localhost as such, running as osm.compton.nu which resolves to a 172.16 IPv4 and a public IPv6.
Does the CORS configuration also need to exempt localhost explicitly, or does the exception for 127.0.0.1 already cover that?
It needs to list localhost explicitly. I'll add that to the section. For reasons unrelated to this issue I don't recommend using localhost but recommend 127.0.0.1 instead as the latter is always a secure origin.
The requests look identical to me with and without this
They should be to different URLs
It was my test environment but not running on localhost as such, running as osm.compton.nu
I'm not sure of a good way to accommodate test locations on other domains. Obviously I can add them as they come up but I'd prefer a more systematic solution.
I'd prefer a more systematic solution.
How about a separate https://apis.dev.openstreetmap.org/ instance?
How about a separate https://apis.dev.openstreetmap.org/ instance?
I'm not sure what you mean by using that as a solution for people doing local development on different domains. I have *.openstreetmap.org allow-listed for CORS so the dev instances should work fine.
Oh right, local development (only) would probably be too variable for a systematic solution. I just meant an apis.dev server could be used together with a local setup to cross-check domain-specific things.
But what looks like exactly the same request works fine for me without this PR merged? I don't understand why or how the server behaviour changes because of a client change that seems to have no effect on the request that is sent to the server?
Does not having the callback cause maplibre to change the way it makes the request so that it now requires CORS when it didn't before or something?
AFAICT, the demo assets were initially for demoing (duh) during development, and therefore, the style JSON was made relative to not to generate the styles for each host access path.
Now the plan from the ops meeting is to commit to hosting an absolute style without CORS and eventually to retire the demo assets.
But what looks like exactly the same request works fine for me without this PR merged? I don't understand why or how the server behaviour changes because of a client change that seems to have no effect on the request that is sent to the server?
The requests shouldn't be the same. Current requests should be to a path in /demo/shortbread and this PR changes them to /styles/shortbread. Can you copy them out to a curl command so I can see both?
Does not having the callback cause maplibre to change the way it makes the request so that it now requires CORS when it didn't before or something?
No, CORS has always been required. /demo was set with a CORS policy of allowing * while we figured it out.
Ah right I must have been looking at every header except the exact path in the URL...
Why do we care who's fetching the style though? Normally CORS is there to control who can request sensitive information but there's nothing sensitive here?
The demo style has some invalid bits to discourage reuse because it wasn’t clear if we were willing to create a long-term expectation that the OWG would continue to host VersaTiles assets from here on out. A restrictive CORS whitelist gives us the ability to at least know who we’ll break if we ever need to move or retire the assets, without a client-side demangling step.
So basically in order to try and make it harder for people to shoot themselves in the foot we're making it impossible for developers to easily work on developing this site in the future. Great.
I mean it's not a huge issue now while it's just one additional layer but if it ever becomes the default then I definitely want it to work.
The status quo is that we need to maintain similar transform code in vectortile-website, the wiki, etc. All of this code is tightly coupled to the stylesheet.
The CORS whitelist should include your test domain and any others that come up. This is a crude mechanism to avoid creating an expectation of long-term support and leave open the possibility of decoupling the “Shortbread” layer from VersaTiles Colorful in the future. The nontechnical alternative would be to add something to the usage policy about the static assets coming with no long-term compatibility or stability guarantee. Or just break compatibility when the time comes.
Was there a reason you asked me for a new review @hlfan? Has anything changed since I last looked at this?
I've expanded the CORS list to cover localhost and tom's domain