Is it possible to enable Cross-Origin Resource Sharing (CORS) in OpenLayers? If so, how?
I have a web map in OpenLayers, and I'm using an HTML canvas to render it as a PNG image. My script works great, but due to the browser's same-origin policy, I can only convert my canvas to an image if all the map tiles I've drawn to it come from the same host (e.g. sub.domain.com
).
To boost my map's loading speed, I pull tiles from an array of subdomains: a.domain.com
, b.domain.com
, etc. This greatly improves performance, working around the browser's limit of four simultaneous connections per host, but prevents me from ever converting my canvas to an image, as the tiles come from multiple hosts.
I'm trying to use CORS to work around this problem. I've set the appropriate Access-Control-Allow-Origin
response header for the tileset I serve with PHP, but this doesn't have an effect. I suspect this is due to not having the Origin
header in the request (as shown in the example on the Wiki page). It would seem that some OpenLayers configuration is required. But what? Has anyone else done this successfully?
Answer
After much grepping through the OpenLayers source, I have found it! The problem was not a missing request header, but a missing attribute on the img
elements that make up the layer, specifically crossorigin
. See MDN for the details of that attribute, and the documentation for OpenStreetMap layers for how to use it with OpenLayers (Update: Here is a little more official documentation in a more reasonable place).
To ensure that your OpenLayers img
s have that element, set the crossOriginKeyword
option in the tileOptions
value in your layer options:
tileOptions: {crossOriginKeyword: 'anonymous'}
You can set it to:
"anonymous"
- Make a "simple" CORS request."use-credentials"
- Make a "credentialed" CORS request, with cookies and HTTP authentication as required.null
- Don't include thecrossorigin
attribute, and thus don't use CORS. The default for most OpenLayers Layer classes, and the source of my troubles.
Finally, for completeness, here's a stripped-down example of how to use it with a WMS layer. Working with other layer classes is similar.
var layer = new OpenLayers.Layer.WMS('My Layer', 'http://my.server.com', {
format: 'image/png',
layers: 'my:layer'
}, {
tileOptions: {crossOriginKeyword: 'anonymous'},
transitionEffect: null
});
I hope this helps someone else!
Note: It seems that if you use this method / attribute, your tile server is required to send an appropriate Access-Control-Allow-Origin
header. Using it with a server that doesn't send that header results in the tiles not displaying. Now to get GeoServer to play along...
No comments:
Post a Comment