Puerto Puerto -4 years ago 494
React JSX Question

Fetch Post issues with CORS not getting header

This CORS has brought me to my knees again. I mean it can be so discouraging. Please understand I have been looking at all 5 million posts on this topic before you down vote me. I realize there is a lot out there on this subject. Here is my Fetch Post in my React UI code. This is running on a IIS server with the compiled JS, and just Index.html for the SPA. Im trying to call a API on the same server different port. It's the preflight that is killing me in Chrome and other modern browsers (seems fine in IE).

Here is the fetch:

return (
fetch(mypost, {
method: 'POST',
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Accept": "application/json",
},
mode: 'cors',
body: JSON.stringify({
name: this.state.value,
})
}).then(response => {
if (response.status >= 400) {
this.setState({
value: 'no greeting - status > 400'
});
throw new Error('no greeting - throw');
}
return response.text()
}).then(data => {
var myData = JSON.parse(data);
this.setState({
greeting: myData.name,
path: myData.link
});
}).catch(() => {
this.setState({
value: 'no greeting - cb catch'
})
})
);


standard prefight error we've all seen.

Fetch API cannot load http://myApiServer:81/values/dui/. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:82' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Here is the fiddle for the preflight:

OPTIONS http://myApiServer:81/values/dui/ HTTP/1.1
Host: myApiServer:81
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:82
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Access-Control-Request-Headers: access-control-allow-origin, content-type
Accept: */*
Referer: http://localhost:82/validator
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8


Now I have learned that setting no-cors will basically set a default header, which is not what I want either, I need my application/json, cause who doesn't want JSON, right? :)

I would love any advice on what I can do to resolve this issue. Basically since this is just compiled Javascript and index.html sitting on a IIS server, I need to know the best solution for dealing with these preflight options checks that seem to be happening.

******Update

I've tried adding webconfig to force the IIS server to handle the preflight. It seems like it needs to be on both ends, my UI and API??

Here is my UI Web.Config

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
</system.webServer>




And my WebApi web.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>

<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE" />
</customHeaders>
</httpProtocol>
<aspNetCore processPath="dotnet" arguments=".\dui.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="true" />
</system.webServer>
</configuration>


All Im getting now is:

fetch API cannot load http://myApiServer:81/values/dui/. Response for preflight has invalid HTTP status code 415.

Here is the fiddle for this.

req

OPTIONS http://myApiServer:81/values/dui/ HTTP/1.1
Host: myApiServer:81
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:82
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Access-Control-Request-Headers: content-type
Accept: */*
Referer: http://localhost:82/validator
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8


And response

HTTP/1.1 415 Unsupported Media Type
Content-Length: 0
Server: Kestrel
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Date: Thu, 02 Mar 2017 18:35:31 GMT

Answer Source

I have since switched to this solution for my dotnet core webAPi. I find it's cleaner since I don't need a webconfig plus the cors config which needs to be set just right for the 2 to work together. This gets rid of the cors stuff in your webConfig so your only setting it in one place, in you API application code itself.

https://www.codeproject.com/Articles/1150023/Enable-Cross-origin-Resource-Sharing-CORS-in-ASP-N

Just to give a brief summary of what's in the link.

Add to project.json

//Cross Origin Resource Sharing
"Microsoft.AspNetCore.Cors": "1.0.0"

In startup add this to your ConfigureServices.

services.AddCors(
options => options.AddPolicy("AllowCors",
builder =>
{
    builder
    //.WithOrigins("http://localhost:4456") //AllowSpecificOrigins;
    //.WithOrigins("http://localhost:4456", 
    "http://localhost:4457") //AllowMultipleOrigins;
    .AllowAnyOrigin() //AllowAllOrigins;

    //.WithMethods("GET") //AllowSpecificMethods;
    //.WithMethods("GET", "PUT") //AllowSpecificMethods;
    //.WithMethods("GET", "PUT", "POST") //AllowSpecificMethods;
    .WithMethods("GET", "PUT", 
    "POST", "DELETE") //AllowSpecificMethods;
    //.AllowAnyMethod() //AllowAllMethods;

    //.WithHeaders("Accept", "Content-type", "Origin", "X-Custom-Header");  
    //AllowSpecificHeaders;
    .AllowAnyHeader(); //AllowAllHeaders;
})
);

Also at it to Configure in Startup

//Enable CORS policy "AllowCors"
    app.UseCors("AllowCors");

Then in your controller ensure you have these references:

 using Microsoft.AspNetCore.Mvc;
 using Microsoft.AspNetCore.Cors;
 using CrossOrigin.WebService.Models.DbEntities;
 using Microsoft.EntityFrameworkCore;

And Finally add the attribute to your controller class.

[EnableCors("AllowCors"), Route("api/[controller]")]
 public class ContactController : Controller
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download