12

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?

19

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 imgs 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 the crossorigin 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...

| improve this answer | |
1

just after

var layer =new OpenLayers.Layer.WMS(...

add

layer.tileOptions.crossOriginKeyword = null;
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.