CORS error when trying to access NASA layer

4348
18
11-20-2020 11:39 AM
SethLutske
New Contributor III

Hi all,

I am trying to pull a layer hosted by the nasa mapserver into my arcgis js api app.  The layer is here:

https://maps.disasters.nasa.gov/ags04/rest/services/ca_fires_202008/sentinel2/MapServer

I define the layer like this:

export const SC2Sept29 = new MapImageLayer({
    url:
        'https://maps.disasters.nasa.gov/ags04/rest/services/ca_fires_202008/sentinel2/MapServer/547',
});

 And add it to the map.  This is giving me a classic CORS error:

Access to fetch at 'https://maps.disasters.nasa.gov/ags04/rest/services/ca_fires_202008/sentinel2/MapServer/547?f=json' from origin 'http://localhost:5501' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I've done a lot of reading about CORS issues, and configuring a proxy, but I'm struggling to pull this layer in. I am not having issues with my other layers, most of which are coming directly from arcgis's own servers.  When I check the response headers for this request, there are no "Access-Control-Allow-<X>" headers.  Does this mean that this is an older server that is not configured for CORS?  

registered my application and tried to establish a proxy for it , and then use esriConfig to configure my app to use it.  When I do that, the page make a request without the proxy, which throws the CORS error.  But then it makes the request again with the proxied URL:

https://utility.arcgis.com/usrsvcs/appservices/LmNXFvAttVIu5FBo/rest/services/World/Utilities/GPServ...

But I'm getting a 403:forbidden error on that request.  Though I may not have configured my proxy correctly in my app.  Configuring a proxy requires that you select a service, like "Geocoding," "Routing Utilities," etc.  I tried "Routing Utilites," and "Service Area," but I'm sort of stumbling in the dark.

 

I'm not sure if I'm going about this all wrong.  How can I get these NASA layers in my app?  I was under the assumption that NASA's layers are available for public consumption.  Is that incorrect?

 

Thanks for reading

Tags (2)
18 Replies
SethLutske
New Contributor III

Yes I am aware of that.  I was playing around with the /547 at the end and happened to copy that code into this question.  I am actually using the sublayers property in my code to property target the right sublayers, I just wrote that url into this post without double checking it.  Regardless of the /id, I'm getting the CORS errors.  Thanks for pointing this out though.

 

 

RobertScheitlin__GISP
MVP Emeritus

OK, so it is an issue which how you are proxing then. Here is my code that works fine:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
  <title>MapImageLayer - set renderers on sublayers - 4.17</title>

  <link rel="stylesheet" href="https://js.arcgis.com/4.17/esri/css/main.css">
  <script src="https://js.arcgis.com/4.17/"></script>

  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }
  </style>

  <script>
    require([
        "esri/Map",
        "esri/views/MapView",
        "esri/layers/MapImageLayer",
        "esri/core/urlUtils",
        "dojo/domReady!"
      ],
      function(
        Map, MapView, MapImageLayer, urlUtils
      ) {

        urlUtils.addProxyRule({
          urlPrefix: "maps.disasters.nasa.gov",
          proxyUrl: "proxy/proxy.ashx"
        });

        var layer = new MapImageLayer({
          url: "https://maps.disasters.nasa.gov/ags04/rest/services/ca_fires_202008/sentinel2/MapServer",
          sublayers: [
          {
            id: 549
          }]
        });
        
        var map = new Map({
          basemap: "dark-gray",
          layers: [layer]
        });

        var view = new MapView({
          container: "viewDiv",
          map: map,
          zoom: 6,
          center: [-83.114, 36.921]
        });
      });
  </script>
</head>
<body>
  <div id="viewDiv"></div>
</body>
</html>
SethLutske
New Contributor III

Is the proxy/proxy.ashx coming from the esri dotnet proxy?  I am not familair with .NET, php, or java.  Is it as simple as copying the files of the git repo into a directory in my project and referenceing that file?

SethLutske
New Contributor III

I am struggling to get this to work.  I have tried the DotNet and PHP proxy, but as I am not experienced in either language, I'm not sure if I'm doing it right.  My network tab shows that when attempting to retrieve the layer, it is indeed being routed through the proxy, but the response is simply the text of the proxy file itself, and I get an "Unexpected token < in JSON at position 0" error in my console. 

