CORS: No 'Access-Control-Allow-Origin' header is present even though response is 200? - https

I am trying to make a cross domain request from my React app (localhost:3000) to my Laravel PHP app (localhost:8000). I believe I have the back end set up to accept cross domain requests. I used this: https://github.com/barryvdh/laravel-cors
I seem to have all the parameters from this answer (https://stackoverflow.com/a/38087435/1555312), so I don't get why mine doesn't work. I actually see a 200 response + the expected body when I use the chrome console.
Here is the error I see in my console:
Failed to load http://localhost:8000/api/v1/upload-sessions: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
Here is how my POST request looks like:
OPTIONS request:
POST request:
Expected response is sent, even though it complains about the CORS issue:

You need to set Access-Control-Allow-... on the response, not the request.
Once you remove that from the request, you probably won't need a pre-flight, so the OPTIONS request won't happen.

Related

CORS Issue on iframe to current Laravel route

I am pulling in an Iframe that has javascript included in it. I have installed the fruitcake cors package and set the config file to be wide open. I also added the "Access-Control-Allow-Origin' header to the xmlhttp request just in case because I am confused on who is actually denying the request. Here is the error I am getting -
Access to XMLHttpRequest at "https://site-that-i-am-posting-to" from origin "https://where-the-iframe-is-sourced-from" has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present of the requested resource.
Figured it out. I needed to add the correct request headers to the xmlhttprequest like this -
xhrapi.setRequestHeader('Origin', 'https://site-posting-from.com');
xhrapi.setRequestHeader('Access-Control-Request-Method', 'POST');
And then it worked. Thanks to anyone that tried to help!

CORS policy with Google Storage allows from my origin, but no 'Access-Control-Allow-Origin' header is present

I'm new to CORS configuration and trying to figure this out, but my set up looks like it is right according to the documentation. I'm hoping you can help me see what I've missed. My code is trying to upload (PUT) a file directly to google storage using a signed url.
Access to XMLHttpRequest at
'https://storage.googleapis.com/herdboss-dev.appspot.com/uploads/152/152-owner-152-61.jpg?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Go...'
from origin 'https://herdboss-dev.appspot.com' has been blocked by
CORS policy: No 'Access-Control-Allow-Origin' header is present on the
requested resource.
I've set the CORS policy on my Google Storage Bucket (added line breaks for readability):
% gsutil cors get gs://herdboss-dev.appspot.com
[{
"maxAgeSeconds": 3600,
"method": ["GET", "HEAD", "PUT"],
"origin": ["https://herdboss-dev.appspot.com"],
"responseHeader": ["X-Requested-With", "Access-Control-Allow-Origin", "Content-Type"]
}]
According to my chrome inspector, the pre-flight request happens and returns the proper methods and headers (as far as I can tell). Also, as a side note, I noticed the PUT shows up in my Chrome inspector before the OPTIONS, but the timestamps show the OPTIONS is sent first.
When the OPTIONS call happens, Google Storage correctly responds and says it can support my request methods GET, HEAD, PUT and origin https://herdboss-dev.appspot.com:
THE PUT REQUEST
However, when the PUT happens, Google Storage does not respond with the proper Access-Control-Allow-Origin header:
What am I missing or doing wrong? I'm able to use these signed urls to PUT files directly into my Google Storage bucket when I make a direct http call, so I know the signed urls work. I'm just running into this CORS problem. It's a new thing for me, I haven't dealt with it before, but it seems like I'm setting all of the things I should be setting.
**EDIT 1:
I tried setting my allowed origins to * just as a test and I was still rejected with the same No 'Access-Control-Allow-Origin' header is present on the requested resource. The Chrome inspector showed the OPTIONS response did send back my * for allowed origins, but it still didn't work and still gave the same error.
Figured it out.
Short version: Chrome's error message about CORS was a red herring. Google Storage was rejecting the request which was being interpreted as a CORS violation.
Long version:
I noticed in Chrome's inspector that the response to my PUT request had a content length of 862 characters, but Chrome wasn't showing me any response. I opened Firefox and tried the upload process again and it failed with the same error messages about CORS and Access-Control-Allow-Origin. However, in Firefox's network inspector, I was able to see the raw response body!
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Message>
<StringToSign>.....</StringToSign>
<CanonicalRequest>PUT
/herdboss-dev.appspot.com/uploads/152/152-owner-152-72.png
X-Goog-Algorithm=GOOG4-RSA-SHA256&....;X-Goog-SignedHeaders=content-type%3Bhost
content-type:image/png
host:storage.googleapis.com
content-type;host
UNSIGNED-PAYLOAD
</CanonicalRequest>
</Error>
My theory is that when Chrome and Firefox do the pre-flight CORS checking and then issue the PUT request and receive a 403 response code that it is responding as if it is a CORS problem even though the problem was not CORS related and the preflight response DID actually have the Access-Control-Allow-Origin header.
From here, I was able to quickly diagnose the problem by checking my url signing code against the request. I noticed that when created the signed upload url that I was requiring a Content-type of application/octet-stream but when the javascript in the browser was doing the PUT request that it was setting the Content-type to image/png. I updated my javascript to force the Content-type to match application/octet-stream and then the request succeeded.

API Gateway: Can't Enable CORS

I can't Enable CORS on my API Gateway instance, this is how it looks:
1. Settings:
2. Result:
I've tried a bunch of things like checking the DEFAULT 4XX and DEFAULT 5XX and manually inputting the Access-Control-Allow-Methods as suggested in some posts.
If I hover over the error I get: Invalid Response status code specified.
I'm able to GET using my browser but POST can only be done from Postman. My ReactJS website won't post either, throwing:
Access to XMLHttpRequest at <ENDPOINT> from origin <S3-REACT-BUCKET> has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I've read that I have my React app should send the CORS headers (haven't got to that) but I can't even Enable CORS in the API Gateway!
That was because No Method Response
You shouldn't manually go on the console to enable CORS. Instead follow this guide from the serverless framework.
In short:
set cors: true in your http event
return {'Access-Control-Allow-Origin': '*','Access-Control-Allow-Credentials': true} in your handler

