How to make http requests work with axios, ArcGISServer & CORS

9439
2
Jump to solution
05-07-2021 07:58 AM
Jay_Gregory
Occasional Contributor III

So I am not actually using Esri's JavaScript API in this case, but am trying to make a request using the standard axios library to an ArcGIS Server endpoint.  

const fs = "https://srvesridev4w.eon.local:6443/arcgis/rest/services/EON/FAA/MapServer/0";
      const config = {
         method: 'post',
         url: fs,
         data:{where:"LocationID='LAX'", f:"json"},
     }
     const results = await axios.request(config);

 It returns the following error:

'https://srvesridev4w.eon.local:6443/arcgis/rest/services/EON/FAA/MapServer/0' from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.

Everything in the documentation says ArcGIS Server is CORS enabled (we're using 10.6.1), and in fact using Esri's JavaScript API does not generate these CORS errors (what I'm trying to accomplish does not justify the overhead the JS API creates).  So this would indicate the issue is on the front end, but any headers I add to the request doesn't help.  Does anyone have any suggestions?

Tags (4)
0 Kudos
1 Solution

Accepted Solutions
Jay_Gregory
Occasional Contributor III

@AndyGup Indeed - I had just stumbled across that realization myself.  GET requests work.  POST requests without any data/parameters also work.  

It seems that using a JavaScript object for parameters will automatically trigger the request headers to have Content-Type: application/json, which causes the preflight request.  I don't know anything about preflight requests, how they interact with ArcGIS Server, or why this might cause the entire operation to fail, but a little bit of reading indicated that Content Type of application/x-www-form-urlencoded  does not generate this pre-flight request.  

So at least in this instance, I was able to get this to work by using a URLSearchParams object as the parameters structure of a JSON object. 

const fs = "https://srvesridev4w.eon.local:6443/arcgis/rest/services/EON/FAA/MapServer/0/query";
 const params = new URLSearchParams();
 params.append("f", "json");
 params.append('where', "LocationID='LAX'");

const config = {
   method: 'post',
   url: fs,
   data:params,
}
 const results = await axios.request(config);

This generates the response that I need, without a preflight request or any CORS errros.  Obviously using a plain JSON / JS object would be easier, and I'm unclear if that's possible in this scenario, but hopefully this will help someone who stumbles across this in the future. 

View solution in original post

2 Replies
AndyGup
Esri Regular Contributor

@Jay_Gregory  since you mention that the JS API works and axios doesn't, this is most likely an issue with axios adding a header field that is triggering preflight rather than a problem with your ArcGIS Server install.

I'm not familiar with axios, but my suggestion is figure out what header field is being added that is causing the problem and remove it. The best way to do that would be to compare the axios request headers with the JS API headers. 

0 Kudos
Jay_Gregory
Occasional Contributor III

@AndyGup Indeed - I had just stumbled across that realization myself.  GET requests work.  POST requests without any data/parameters also work.  

It seems that using a JavaScript object for parameters will automatically trigger the request headers to have Content-Type: application/json, which causes the preflight request.  I don't know anything about preflight requests, how they interact with ArcGIS Server, or why this might cause the entire operation to fail, but a little bit of reading indicated that Content Type of application/x-www-form-urlencoded  does not generate this pre-flight request.  

So at least in this instance, I was able to get this to work by using a URLSearchParams object as the parameters structure of a JSON object. 

const fs = "https://srvesridev4w.eon.local:6443/arcgis/rest/services/EON/FAA/MapServer/0/query";
 const params = new URLSearchParams();
 params.append("f", "json");
 params.append('where', "LocationID='LAX'");

const config = {
   method: 'post',
   url: fs,
   data:params,
}
 const results = await axios.request(config);

This generates the response that I need, without a preflight request or any CORS errros.  Obviously using a plain JSON / JS object would be easier, and I'm unclear if that's possible in this scenario, but hopefully this will help someone who stumbles across this in the future.