I want to be connected to a remote API through AJAX via http://localhost:5500. This is my code with a sample URL:
$.ajax({
url: "https://api.website.com/",
headers: { 'x-api-key': 'Sd6g8uieEk8couufkxv9MVp5xdDJBcTSA' },
type: "GET",
withCredentials: false,
success: function(data) { console.log(data) }
});
If I remove the x-api-key part from this code, I have not any issue and receive responses. But, as I add this section to the code, I receive CORS errors:
Access to XMLHttpRequest at
'https://api.website.com/' from origin
'http://localhost:5500' has been blocked by CORS policy: Response to
preflight request doesn't pass access control check: It does not have
HTTP ok status.
I have added different settings in the .htaccess file, but they could not solve the issue:
Header add Access-Control-Allow-Origin "http://localhost:5500"
Header set Access-Control-Allow-Credentials "true"
Header set Access-Control-Allow-Methods "GET, POST, PUT, PATCH, POST, DELETE, OPTIONS"
Header set Access-Control-Allow-Headers: *
I have read many articles, and did many changes on settings, but I could not solve the issue. May you help me please?
Related
I am facing a CORS error when trying to make a request from the client to a node server. I want to solve the issue independent of the CORS middleware. Here is the server-side code. Please let me know if I am missing something. Thanks.
const express = require("express");
const app = express();
app.get("/", (req, res) => {
res.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:5500");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT");
res.setHeader("Access-Control-Allow-Headers", "application/json");
res.send("<h1>Server is running at port 3000!<h1>");
});
app.listen(3000);
The error on the console:
Access to fetch at 'http://localhost:3000/' from origin 'http://127.0.0.1:5500' 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.
The error message you get on the console says this:
Response to preflight request doesn't pass access control check
That means that the type of requests you are sending is not a "simple" request and requires server pre-flight. Pre-flight is where the browser sends an OPTIONS request with some details about the type of request it wants to send. The server then must respond to that OPTIONS request with the right CORs info before the browser will treat the request as approved and send the actual request.
To response to a pre-flight request, you must handle an incoming OPTIONS request (not a GET or POST or PUT, but OPTIONS). This is the browser asking your server if this request would be OK to send. You can read more about pre-flight requests here on MDN. And, you can read about the difference between simple requests and pre-flighted requests here on MDN.
To code your server to accept the pre-flighted request, you could do something like this:
app.options("/", (req, res) => {
res.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:5500");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT");
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
res.sendStatus(204);
});
Depending upon what exactly the pre-flighted request is (what content-type, what method, etc...) you may need to specify additional options here. You don't show the code for the request in question here so we can't offer more specific details on that request.
Also, where you have this:
res.setHeader("Access-Control-Allow-Headers", "application/json");
that doesn't really make sense because "application/json" is a content-type, not a header. Perhaps you meant this:
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
Simple Requests
This is all spelled out in one of the above MDN references, but a Simple Request that does not require CORs pre-flight, meets the following criteria:
Http method is GET, HEAD or POST
Manually set headers on the request (apart from what the browser sets automatically) are no more than Accept, Accept-Language, Content-Language and Content-Type.
Content-Type can only be application/x-www-form-urlencoded, multipart/form-data or text/plain
Any request that doesn't meet these simple rules will require pre-flight. So, for example, if you were setting the Content-Type to application/json, that would immediately cause pre-flight because that's not one of the permitted content-types for non-preflighted requests. If your request was a GET, then there's no need to set content-type at all since you aren't sending any content with the request.
const corsOpts = {
origin: '*',
methods: [
'GET',
'POST',
],
allowedHeaders: [
'Content-Type',
],
};
app.use(cors(corsOpts));
OR you can use
app.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
I'm deploying my web app to heroku and use the following cors config on the client side.
const instance = axios.default.create({
baseURL: "https://myapp-backend.herokuapp.com",
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
"Access-Control-Allow-Origin": "https://myapp-backend.herokuapp.com"
}
});
And on the server side
const corsConfig = {
origin: ['https://myapp.herokuapp.com', 'http://localhost:3001']
}
app.use(cors(corsConfig));
But I keep getting error: "Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."
Any help would be much appreciated. Sometimes the config works but sometimes it doesn't...
The custom headers on your request (some of which are misguided) have triggered a pre-flight request for the cross origin request. This means that the browser will separately send an OPTIONS request to your server to ask it if it is OK to process this request before sending the actual request.
You have a couple of choices. First, remove the custom headers that are triggering the pre-flight request. Neither Content-Type or Access-Control-Allow-Origin are appropriate for a request you are sending from the browser. Content-Type belongs to the response and the client does not get to specify anything about what origins are allowed - that's for the server to decide.
If, for some reason, you can't stop the browser from triggering the pre-flight request, then you need to explicitly add support to your server for the OPTIONS pre-flight request. You can see how to use the cors module to do that here.
This may seem like it's been asked a million times but I've tried adding to both my frontend (React) and backend (Lambda with Node.js):
Access-Control-Allow-Headers
Access-Control-Request-Headers
Access-Control-Allow-Methods: 'GET,PUT,POST,DELETE,PATCH,OPTIONS'
But I still get this error:
Access to XMLHttpRequest at 'https://<API-INVOKE-URL>/prod/notes' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
Here's my Lambda code to handle response:
function buildOutput(statusCode, data) {
let _response = {
statusCode: statusCode,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(data)
};
return _response;
};
Here's my React code to send the POST request:
createNote(note) {
return API.post("notes", "/notes", {
headers: {
"Authorization": this.state.token,
"Access-Control-Allow-Origin": "*"
},
body: {
userid: this.state.username,
noteid: 'new',
content: 'from frontend'
}
});
I've tested my Lambda function from the console and it works (able to do CRUD to DynamoDB).
I've turned on CORS for my API Gateway resources and deployed the API.
I've tried using PostMan with:
Headers:Content/Type: application/json
Authorization: <MY_TOKEN>
*With and without* Access-Control-Allow-Origin: *
and it works: the request is sent successfully from PostMan to API Gateway results in a new item in my DynamoDB.
Actually adding some data in header converts POST request to OPTIONS.
So that, it will fire to requests:
1) with OPTIONS method
2) After getting a successfull response for OPTIONS request, the actual API call will occur.
To handle CORS you should use this in the backend.
Just to throw some light to the problem. Some browsers will do a "preflight" check to your endpoint. That means that will invoke your endpoint with OPTIONS method before making the POST method call you expect. In AWS, go to API Gateway and create a new resource , check the option to Create Options, that will create the default response headers that you need to add to your endpoint.
CORS requires a direct connection between the client and server. Your browser may be blocking the connection for security reasons.
HTTP versus HTTPS
I'd also try enabling downloads on your browser.
I believe you should also add the bearer to your token in the authorization header like:
'Bearer TOKEN_VALUE'
Thank you, guys. I've upvoted your answers/suggestions. I'm sure they're helpful in most cases. I've figured out why I had that error.
My bad: I have both resources like this:
/notes/ (method: any)
/notes/{noteid} (method: any)
and the Invoke URL is literally <path>/notes/{noteid} (with the {} included in the string) in AWS API Gateway. I was assuming it'd be something like /notes/:noteid
So the frontend code should be like this:
return API.post("notes", "/notes/{noteid}", {...}
I want to use fineuploader with cross domain.
I get Request header field Cache-Control is not allowed by Access-Control-Allow-Headers in preflight response. error.
My fineuploader config is:
request: {
endpoint: "http://api.polskieszlaki.local/4adm/zdjecia/fileupload",
},
cors: {
expected: true,
},
On my apache server in .htaccess I have
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE"
Header set Access-Control-Allow-Headers "Content-Type, Authorization"
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
I have no firther ideas to make it work.
The message cited in the question indicates you must change your .htaccess to have Cache-Control in the value set for the Access-Control-Allow-Headers response header, and because the Fine Uploader docs indicate it sends the X-Requested-With header, then altogether you need:
Header set Access-Control-Allow-Headers "Cache-Control, Content-Type, Authorization, X-Requested-With"
The MDN docs for the Access-Control-Allow-Headers response header explain:
The Access-Control-Allow-Headers header is used in response to a preflight request to indicate which HTTP headers can be used when making the actual request.
I'm getting mirriad of errors trying to do an ajax call in a reactjs app using axios. I have an api that lives at a subdomain and making calls from the main domain.
.htaccess:
Header add Access-Control-Allow-Origin: "*"
Header add Access-Control-Allow-Credentials: "true"
Header add Access-Control-Allow-Methods: "GET,HEAD,OPTIONS,POST,PUT"
Header add Access-Control-Allow-Headers: "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers"
ajax headers in reactjs (using axios):
var options = {
method: 'GET',
url: 'http://admin.mysite.com/menus/5',
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET,HEAD,OPTIONS,POST,PUT',
'Access-Control-Allow-Headers': 'Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers'
}
}
I've tried making changes to each of these but get different errors. If I have the Header add Access-Control-Allow-Origin: "*" it complains about double origins. If I remove it I I get an error about Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response other changes has responded with Access-Control-Allow-Headers is not allowed by Access-Control-Allow-Headers in preflight response
I'm using wordpress as a headless CMS and tapping into the restful api to pull the data I need. I have noticed if I removed all of this I can get my data fine but I can't post without fixing the cross domain issues.
If I remove it I I get an error about Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response other changes has responded with Access-Control-Allow-Headers is not allowed by Access-Control-Allow-Headers in preflight response
Both those error messages are happening because in your frontend JavaScript code you have this:
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET,HEAD,OPTIONS,POST,PUT',
'Access-Control-Allow-Headers': 'Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers'
}
You need to remove that entire headers option from your request code.
The reason is, all the Access-Control-Allow-* headers are response headers that servers must return. The only effect you’ll have by sending them as request headers is to cause exactly the kinds of errors cited in the question.
If the reason you’re adding them is that your .htaccess settings on the server side for the API endpoint you’re sending the request to aren’t making the server send the right response headers, then you need to figure that out and fix that on the server side. Sending additional request headers from the client side isn’t going to fix that problem.
One suggestion you might try for your .htaccess: instead of Header add, use Header set:
Header set Access-Control-Allow-Origin: "*"
Header set Access-Control-Allow-Credentials: "true"
Header set Access-Control-Allow-Methods: "GET,HEAD,OPTIONS,POST,PUT"
Header set Access-Control-Allow-Headers: "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers"
Header set tells Apache to overwrite/clobber any existing value that might already be a set for a particular header, whereas Header add tells it to just add a header with the name and value given, without overwriting any header that might already be set with that name.
So Header add can cause multiple headers with the same name to be sent in a response, in which case the browser treats it as a single header with multiple values. You don’t want that.