What does "Response to preflight request doesn't pass access control check" mean?

I have receive the following response when trying to access an API via an ajax request in Chrome:
"Failed to load http://localhost:1880/api_resource: 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:3000 is therefore not allowed access."
As you can see from the message, both client and API are running locally.
I understand that this situation relates to a CORS cross origin request. I see that there are similar questions about this on stack overflow, but from those answers I do not understand what the message is telling me and where it comes from.
Specifically I understand that the response header "Access-Control-Allow-Origin" must be set (typically to '*') to allow access to the API from a different domain to the one on which the API is being served. But the message seems to relate to the request and not the response, and as far as I am aware, no request ever reaches the API.
What is a preflight request and how is it failing?
As I now understand it, modern browsers will issue a 'preflight' request before the actual cross origin request. This preflight request uses the 'OPTIONS' HTTP verb along with the CORS headers Access-Control-Request-Method and Access-Control-Request-Headers to which it expects to see a response with valid Access-Control-Allow-Origin in the header that indicates that the server understands the CORS protocol and will allow the actual (GET/POST/PUT) request.
The message "Response to preflight request doesn't pass access control check" means that the browser did not see a valid "Access-Control-Allow-Origin" header in the Options response.
In my case this was because the server (implementing a REST API) was set up to respond correctly to PUT and POST requests but not setup to respond to OPTIONS requests with the CORS headers.
in my case the problem was for my website address, i'm calling all apis from the same server but i got this error.
my website address is sateh.ir
so im my ajax request i set the url: http://sateh.ir/api/...
after getting this error and working on it for some hours, i got that i had to set ajax url to: http://www.sateh.ir/api/...
i dont know why my website cant understand that i'm calling api from the same server if i dont put 'www', but that was my problem at all.

Angular resource how to keep ajax header and enable cors at the same time

