CesiumGS / cesium

An open-source JavaScript library for world-class 3D globes and maps :earth_americas:
https://cesium.com/cesiumjs/
Apache License 2.0
12.86k stars 3.47k forks source link

Cesium/ThirdParty/Workers/inflate.js blocked by CORS #8819

Open thecodehustler opened 4 years ago

thecodehustler commented 4 years ago

I'm trying to add a KML datasource, that's when I met this. THIS Seems that the access from localhost is blocked by CORS. Importing Cesium.js from an external CDN (jsDelivr) won't work either.

Is there any possible way to workaround this?

OmarShehata commented 4 years ago

I am able to use CesiumJS from CDN running in localhost. Following the getting started guide, I have the following code in an HTML file, and I serve it locally at localhost:8080, it succeeds:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <script src="https://cesium.com/downloads/cesiumjs/releases/1.68/Build/Cesium/Cesium.js"></script>
  <link href="https://cesium.com/downloads/cesiumjs/releases/1.68/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
  <div id="cesiumContainer" style="width: 700px; height:400px"></div>
  <script>
    var viewer = new Cesium.Viewer('cesiumContainer');
  </script>
</body>
</html>

Can you describe more details about your local setup?

thecodehustler commented 4 years ago

@OmarShehata Thanks for your reply. I can use Cesium.js, but a worker (inflate.js) failed to load, thus I cannot load KMZ files. when I add

    viewer.dataSources.add(Cesium.KmlDataSource.load('./gadm36_CHN_3.kmz'));

to my code, mentioned error happens. Firefox still complains: 图片

I use Python to start a local HTTP server.

python -m http.server --directory . --bind 127.0.0.1 7999
OmarShehata commented 4 years ago

Thansk @thecodehustler , I can reproduce by loading a KMZ as well to trigger loading that worker.

As far as I can tell this is a similar issue to https://github.com/CesiumGS/cesium/issues/8286 where we need to adjust our CORS settings. We're looking into it.

mramato commented 4 years ago

I spent some time looking into this. This is indeed a bug, but it is an issue specific to the zip.js code we use for decompression and not our server configuration. Workers have to be written a special way in order to work properly over CORS and zip.js doesn't do it.

Long story short, you can't use a CORS url with a worker directly, you need a "bootstrapper" worker that wraps the real worker in an importScripts call. While not ideal, the workaround is to tell our thirdparty zip code NOT to use webworkers and include the required libraries it needs yourself. Here is a full example I created by replacing Cesium's local HelloWorld.html with the below content:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <script src="https://cesium.com/downloads/cesiumjs/releases/1.68/Build/Cesium/Cesium.js"></script>
  <script>
    // Required for direct inflate/default inclusion to work.
    window.zip = {};
  </script>
  <script src="https://cesium.com/downloads/cesiumjs/releases/1.68/Build/Cesium/ThirdParty/Workers/inflate.js"></script>
  <script src="https://cesium.com/downloads/cesiumjs/releases/1.68/Build/Cesium/ThirdParty/Workers/deflate.js"></script>
  <link href="https://cesium.com/downloads/cesiumjs/releases/1.68/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>

<body>
  <div id="cesiumContainer" style="width: 700px; height:400px"></div>
  <script>
    //Disable web workers for zip library
    Cesium.zip.useWebWorkers = false;

    //Grab imported inflate/deflate classes and make Cesium's
    //internal zip library use them
    Cesium.zip.Inflater = window.zip.Inflater;
    Cesium.zip.Deflater = window.zip.Deflater;

    var viewer = new Cesium.Viewer('cesiumContainer');
    viewer.dataSources.add(
      Cesium.KmlDataSource.load(
        "SampleData/kml/gdpPerCapita2008.kmz",
        {
          camera: viewer.scene.camera,
          canvas: viewer.scene.canvas,
        }
      )
    );
  </script>
</body>

</html>

Obviously the workaround is not perfect because it moves zip decompression to the main thread, but that is okay for many use cases. We should definitely put in a real fix long term that probably involves updating/modifying the thirdparty library we use (or switching to a different one)

RiVeND commented 2 years ago

Is there any progress on a permanent fix for this? I have tried using the workaround on 1.93 (though inflate.js and deflate.js look like they no longer exist and I've had to replace them with pako_inflate.min.js and pako_deflate.min.js, which removes the sort of error messages that thecodehustler reported but it is now complaining that: (my site) may not load data from https://cesium.com/downloads/cesiumjs/releases/1.93/Build/Cesium/ThirdParty/Workers/z-worker-pako.js I have tried adding an explicit include for the z-worker-pako.js file but this isn't having any effect.

RiVeND commented 2 years ago

Slight update - I've found that if I go back to version 1.84 then the KLM loads fine. Moving to 1.85 or anything later breaks it with the errors reported above.