RobertScheitlin__GISP
MVP Emeritus

Seth,

   Using either Proxy does not require any experience in that language. The Proxy is a already build and configurable web application. All you have to know is how to deploy a web application to your web server. If your web server is IIS then you should just stick with the .Net proxy. Look in the proxies readme.md file for how to set it up and test the proxy using the ping url. https://github.com/Esri/resource-proxy/blob/master/DotNet/README.md

The only file you alter is the proxy.config. In there I have this 

<serverUrl url="https://maps.disasters.nasa.gov" matchAll="true" />

In my JS Development environment I have a C:\JS_Workspace setup as a virtual directory in IIS that allows me to run any html page from that location using my development machine url or localhost inside the C:\JS_Workspace I have the proxy folder with the proxy.ashx, proxy.config, etc. Because I have my xyz.html inside the C:\JS_Workspace and the proxy folder is also under C:\JS_Workspace then the code I provided earlier just works (no CORs errors).

SethLutske
New Contributor III

Sorry to keep dragging this out.  I feel like there is a lot of assumed knowledge here and I'm trying to find my way.  I have experience setting up server-side applications with node.js, and my dev environment has always been on a mac.  Until this, I had never heard of IIS. 

I read through those readmes thorougly, but I can't seem to connect the dots to get things to work in my local dev environment, let alone anticipate how to set it up for my target production environment.  (My intention was to simply publish my application to github pages as a static web page, but if I need to deploy a server-side app as well to use a proxy, I suppose I could deploy it on heroku or AWS).  I followed your suggestion of changing the url in the proxy.config for both the php and .net proxies, but still no change.  I am testing small snippets like the HTML you posted in VS Code with vscode live server.  My local environment for my actual application uses webpack-dev-server.  I'm at a loss for how to prepare a proxy for use with any of these environments.  I feel I'd do well if there was a nodejs version of the proxy, as then I could at least understand the proxy code and how to run it.

At this point I've even tried putting in https://cors-anywhere.herokuapp.com/ a popuplar CORS workaround, as the proxyUrl in urlUtils.  Even with this, the response is returning the content of the proxy, not the resource I want my proxy to communicate back to my page.  You can see what I'm working with in my pratice git repo, here.  I don't want to give up on this, but I feel there's a huge gap in documentation and I'm having a hard time agreeing with your statement that 'using either proxy does not require any experience in that language.'

I appreciate your time and your knowldge.

kattoor
New Contributor II

Please let me know if you have got this working, I am also facing the same issue with the proxy (jsp/php/asp) services. But I could able to make the jsp proxy working, if I deploy both application code and proxy code in same server. 

RobertScheitlin__GISP
MVP Emeritus

It is absolutely standard to have4 the proxy and the app on the same server. Otherwise you will continue to have cors issues.

SethLutske
New Contributor III

I did get it working, but not with any of the proxies provided by ESRI.  I wrote my own quick nodejs server and used an instance of cors-anywhere to attach the proper cors headers.  Here's the code for that:

const express = require('express');
const cors = require('cors');
const corsAnywhere = require('cors-anywhere');
const path = require('path');

const port = process.env.PORT || 3030;
process.env.PWD = process.cwd();

var app = express();

let proxy = corsAnywhere.createServer({
	originWhitelist: [], // Allow all origins
	requireHeaders: [], // Do not require any headers.
	removeHeaders: [], // Do not remove any headers.
});

app.use(cors());

app.get('/proxy/:proxyUrl*', (req, res) => {
	req.url = req.url.replace('/proxy/https:/', '/https://');
	proxy.emit('request', req, res);
});

app.use(express.static(path.join(process.env.PWD, 'dist')));

app.listen(port, () => {
	console.log(`App listening on port ${port}`);
});

The proxy url replace line is a little weird, you can read more about why I had to do that here: https://stackoverflow.com/a/65217801/12010984

Then when I create my layer, I prefix the layer url with /proxy/, and it works.  As you can see, this same server which provides the proxy also serves the static front end files from the dist folder.  

For some reason NASA returns the image responses verrryy slowly, but it does work with no CORS errors.  Hopefully that helps you.