Request has failed when trying to load external KML file with sandcastle

Hi everyone,

I'm starting to play with sandcastle.
I try to load external kml file into sandcastle, absolutely available (https://developers.google.com/kml/documentation/KML_Samples.kml)

I slightly modify the kml example (http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=KML.html&label=DataSources) by adding these line for the toolbar

{
    text : ‘KML test’,
    onselect : function() {
        viewer.homeButton.viewModel.command();
    viewer.dataSources.add(Cesium.KmlDataSource.load(‘https://developers.google.com/kml/documentation/KML_Samples.kml’));
    }
},

Unfortunately, the console throws me a 'Request has failed' error and nothing happens.

Is there something I miss ? Does kml feature doesn't support to use external kml file ?

Thanks,

Olivier

When I press ctrl-shift-i I get this (the sandcastle console only gives the first string)

XMLHttpRequest cannot load https://developers.google.com/kml/documentation/KML_Samples.kml. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://cesiumjs.org’ is therefore not allowed access.

Sandcastle-client.js:13 RequestErrorEvent {statusCode: undefined, response: undefined, responseHeaders: undefined, toString: function}

As Hyper touched on, the problem is that Google’s server is not configured with CORS (cross-origin resource sharing). That makes it impossible for an external JavaScript application to load that particular url directly. This isn’t a problem when CORS is enabled on a server (such as GitHub pages) or you control the servers yourself (in which you can enable cors). If you were to copy KML_Samples.kml to the same server Cesium was running, it would work as well. That link above should fill in any details for you.

If you absolutely have to load uncontrolled remote data, the solution is to use a proxy. Cesium ships with a development server that contains a local proxy that will retrieve anything for you, but for production applications you will need to set up something on your own server. So if you run Cesium locally with the supplied server, the below will work:

var viewer = new Cesium.Viewer(‘cesiumContainer’);

var url = ‘http://developers.google.com/kml/documentation/KML_Samples.kml’;

var promise = Cesium.KmlDataSource.load(url,{

proxy : new Cesium.DefaultProxy('/proxy/')

});

viewer.dataSources.add(promise);

Note, this code will not run on the public cesiumjs.org server because we do not run an open proxy (which is generally a bad idea), you need to be running the local node server that ships with Cesium.

Thanks, I understand now.

Is there any other notable/annoying cases where CORS is required with Cesium apart from KML ?

Do you know any online storage platform with CORS enabled ? Or a list of them ?

It’s literally anything that deals with external data. Imagery/Terrain/KML/CZML/GeoJSON. If it’s loaded via JavaScript, it needs to either be same origin or have CORS enabled (or use jsonp, or go through a proxy), that’s just the way the web works for security reasons.

CORS is becoming pretty common, so most providers are starting to turn it on (or will turn it on if asked). Especially paid services. For free once, other than GitHub pages, which recently enabled it, I don’t know of any off the top of my head (since I don’t use them).

Well, I don't think Imagery/Terrain would be a problem. It is something that we can control.
But KML data (or GeoJSON/CZML) might as our clients may want to load external data from any sources (weather, private data, etc.) updated or not dynamically. (I'll think about that)

In the meantime, I tried to upload a kml on Github. It looks like this ressource have not CORS enable. Should I do any particular configuration to have this loadable in Cesium Sandcastle ?

https://github.com/theOgrable/KMLTest/blob/master/KML_Samples.kml

While CORS is not enabled on all of GitHub, GitHub pages do have it enabled. So if anyone is looking for a free CORS enabled hosting solution, I can recommend gh pages.