Enabling CORS in OpenLayers

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...