Cross-Origin Images (CORS)
The Cross-Origin Resource Sharing (CORS) protocol imposes security restrictions on certain KeyLines functions.
How does CORS affect KeyLines?
- If you run pages from a file system instead of a web server, CORS prevents KeyLines from running in WebGL mode.
- Images from different origins are affected by the same-origin policy and won't appear on your chart, or be included in the output of chart.export() or chart.toDataURL() (now deprecated). This includes images on nodes, labels or glyphs, as well as font icons and map tiles.
For example, you may want to reference an image that doesn't originate from the same domain as the KeyLines library file. Your browser will mark it as insecure and prevent the image from being loaded. KeyLines will attempt to load the image again with the crossorigin HTML attribute set. You can use the KeyLines.corsAdapter() function to change the value of the attribute. If it still cannot load the image, it will mark it as missing and throw a SecurityError exception.
How do I fix this?
To use KeyLines in WebGL mode, you should run it from a web server, not a file system.
To make sure your images display properly, do one of the following:
- Use access-control headers to authorise KeyLines to examine the image’s contents from the server it came from.
- Proxy the resources so the browser gets them from the same origin as the KeyLines library.
Use access-control headers
Note: You can only use this solution if you can configure the web server that’s providing the resources. If they’re coming from a third-party server, you'll need to Proxy the resources.
To give KeyLines access to the resource's contents, you need to configure the remote resource’s web server to set an Access-Control-Allow-Origin header in its response.
For example, if KeyLines was at http://www.example.com/vendor/keylines, in the headers returned with the resources, you’d set:
Access-Control-Allow-Origin: http://www.example.com
Security policies can also sometimes restrict loading of inline images. From version 5.0, KeyLines loads both asset and placeholder images inline as data URI images.
To resolve this you can permit image elements to load data URIs, which should maintain the security of your application while allowing KeyLines to function:
<meta http-equiv="Content-Security-Policy" content="img-src 'self' data:" />
Proxy the resources
You can use the web server (that contains the KeyLines library file) as a proxy for resources, so you’re no longer requesting them from a different domain. How you do this depends on which web server you’re using, but the basic approach is:
- Load images from their original location.
- Send them to the web browser from the same origin as the KeyLines library.
This caching example is based on the Express web framework. To make it simpler, we’ve taken out the error-handling code:
app.get('/images/:name', function (req, res) { // look in store for picture var name = req.params.name; var filename = path.join(picdirectory, name + '.jpg'); fs.exists(filename, function (exists) { // if we have cached the file already then just pipe it back to the client if (exists) { fs.createReadStream(filename).pipe(res); } else { var outstream = fs.createWriteStream(filename, {flags : 'w'}); var url = 'http://www.example.com/path/to/images/' + name; //now stream this into the file var imagestream = request.get({uri:url}); imagestream.pipe(outstream); //when finished just pipe back to client outstream.on('close', function () { fs.createReadStream(filename).pipe(res); }); } }); });