In my ng-resource files, I enable the ajax header:
var app = angular.module('custom_resource', ['ngResource'])
app.config(['$httpProvider', function($httpProvider) {
//enable XMLHttpRequest, to indicate it's ajax request
//Note: this disables CORS
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
}])
app.factory('Article', ['$resource', function($resource) {
return $resource('/article/api/:articleId', {articleId: '#_id'}, {
update: {method: 'PUT'},
query: {method: 'GET', isArray: true}
})
}])
So that I can separate ajax and non-ajax request and response accordingly (to send json data like res.json(data), or to send the entire html page like res.render('a.html')
for example, in my error handler, I need to decide to render error.html page or to just send a error message:
exports.finalHandler = function(err, req, res, next) {
res.status(err.status || 500)
var errorMessage = helper.isProduction() ? '' : (err.message || 'unknown error')
if (req.xhr) {
res.json({message: errorMessage})
}
else {
res.render(dir.error + '/error_page.ejs')
}
}
But now I need to do CORS request to other sites. Is it possible to do CORS request while keeping the ajax header? or other ways I can identify ajax and non-ajax request from server?
In case my question is not clear, heres a relevant article about angular and CORS
http://better-inter.net/enabling-cors-in-angular-js/
Basically, we need to delete xhr header to enable cors for other server, but I need the header for my own server
EDIT 2:
today I tried integrating google map and I got this error:
XMLHttpRequest cannot load http://maps.googleapis.com/maps/api/geocode/json?address=Singapore&sensor=false. Request header field X-Requested-With is not allowed by Access-Control-Allow-Headers.
Setting custom headers on XHR requests triggers a preflight request.
So, it doesn't disable CORS but your server is most likely not handling the preflight request.
Inspired from this post: https://remysharp.com/2011/04/21/getting-cors-working
The solution should be to use the cors module and add the following to your node.js code before your routes:
var corsOptions = {
origin: true,
methods: ['GET', 'PUT', 'POST'],
allowedHeaders: ['X-Requested-With','Content-Type', 'Authorization']
};
app.options('*', cors(corsOptions)); //You may also be just fine with the default options
You can read more at: https://github.com/expressjs/cors
you may try to use cors package
First, to address you primary concern is it possible to do CORS request while keeping the ajax header?: the answer is YES, provided the sites you are accessing allow requests from you or any other external clients at all.
You wrote:
//Note: this disables CORS
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
But I don't understand what you mean by, it "disables CORS". The X-Requested-With header is not a standard header, and the known effect of adding a non-standard header to a request (made from a browser) is the triggering of a pre-flight request [3].
If the other sites you are interested in would set their servers to refuse processing of requests that do not originate from their own domain, then whether you set that header or not, your request should fail.
It seems everything is working fine for you, for requests sent to you own server. Otherwise you can solve the problem by appending the Access-Control-Allow-Origin header in your server responses as follows:
if you need to allow requests from specific domains
response.set("Access-Control-Allow-Origin", "one-host-domain, your-host-domain, some-other-host-domain"); // second argument is a comma-delimited list of allowed domains
(It may be better for you to actually check the request object for the origin, and if it's permitted based on presence in a pre-determined list, then send back the exact same origin).
If you need to permit all requests regardless of its origin
response.set("Access-Control-Allow-Origin", "*");
That should do, and I hope it clears your doubts for you.
More info on handling CORS when using AJAX: 0, 1 & 2.
EDIT
Following exchanges in the comment, I add the following points to support this answer further.
As it is today, the only side that needs disabling/enabling CORS in the client-server system is the server. All modern browsers allow cross origin requests by default and you don't need to do anything additional to support that capability. I understood that you're adding a custom header to distinguish AJAX requests from the rest?? AFAIK, that header changes nothing about how requests are made by browsers.
Here is how all cross-origin requests are handled by browsers today: for all request methods (but usually with the exception of GET), browsers send a pre-flight request with the OPTION method. If the destination server allows it, the actual request is then sent, otherwise the request fails. In the case where the servers, responds with a refusal there's nothing you nor whatever library you use can do about it. This is the fact from my own experience.
There are 3 solutions that come to my mind:
1. Ask site's admin to enable x-requested-with header in CORS.
2. Use proxy server.
3. Send request without x-requested-with header.
This article should make it clear how CORS works and how to make CORS requests.
Particularly "Simple requests" section and "Access-Control" section, especially access-control-allow-headers description is important in this case.
As it says: for simple requests access-control-allow-origin is enough. However if the request includes custom header (a header which is not included by default, such as x-requested-with header), the preflight request is triggered, and server's response to this request should enable this custom header in access-control-allow-headers by setting its value to either "*" or to the name of a custom header (x-requested-with).
Hope it makes it a little bit clearer.

Resources