问题
I am calling the Web API from the my react component using fetch when I used to run it as one application, there was no problem, but when I am running the application react separate from API, I am getting the CORS error, my fetch call is as below,
componentDidMount() {
console.log(clientConfiguration)
fetch(clientConfiguration['communitiesApi.local'])
.then((response) => {
return response.json();
})
.then(data => {
console.log(data);
let communitiesFromApi = data.map(community => { return { value: community, display: community } });
this.setState({ communities: [{ value: '', display: 'Select a Community...' }].concat(communitiesFromApi) });
}).catch(error => {
console.log(error);
});
};
and my POST call using Axios as below also.
handleDownload = (e) => {
e.preventDefault();
var formData = new FormData();
formData.append('communityname', this.state.selectedCommunity);
formData.append('files', JSON.stringify(this.state['checkedFiles']));
let url = clientConfiguration['filesApi.local'];
let tempFiles = clientConfiguration['tempFiles.local'];
axios({
method: 'post',
responseType: 'application/zip',
contentType: 'application/zip',
url: url,
data: formData
})
.then(res => {
var fileName = `${this.state['selectedCommunity']}.zip`;
saveAs(`https://localhost:44352/TempFiles/${res.data}`, fileName);
});
};
Here is my server side api code:
[HttpGet("{communityName}")]
public string Get(string communityName)
{
string rootPath = Configuration.GetValue<string>("ROOT_PATH");
string communityPath = rootPath + "\\" + communityName;
string[] files = Directory.GetFiles(communityPath);
List<string> strippedFiles = new List<string>();
foreach (string file in files)
{
strippedFiles.Add(file.Replace(communityPath + "\\", ""));
}
return JsonConvert.SerializeObject(strippedFiles);
}
[HttpPost]
public string Post([FromForm] string communityName, [FromForm] string files) //FileContentResult
{
var removedInvalidCharsFromFileName = removeInvalidCharsFromFileName(files);
var tFiles = removedInvalidCharsFromFileName.Split(',');
string rootPath = Configuration.GetValue<string>("ROOT_PATH");
string communityPath = rootPath + "\\" + communityName;
byte[] theZipFile = null;
using (MemoryStream zipStream = new MemoryStream())
{
using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
{
foreach (string attachment in tFiles)
{
var zipEntry = zip.CreateEntry(attachment);
using (FileStream fileStream = new FileStream(communityPath + "\\" + attachment, FileMode.Open))
using (Stream entryStream = zipEntry.Open())
{
fileStream.CopyTo(entryStream);
}
}
}
theZipFile = zipStream.ToArray();
}
////return File(theZipFile, "application/zip", communityName + ".zip");
string tempFilesPath = Configuration.GetValue<string>("Temp_Files_Path");
if (!System.IO.Directory.Exists(tempFilesPath))
System.IO.Directory.CreateDirectory(tempFilesPath);
System.IO.File.WriteAllBytes($"{tempFilesPath}\\{communityName}.zip", theZipFile);
//return System.IO.File.ReadAllBytes($"{tempFilesPath}\\Test.zip");
//return $"{tempFilesPath}\\{communityName}.zip";
return $"{communityName}.zip";
}
And I am getting the error for Get as below: "Access to fetch at 'https://localhost:44368/api/communities' from origin 'http://localhost:3000' 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."
回答1:
You'll need to modify your sever. You'll need to
- Enable CORS on the server side and
- Add the domain where you'll be hosting your front-end to your list of Allowed Origins.
回答2:
Adding mode: 'no-cors'
to the fetch method should do the trick
fetch(clientConfiguration['communitiesApi.local'], {
mode: 'no-cors'
})
.then((response) => {
return response.json();
})
.then(data => {
console.log(data);
let communitiesFromApi = data.map(community => { return { value: community, display: community } });
this.setState({ communities: [{ value: '', display: 'Select a Community...' }].concat(communitiesFromApi) });
}).catch(error => {
console.log(error);
});
When using axios I like to use Allow CORS: Access-Control-Allow-Origin from chrome web store, pretty handy when developing web apps on localhost
回答3:
thank you I could able to resolve this issue by implementing CORS on my Web API, here is the Code I did, but yours too work great in situations where the Web Api is already implemented and we need to consume the Api and there is not way to go and modify the api, then yours from the client side works. Here is my change in the Web API
public void ConfigureServices(IServiceCollection services)
{
string configValue = Configuration.GetValue<string>("CORSComplianceDomains");
string[] CORSComplianceDomains = configValue.Split("|,|");
services.AddCors(options =>
{
options.AddDefaultPolicy(
builder =>
{
builder.WithOrigins("http://localhost:3000");
});
options.AddPolicy("AnotherPolicy",
builder =>
{
builder.WithOrigins(CORSComplianceDomains)
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
}
And added the urls in the appsettings.json file so that any user can add the new urls without much sweating.
"CORSComplianceDomains": "http://localhost:3000|,|http://www.contoso.com"
Thank you very much - I put my answer here so that someone can get it - thanks for jumping in and helping please - I appreciated it - thank you so much.
来源:https://stackoverflow.com/questions/58403651/react-component-has-been-blocked-by-cors-policy-no-access-control-allow-origin