I have an application with React front-end and .NET as API using fetch.
In App.js I have:
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append('Access-Control-Allow-Origin', '*');
myHeaders.append('Access-Control-Allow-Credentials', 'true');
var raw = JSON.stringify({
"userText": e.target.value
});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow',
};
fetch("https://localhost:7101/api/Game/UserText", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
and for my controller:
[HttpPost]
[Route("UserText")]
public IActionResult GetUserText([FromBody] UserText userText)
{
Console.WriteLine(userText.userText);
return Ok();
}
and in program.cs:
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("*");
});
});
app.UseCors(MyAllowSpecificOrigins);
I have tried a few things but the error is always the same. Also tried to install the extension for Chrome but the error also stays.
The error message is:
Access to fetch at 'https://localhost:7101/api/Game/UserText' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: 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.
:7101/api/Game/UserText:1
Failed to load resource: net::ERR_FAILED
You have not provided the error anywhere, but I assume its CORS error you are talking about.
Have you tried allowing all Headers, Methods etc as below?
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins("*")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
app.UseCors(MyAllowSpecificOrigins);
Note: If you have the specific values for these parameters, its always recommended to use them. For instance, instead of WithOrigins("*"), it should be the WithOrigins(urls) which should have access to the site.
Related
TL;DR: How to actually change a request header in http-proxy-middleware?
To get around some CORS errors I set up a local proxy using the http-proxy-middleware module. In addition to setting the mode of my request to "no-cors" I need to change an additional header: "Content-Type". However, this seems to be not working. In fact, I cannot even change the response headers on a redirected (through my proxy) request. For local requests (fetching pages etc) I am able to change the response headers but even then I am unable to change the request headers.
This is my setupProxy.js:
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use((req, res, next) => {
req.header("Content-Type", "application/json");
res.header("Access-Control-Allow-Origin", "*");
next();
});
function onProxyReq(proxyReq, req, res) {
console.log("test 1");
proxyReq.setHeader("Content-Type", "application/json");
req.header("Content-Type", "application/json");
}
app.use(
"/api",
createProxyMiddleware({
target: "https://my-domain.com/",
changeOrigin: true,
onProxyReg: { onProxyReq },
// secure: true,
// on: {
// proxyReq: requestInterceptor(async (buffer, proxyReq, req, res) => {
// console.log("test 2");
// }),
// },
logger: console,
})
);
};
And this is the code that sends the request:
try {
let requestOptions: RequestInit = {
method: "POST",
mode: "no-cors",
headers: {
accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
email: { username },
password: { password },
}),
};
fetch("https://localhost:3000/api/path/to/login/api", requestOptions)
.then(async function (response) {
console.log(response);
if (!response.ok) {
setError("Error code: " + response.status.toString());
}
return response.json();
})
.then(function (response) {
console.log(response);
});
} catch (e) {
console.log(e);
}
I'm getting an error back from the API itself (the CORS avoidance is working):
Content type 'text/plain;charset=UTF-8' not supported
And indeed, when I use the Chrome inspector to look at the request, the request header is set to "text/plain;charset=UTF-8". I tried setting the response header content type to "text/plain" but even that remains untouched. But how can this be after routing the request through my proxy?
EDIT:
Ok so I found out part of the problem. Setting the mode to "no-cors" in my fetch request alters the headers. But this still doesn't explain why my proxy can't edit the request headers. When I remove the "no-cors" mode but copy the headers it produced, the server is giving me error 400 (bad request). This means it is not receiving the same request as before, but this baffles me since I copied all the headers manually.
EDIT2:
Actually, I found out that when I remove mode: "no-cors" and set the "Sec-Fetch-Mode" header to "no-cors" manually, it is still set to "cors" in the actual request!
EDIT3:
I tried sending my request through ReqBin and it works there :)! So at least we know my request is correct.
I found out that changing the "content-type" header in cors mode is simply not allowed. The solution is to first send a preflight request with the options. When this has been accepted, you can send the actual request.
You can send the request through ReqBin, it will take the necessary steps to complete the request succesfully. It will even generate code to reproduce the request for you.
var url = "https://thedomain.com/path/to/api";
var xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
console.log(xhr.status);
console.log(xhr.responseText);
}
};
var data_ = '{"email": "*************", "password": "******"}';
xhr.send(data_);
And this works! :)
Im using RapidApi to make som simple calls for fetching country data using axios. The API is paged in that the next response will have the URL for the next request. So basically i don't even have the URLs.
Problem i get the error which i have seen all over stack overflow about cors policy
Access to XMLHttpRequest at 'https://api.hybridgfx.com/api/list-countries-states-cities?page=2' from origin 'http://localhost:3002' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I tried adding the line "access-control-allow-origin": "*" but that doesn't work and i still get the same error. When i click on the URL or just run it directly on the browser i get a bunch of data but when it is called in the code it blows up . Please help.
const fetchNextResults = async (url: string): Promise<FetchResponse> => {
const options = {
method: "GET",
url: url,
headers: {
"X-RapidAPI-Key": MyKey,
"X-RapidAPI-Host": "countries-states-cities-dataset.p.rapidapi.com",
"access-control-allow-origin": "*",
},
};
const res: FetchResponse = await axios
.request(options)
.then(function (response) {
console.log(response.data);
return response.data;
})
.catch(function (error) {
console.error(error);
});
return res;
};
You can send a request throw the CORS proxy.
List of proxies.
url: <proxy url>/<my url>
Or create your own.
I am getting the cors policy error like this.
Access to fetch at 'my-url' from origin 'http://www.mywebsite.com' 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.
This is my code:
const requestOptionsBR = {
method: "POST",
headers: new Headers({
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
}),
body: JSON.stringify({
action: "user_reports",
user_id: this.state.user_id,
start_date: this.convertDate(this.state.startDate),
end_date: this.convertDate(this.state.endDate),
}),
};
fetch(my-url, requestOptionsBR)
.then((res) => res.json())
.then((data) => {
this.setState({ loadingStatus: true });
console.log("User Reports", data)
if (data.status) {
this.setState({
user_data: data.params,
loadingStatus: false,
resultRetrieved: true,
});
this.generate_download_csv_data(data.params);
}
The above is working fine in local , but in production it is not working.
How to overcome this issue?
Any help would be great.
The wildcard * isn't allowed, as you must give a specific protocol, domain and port for security reasons.
More info here...
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSNotSupportingCredentials
As the error message suggests, you can also set the option:
mode: 'no-cors'
...in your requestOptionsBR, however this will limit what you can put in your request headers.
More info here...
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#supplying_request_options
Can you help me, i have a function problematic:
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:
handleSubmit = e => {
e.preventDefault();
const data={
'username' : this.username,
'password' : this.password
}
fetch(process.env.REACT_APP_API_URL+'/api/login', data,{
method:"POST",
headers:{
'accept': 'application/json',
'Access-Control-Allow-Origin': "*",
'content-type': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Credentials': 'true',
}
})
.then(r => r.json());
}
but there is a problem with the url, how do is solve it?
enter image description here
You can't access resources when the origin you are accessing to is not the same as the origin you are using.
Fixes
As commented by #Freestyle09, you need to enable CORS policies in your backend:
In PHP:
header('Access-Control-Allow-Origin: *');
In node.js (Express):
Install cors package from npm.
var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());
This should set the headers to Access-Control-Allow-Origin: *, if you want to specify a host:
app.use(cors({
origin: 'http://yourapp.com'
}))
Read more from this answer:
https://stackoverflow.com/a/7564919/11555297
https://medium.com/zero-equals-false/using-cors-in-express-cac7e29b005b
Thank you all for your input and answers, this problem has been resolved, and it's running.
this problem is simple, I just add it in pckage.json
"proxy":"http://127.0.0.1:8000",
and i am use in axios fatch
axios({
url:'/api/login',
data:data,
method:"POST",
mode: 'no-cors',
headers:{
"Content-Type": "application/json",
"Access-Control-Allow-Origin": process.env.REACT_APP_API_URL,
"Access-Control-Request-Headers": 'Content-Type, Authorization'
}
})
.then(res => {
console.log(res);
})
.catch(err =>{
console.log(err);
})
and it's work for me thank you all (n_n)
In spring boot you can use annotation "#CrossOrigin". You will pass the url of your react app for parameter origins:
#CrossOrigin(origins = "http://localhost:3000",methods = RequestMethod.GET)
#GetMapping("/courses")
public Iterable<Course> getCourses() {
CourseService courseService=new CourseService();
return courseService.getAllCourses();
}
const https = require('https');
export async function main(event, callback) {
const options = {
method: 'GET',
host: 'https://api.challonge.com/v1/',
headers: {
'Access-Control-Allow-Methods': 'GET',
"api_key": "THE_KEY",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": true
}
};
var dataString = " ";
const response = await new Promise((resolve, reject) => {
const req = https.get(options, function (response) {
response.on('data', chunk => {
dataString += chunk;
});
response.on('end', () => {
resolve({
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify((dataString))
});
});
});
req.on('error', (e) => {
reject({
statusCode: 500,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: e.message
});
});
});
return response;
};
This is the lambda function ^
getChallongeTournaments:
handler: getChallongeTournaments.main
events:
- http:
path: tournaments/
method: get
cors: true
authorizer: aws_iam
my serverless.yml
// in a useEffect
function getChallongeTournaments(){
return API.get("byoc_users", '/tournaments.json');
}
async function onLoaded() {
try {
const testChallonge = await getChallongeTournaments();
^ The API call
According to the challonge docs this should receive 'Retrieve a set of tournaments created with your account.' and there is one created.
This is the CORS error I'm receiving: Access to XMLHttpRequest at 'https://m3heucf413.execute-api.us-east-2.amazonaws.com/prod/tournaments.json' from origin 'http://localhost:8100' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
Preflight Requests and CORS flag is raised by the Browser when there is a request from a domain/port to an entire new domain/port. If you are doing this for testing, you can disable this security flag in chrome by adding the --disable-web-security flag. Just create a shortcut of chrome to desktop > Right click > Properties >In shortcut tab - Target > Append --disable-web-security --user-data-dir="C:\tmpChromeSession" to target. This will disable the CORS check.
If you have access/control on the 3rd party api server config, what you should be doing is to add necessary response headers (Access-Control-Allow-Origin) to the response. If you do not have access, one option will be to route the request through a CORS proxy.