I'm trying to send a file to rackspace via AJAX. This is my first time looking at CORS. I see in the documentation the option to send a preflight request, however since I personally set the header and know that my origin is valid I'm trying to forgo, these are the headers from my upload endpoint:
HTTP/1.1 204 No Content
Content-Length: 0
X-Container-Object-Count: 2
Accept-Ranges: bytes
X-Container-Meta-Access-Log-Delivery: false
X-Container-Meta-Access-Control-Expose-Headers: etag location x-timestamp x-trans-id
X-Timestamp: 1401852621.29287
X-Container-Meta-Access-Control-Allow-Origin: h ttp://localhost:8080**<-- (manually added the space after "h" so stackoverflow would let me submit)
X-Container-Bytes-Used: 5572910
Content-Type: text/plain; charset=utf-8
X-Trans-Id: txfc64055cb1114b6fb0ef6-0053a77a46ord1
Date: Mon, 23 Jun 2014 00:52:22 GMT
However, whenever I try to send the request it immediate fails in chrome with the following message:
XMLHttpRequest cannot load [**I'm redacting my actual endpoint**]. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'h ttp://localhost:8080' is therefore not allowed access.
Here are my request headers:
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryZSg4nEq8EDaXQQBu
Origin:h ttp://localhost:8080
Referer:h ttp://localhost:8080/tools/artwork
<-- (manually added the space after "h" so stackoverflow would let me submit)
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36
What am I missing? Is preflight request required even if you know origin is permitted? I never see a packet come back to seems like Chrome isn't sending?
Yes, preflight is required any time your CORS request is not of the "simple" variety--meaning, you have a method other than GET, HEAD, or POST, a content type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, or your request sets a custom header.
Regardless of this, however, the response you've pasted does not contain Access-Control-Allow-Origin (it has X-Container-Meta-Access-Control-Allow-Origin) in the first place, which is why your request was rejected.
In your server,add Access-Control-Allow-Origin: http://foo.example header.
For example in Spring Controller, response.setHeader("Access-Control-Allow-Origin", "http:localhost:8080");
Additional things,
Access-Control-Allow-Origin: http://foo.example // you can add as many urls separated by commas or '*' to allow all urs
Access-Control-Allow-Methods: POST, GET, OPTIONS // Request method options separated by commas
Access-Control-Allow-Headers: X-PINGOTHER
Access-Control-Max-Age: 1728000 // expiration in milliseconds
Refer this MDN site.
Related
I'm accessing nasa pictures with their public api, but i get this error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at
[nasa api website] (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
But when i inspect their response header, the ‘Access-Control-Allow-Origin’ is present and set to '*', here you can see it:
RESPONSE HEADERS:
Access-Control-Allow-Origin *
Age 0
Cache-Control max-age=0, private, must-revalidate
Content-Encoding gzip
Content-Type application/json; charset=utf-8
Date Sat, 28 Mar 2020 14:37:13 GMT
Etag W/"e26hidden..."
Referrer-Policy strict-origin-when-cross-origin
Server openresty
Strict-Transport-Security max-age=31536000; includeSubDomains
Vary Origin
Via https/1.1 api-umbrella (ApacheTrafficServer [cMsSf ]), 1.1 vegur
X-Cache MISS
X-Content-Type-Options nosniff
X-Download-Options noopen
X-Frame-Options SAMEORIGIN
X-Permitted-Cross-Domain-Policies none
X-RateLimit-Limit 1000
X-RateLimit-Remaining 999
X-Request-Id 00c8c415-37ad-474b-bfbd-8e968d60f37f
X-Runtime 0.125778
X-Xss-Protection 1; mode=block
REQUEST HEADERS:
Accept text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding gzip, deflate, br
Accept-Language en-US,en;q=0.5
Connection keep-alive
Host api.nasa.gov
If-None-Match W/"e26chidden.."
Upgrade-Insecure-Requests 1
User-Agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:74.0) Gecko/999991 Firefox/74.0
There’s a common mistake that can happen when specifying a URL for a cross-origin request in code, and the mistake can cause browsers to end up reporting a CORS error when in fact the problem is simply an easy-to-overlook mistake in the request URL itself.
The mistake is just a missing "s": using "http" as the URL protocol part instead of "https".
That missing "s" causes the server you sent the request to respond with a 3xx redirect to the equivalent https location of that URL. But the problem is: by default, many/most servers won’t include the Access-Control-Allow-Origin header in 3xx responses. So the browser gets that 3xx, but because it lacks the Access-Control-Allow-Origin header, the browser refuses to let your code follow the redirect; instead the browser stops right there and emits a CORS error.
So when you encounter a case like this, the way to troubleshoot it is: Open the Network pane in devtools and inspect the response. Check the response status code shown there and check the response headers. If the cause is the mistake described in this answer, you’ll see a Location response header. That value is the URL to which the server is trying to redirect the request.
And when you look at the Location value, you might initially think it’s exactly the same as the request URL you have in your code, because it’s easy to overlook that the difference is just that single missing "s". But of course if you take the URL in that Location value and replace the request URL in your frontend code with it, and it works, then the difference becomes apparent.
So in the case of the URL in this question, the problem was just, the frontend code specified a http://mars.jpl.nasa.gov URL that should instead be a https://mars.jpl.nasa.gov URL.
I have a JavaScript application let's say that it is deployed on portal.example.com.
That includes a <script> tag that loads source that is served from assets.example.com.
That JavaScript file makes an HTTP request to an API on admin.example.com
This API request is erroring due to CORS pre-flight failing.
Failed to load http://admin.example.com/v0/user/navigation: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://portal.example.com' is therefore not allowed access.
The actual OPTIONS request is as below
OPTIONS /v0/user/navigation HTTP/1.1
Host: admin.example.com
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://portal.example.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36
Access-Control-Request-Headers: authorization,x-correlation-id,x-user-domain
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,en-GB;q=0.8
The actual OPTIONS response is as below
HTTP/1.1 200
Allow: GET
Access-Control-Allow-Headers: authorization,x-correlation-id,x-user-domain
Access-Control-Allow-Methods: GET
Access-Control-Allow-Origin: http://portal.example.com
Vary: Origin
Content-Length: 0
Date: Tue, 20 Feb 2018 12:12:19 GMT
Set-Cookie: 97d2c19dadc3933a73dce9bec0748df1=5a15895c5e0f5b526c177132cb4aa666; path=/; HttpOnly
Cache-control: private
X-RBT-SCAR: 10.127.48.7:777511903:1000
I think the issue is because the request is actually coming from a script served from assets.example.com is making the request. So I should be returning Access-Control-Allow-Origin: http://assets.example.com in the OPTIONS response. However, I have followed the advice of W3C.
The Access-Control-Allow-Origin header indicates whether a resource can be shared based by returning the value of the Origin request header, "*", or "null" in the response.
So am I misunderstanding CORS, or is the browser sending the Origin of the main executing URL and not the URL of the script making the request?
UPDATED
GET response
HTTP/1.1 200
X-Correlation-Id: 8978b245-081a-4c4a-b4c9-73f2920ab55c
Content-Type: application/vnd.example+json
Transfer-Encoding: chunked
Date: Tue, 20 Feb 2018 13:22:39 GMT
Set-Cookie: 97d2c19dadc3933a73dce9bec0748df1=dc4e3543c3071d752959e7176c5e4d29; path=/; HttpOnly
Cache-control: private
X-RBT-SCAR: 10.127.48.7:778160108:2000
No 'Access-Control-Allow-Origin' header is present on the requested resource.
That means that 'Access-Control-Allow-Origin' header is missing, not that your domain is not allowed.
If you didn't have permission, you would see something like
The 'Access-Control-Allow-Origin' header has a value 'http://www.example.com' that is not equal to the supplied origin.
So, to solve your problem you need to configure your GET response to provide the necessary CORS headers as well as the OPTIONS response.
In your edited question the GET response headers doesn't provide anything for the Access-Control-* so that's why you get the error!
Your CORS preflight is not failing - you're getting a 200 response and all the required CORS response headers...
However, you're not returning any of the CORS response headers in the GET response - that is what's failing. At a minimum, you need to return a Access-Control-Allow-Origin response header which matches the one returned in the OPTIONS response.
So just include this in your GET response and you'll be fine:
Access-Control-Allow-Origin: http://portal.example.com
Finally, the Origin request header is added by the browser, and trust me - it's correct. But it really doesn't matter what value is sent, since all that is required is that the Access-Control-Allow-Origin response header matches the Origin request header (either by having a value of '*' or exactly matching the Origin value).
I am building a prototype application that does an Ajax GET call via javascript in an html page. The configuration I am using is:
Windows/Apache Web Server (XAMPP)
MongoDB
Chrome Browser
All running on the same Windows7(32) machine. The mongodb server and data are installed in the C:\ path; the Apache server is in the C:\XAMPP path. I can access the MongoDB server directly through the browser; for example a call to:
localhost:28017/ database/ collection
will return the collection's data in json format.
However, if I try running the same Ajax call in javascript via an html page, I get the error:
XMLHttpRequest cannot load http:// localhost:28017/ database/ collection. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http:// localhost' is therefore not allowed access.
I modified/inspected my httpd.conf file and have the following set for :
<Directory />
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "X-Requested-With, Content-Type,
Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
AllowOverride none
Require all denied
</Directory>
I also confirmed that the headers_module is being loaded:
LoadModule headers_module modules/mod_headers.so
However, this does not work. The port number is changing between the html and the ajax call (80 vs. 28017), therefore a new domain.
Here is the script code:
var xhr = new XMLHttpRequest();
console.log("xhr open")
xhr.open("GET", "http://localhost:28017/ database/ collection/", false);
xhr.send();
Here are the response headers from the html call:
Accept-Ranges:bytes
Access-Control-Allow-Headers:X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding
Access-Control-Allow-Methods:POST, GET, OPTIONS, DELETE, PUT
Access-Control-Allow-Origin:*
Access-Control-Max-Age:1000
Connection:Keep-Alive
Content-Length:564
Content-Type:text/html
Date:Mon, 09 Jan 2017 23:47:06 GMT
ETag:"234-545b12ed82b40"
Keep-Alive:timeout=5, max=100
Last-Modified:Mon, 09 Jan 2017 22:49:41 GMT
Server:Apache/2.4.23 (Win32) OpenSSL/1.0.2h PHP/5.5.38
And all the headers from the xhr call:
General
Request URL:http://localhost:28017/ database/ collection/
Request Method:GET
Status Code:200 OK
Response Headers
Connection:close
Content-Length:369
Content-Type:text/plain;charset=utf-8
x-action:
x-ns:database.collection
Request Headers
Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Host:localhost:28017
Origin:http:// localhost
Referer:http://localhost/ load_mongodb_data.html
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Any assistance appreciated.
CORS is a mechanism where restricted Resources can be requested from (Shared to) another domain - i.e. "Cross Origin" ... the domain owning the resource controls who can have it - this is the important part of CORS, the owner of the resource permits or denies access to the resource
In your case, the page making the request is served on port 80, the resource is requested on port 28017
Think of port 80 as being your domain with your resources
Think of port 28017 being someone elses domain, and they have some resources you want to use
You can't "enable CORS" on your domain and expect the other domain to then grant you access to it's resources - if that's how CORS worked, there'd be no need for CORS to begin with
What you'll need to do is set those Access-Control-* headers on the server running on port 28017
I ham trying to make a request to a REST api. It is a CORS request.
My frontend : Angular 1.5 (localhost:3000)
My Backend : Django (*****.ddns.net)
So I am using a service ( made by someone who doesn't want to share the code :( ), that is doing a OPTIONS request before the real request (preflight). To be precise, the call is made through the resolve option of UI-router state definition.
Django has CORS to allow *.
This is the error that i get in google chrome :
XMLHttpRequest cannot load https://****.net/api/myprofile. The request was redirected to 'https://*****.net/punchclock/api/myprofile/', which is disallowed for cross-origin requests that require preflight.
If I do a classic $http request in a controller, it is working.
This is the request recieved my django :
+6655:5740d0f9:10|
OPTIONS /punchclock/api//myprofile HTTP/1.0|
Host:*****.net|
Connection:close|
Pragma:no-cache|
Cache-Control:no-cache|
Access-Control-Request-Method:GET|
Origin:http%3a//localhost%3a3000|
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36|
Access-Control-Request-Headers:accept, authorization|
Accept:*/*|
Referer:http%3a//localhost%3a3000/dashboard|
Accept-Encoding:gzip, deflate, sdch|
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,es;q=0.2
-6655:5740d0f9:10
And this is the response i get if I do it with postman (it is working with postman when i do an OPTIONS request)
Access-Control-Allow-Headers →x-requested-with, content-type, accept, origin, authorization, x-csrftoken
Access-Control-Allow-Methods →GET, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Allow-Origin →*
Access-Control-Max-Age →86400
Allow →GET, HEAD, OPTIONS
Connection →keep-alive
Content-Type →application/json
Date →Sat, 21 May 2016 21:15:02 GMT
Server →nginx/1.6.2
Transfer-Encoding →chunked
Vary →Accept
X-Frame-Options →SAMEORIGIN
I think it is an issue on Django's side, I don't know. If you have any idea... (I need to learn a lot about CORS...)
Make sure the URL you are targeting is correctly constructed and that there is a trailing slash at the end of the route you are calling. As mentioned here. So instead of this
'http://localhost:5000/auth'
you would call this
'http://localhost:5000/auth/'
Hope this helps.
It is probably because some of the headers you are sending are not allowed. To make sure, just go to google chrome debugger and copy the request headers and send them using postman. If it fails eliminate the headers until you find out which one is not allowed.
There is a similar answer here that may help. Specifically where it says
According to the W3 CORS Spec Section 6.2 Preflight Requests, the preflight must reject the request if any header submitted does not match the allowed headers.
What I am trying to do is to have a page on the HTTP protocol sending an AJAX call to the same Web server but using HTTPS. Both the requesting page and the AJAX handler are on the same server, having the same domain and port. (I.e., only difference is the protocol.) To illustrate,
From
http://www.example.com/index.php
Triggers a jQuery AJAX call to
https://www.example.com/authenticate.php?user=123&password=456
(I am hoping to pass the password through HTTPS to make it encrypted over the Internet. Due to some design constraints I must use AJAX call instead of redirecting the page.)
I understand that there is a CORS issue here and thus I researched a bit and found that I could actually make use of the Access-Control-Allow-Origin header to help. I then set the following in my Apache's configuration file,
Header set Access-Control-Allow-Origin *
Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Header set Access-Control-Allow-Headers "content-type, accept"
Header set Access-Control-Max-Age 1000
I can see that when the browser requests the resources from the server, the headers can be seen. Request:
Accept */*
Accept-Encoding gzip, deflate
Accept-Language en-us,en;q=0.5
Authorization Basic Y2FzZXRhZ3JhbWRldjpwYXNzd29yZGRldiE=
Cache-Control no-cache
Connection keep-alive
Cookie __utma=99230732.2019724749.1337107099.1337849971.1337856946.9; __utmz=99230732.1337107099.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utma=217650581.954519005.1337107174.1337772401.1337777327.5; __utmz=217650581.1337107174.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmc=99230732; PHPSESSID=m8lnqhqv2qa6f884a8um413n81
Host www.example.com
Pragma no-cache
Referer http://www.example.com/index.php
User-Agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:12.0) Gecko/20100101 Firefox/12.0
The response is like,
Accept-Ranges bytes
Access-Control-Allow-Head... content-type, accept
Access-Control-Allow-Meth... GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Orig... *
Access-Control-Max-Age 1000
Connection close
Content-Length 16599
Content-Type application/x-javascript
Date Thu, 24 May 2012 14:48:17 GMT
Etag "48157-40d7-4c0c938b220c0"
Last-Modified Thu, 24 May 2012 14:39:39 GMT
Server Apache/2.2.3 (CentOS)
So it looks like the header part is fulfilled. (Am I right?)
Then when I tried to call the follow jQuery AJAX code in JavaScript,
$.ajax({
// Use HTTPS as there is password transferred
url : "https://www.example.com/authentication.php",
type : 'POST',
dataType : 'json',
async : false,
data : ajaxData,
beforeSend : function(xhr, opt) {},
error : function(error) {
console.log("Ajax error: unable to login user: ");
console.log(error);
},
success : function(status) {
if(status==USER_AUTH_AUTHENTICATE_USER_SUCCESS) {
console.log("User login succeeded!");
} else {
console.log("User login failed.");
}
}
});
The browser (FireFox 12) will just return an object,
readyState 0
status 0
statusText "[Exception... "Access to restricted URI denied" code: "1012" nsresult: "0x805303f4 (NS_ERROR_DOM_BAD_URI)" location: "http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js Line: 8240"]"
Is there something that I missed out?
In fact I had already tried a lot of suggestions from forums and blogs trying to get this done but still I am unsuccessful. I also tried using JSONP and it works fine on FireFox but failed on Chrome/Safari with no readable error message but just throwing an error from jQuery code "head.insertBefore( script, head.firstChild );".
Appreciate much if someone can give me a clue on what is wrong with my code/settings.
Thanks!
Edited on 2012-05-25 20:29 (UTC +08:00)
As suggested I read this reference case (http://stackoverflow.com/questions/5750696/how-to-get-a-cross-origin-resource-sharing-cors-post-request-working) and I found that it linked to this case (http://stackoverflow.com/questions/5584923/a-cors-post-request-works-from-plain-javascript-but-why-not-with-jquery) as well which is related. I tried the sample XHR code there,
var request = new XMLHttpRequest();
var params = "action=something";
request.open('POST', 'https://www.example.com/controllers/Authentication.php', true);
request.onreadystatechange = function() {if (request.readyState==4) alert("It worked!");};
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.setRequestHeader("Content-length", params.length);
request.setRequestHeader("Connection", "close");
request.send(params);
The code is called from a page with HTTP protocol. Once the code is executed, the error below is thrown right away,
Access to restricted URI denied...test_xhr.php Line 11
(If I change the HTTPS in JavaScript HTTP, the script works right away and so there should not be any syntax problem or so.)
The request and response headers of the page itself are as follows. Request is,
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language en-us,en;q=0.5
Authorization Basic Y2FzZXRhZ3JhbWRldjpwYXNzd29yZGRldiE=
Cache-Control no-cache
Connection keep-alive
Cookie __utma=99230732.2019724749.1337107099.1337856946.1337921578.10; __utmz=99230732.1337107099.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utma=217650581.954519005.1337107174.1337772401.1337777327.5; __utmz=217650581.1337107174.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmc=99230732; PHPSESSID=ktd6anojfi40ohemlujosdmhi4
Host www.example.com
Pragma no-cache
User-Agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:12.0) Gecko/20100101 Firefox/12.0
The response is,
Access-Control-Allow-Head... content-type, accept
Access-Control-Allow-Meth... GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Orig... *
Access-Control-Max-Age 1000
Connection close
Content-Length 590
Content-Type text/html; charset=UTF-8
Date Fri, 25 May 2012 12:24:44 GMT
Server Apache/2.2.3 (CentOS)
X-Powered-By PHP/5.1.6
So I am just thinking something is fundamentally wrong with my setup but not jQuery as native XHR does not work as well. :(
You have two issues:
1) Access-Control-Allow-Origin "*" is not working with authenticated calls, instead of * reflect the calls Access-Control-Request-Origin or Origin header fields.
2) You'll need Access-Control-Allow-Credentials: true in the response.
Other things that might help: setting authorization header manually, assembling name and password with base64. This is the surest way to have working. Its advantage is its drawback: setting authorization header manually activates the OPTIONS header based CORS handshake. (All your requests are preceded with an OPTIONS request that you have to also handle) This one seems to have a coherent implementation across all modern browsers (IE9 of course is an exception, IE10 however works allegedly).
HTH