I have the following coffee script which performs some sort of login:
signIn: (url, completion) ->
$.ajax
method: 'GET'
url: url
dataType: 'json'
error: (jqXHR, status, errorThrown) ->
completion false, errorThrown
success: (data)->
completion true, data.Identifier
When I check the given URL in the browser I get a valid JSON Response back.
However, when this call is executed using JavaScript I get the following error in the console . Please note that I have changed the URLs for obfuscation:
XMLHttpRequest cannot load http://my.servicedomain.com/session/someIdentifier?access_token=secret.
Origin http://html.server.net is not allowed by Access-Control-Allow-Origin.
These are my headers, which I get from the my.servicedomain.com server:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 1417
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Authorization
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Authorization
Date: Wed, 10 Jul 2013 14:24:35 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
Connection: Keep-Alive
Why do I get this error, even though I have Access-Control-Allow-Origin: * in the response header?
I have just figured out the answer myself. I knew that I had duplicated headers in my response, but I was assuming this would not be a problem.
It looks like this is a Problem according to the CORS Spec:
If the response includes zero or more than one Access-Control-Allow-Origin header values, return fail and terminate this algorithm.
This is also described in this SO Thread:
Will duplicate "Access-Control-Allow-Origin: *" headers break CORS?
Related
I have a simple post request with axios:
axios.post('my endpoint', values).then(res => console.log(res.headers));
axios is listing those values as headers:
cache-control: "max-age=0, private, must-revalidate"
content-length: "13757"
content-type: "application/xml; charset=utf-8"
but when I check the network tab in chrome, I can see those values under response headers:
access-control-allow-origin: http://localhost:8080
access-control-expose-headers: Total,Total-Pages
cache-control: max-age=0, private, must-revalidate
content-length: 13757
content-type: application/xml; charset=utf-8
date: Thu, 02 Sep 2021 19:37:42 GMT
x-envoy-upstream-service-time: 385
x-request-id: FqEYfGCtbcHGzzwASr4C
I need to access the x-request-id header, but there is no way to get this with axios or fetch.
I saw some messages about the header being blocked by cors, but I have X-Request-Id in my access-control-allow-headers
Someone has any idea how to get this header with axios?
I think you have to specify this on the server so that axios has access to the specific headers you require.
https://stackoverflow.com/a/37931084/8818020
I'm new to web programming so bear with me. I've created a simple REST API in python flask, and am hosting it with Apache 2.4. I've tested it via cURL and it works. Now I'm trying to access it via a web interface with jQuery.
The REST api is at http://api.localhost and the website that accesses it is at http://localhost.
The code I'm using to try and do a POST looks like this:
$.ajax({
type: 'POST',
url: 'http://api.localhost/auth',
data: '{"username":"user1", "password":"abcxyz"}',
success: function(data) { console.log(data); alert('data: ' + data); },
contentType: "application/json",
dataType: 'json'
});
However, it seems the success function doesn't run. Looking in dev console (f12) I can see that instead of a POST to that URL, and OPTIONS HTTP request is made. My understanding is this is a Cross-Origin Resource Sharing (CORS) preflight check, to make sure it's OK for localhost to access api.localhost.
I've added the following lines to my apache config for api.localhost:
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS"
It seems to be working to because the OPTIONS request returns a 200 (and no other data). However, there is no follow up. My understanding is since the server is saying it's OK for anyone to POST to api.localhost, that it should go ahead and do the POST next, but it doesn't.
Here are the preflight check request headers:
Host: api.localhost
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101
Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Origin: http://localhost
Connection: keep-alive
Cache-Control: max-age=0
Here are the response headers for that same request (remember, status 200):
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Origin: *
Allow: POST, OPTIONS
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 20
Content-Type: text/html; charset=utf-8
Date: Thu, 07 Dec 2017 00:17:08 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.29 (Debian)
Vary: Accept-Encoding
You can see that the server is saying any domain is fine (*) and that POST is OK. However, there is no follow up POST. What am I missing?
Thanks.
http://api.localhost/auth must also send Access-Control-Allow-Headers: content-type.
So to your Apache config, you also need to add this:
Header always set Access-Control-Allow-Headers "content-type"
That’s necessary because the contentType: "application/json" part of your frontend code adds a Content-Type: application/json header to the request, and any values for the Content-Type request header other than text/plain, application/x-www-form-urlencoded, or multipart/form-data will trigger browsers to send a CORS preflight OPTIONS request.
So if you have your http://api.localhost/auth server send back the Access-Control-Allow-Headers: content-type response header, that should cause the preflight to succeed, and so cause the browser to move on to making the POST request from your frontend code.
I have a problem with Chrome - in the network tab it only displays an empty Access-Control-Exposed-Headers header.
In postman the header's value is visible:
When trying to access the ETag header through the getResponseHeader('ETag') method of the XMLHttpRequest I'm getting a Refused to get unsafe header "etag" error. I already ran out of ideas how to fix this. Does anybody know what could be wrong?
EDIT: Apparently that behaviour is caused by the Origin header - when it is present in the request, the Access-Control-Expose-Headers in the response is empty. Unfortunately, I don't have access to the backend code, so I can't provide an example. All response headers:
HTTP/1.1 200 OK
Server: openresty/1.9.7.5
Date: Sun, 03 Sep 2017 13:02:55 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Expose-Headers:
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: *,x-requested-with,Content-Type,If-Modified-Since,If-None-Match,latest_time
Access-Control-Max-Age: 1728000
ETag: "eef3e52bc505031d93da42098f32cc60"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: eb5c7353-0b4b-43c8-b2ff-4763d56d9ec9
X-Runtime: 0.015680
Access-Control-Allow-Credentials: true
Vary: Origin
Application is on 'http://192.168.1.5:8000', and API server is on 'http://192.168.1.5:9000'. I'm trying to send GET requests with cookies to API server in the application using jQuery.
Here is the complete request headers (extracted from FireBug):
GET /api/rooms HTTP/1.1
Host: 192.168.1.5:9000
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.5:8000
Origin: http://192.168.1.5:8000
Cookie: COOKIE=bf27f9f2-6bf8-4688-ac03-fc802653ce22
Connection: keep-alive
Response header:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Allow: GET, OPTIONS, POST
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: OPTIONS, GET, POST
Access-Control-Allow-Headers: Content-Type, Depth, User-Agent, X-File-Size, X-Requested-With, If-Modified-Since, X-File-Name, Cache-Control
Date: Wed, 09 Dec 2015 15:33:50 GMT
Content-Length: 6670
jQuery code:
$.ajax('http://192.168.1.5:9000/api', {
xhrFields: {
withCredentials: true
},
dataType: 'json',
crossDomain: true,
type: 'GET',
success: function (response) {
console.log(response);
}
});
While browser got the response (with status code 200), but jQuery stops because of cross origin policy.
How to resolve this issue? More headers needed?
Note, your response headers above use the wildcard * for the allow origin header,
Access-Control-Allow-Origin: *
yet the CORS spec indicates that wildcards may not be used for that header, for requests that support credentials (use the explicit origin value as the accept origin value instead). CF: https://www.w3.org/TR/cors/#resource-requests
Access-Control-Allow-Origin: "the actual explicit origin"
I hope that info helps,
..Mike Burati
The server has been modified to send the right request headers.
Server - Response Headers:
Access-Control-Max-Age: 86400
Access-Control-Allow-Methods: GET, OPTIONS, POST
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type, X-Requested-With
I'm using Spring web mvc for the server (a.foo.com), and using mvc interceptors to set the HttpResponseHeaders.
I also attempted setting the origin to the domain of the request, instead of '*'.
Client - jQuery Code
I'm using jQuery/AJAX - jquery 1.7.1
Here is a summary of the POST request.
var settings = {};
settings.url = "http://a.foo.com/api";
settings.type = 'POST';
settings.data = JSON.stringify(request);
settings.dataType = 'json';
settings.contentType = 'application/json; charset=utf-8';
settings.crossDomain = true; // adding or removing this, didn't make a difference
.... (setup callbacks etc)
jQuery.ajax(settings);
The website - html/js is hosted on a.bar.com
Error on Client - javascript console (testing on chrome)
XMLHttpRequest cannot load http://a.foo.com/api. Origin http://a.bar.com is not allowed by Access-Control-Allow-Origin.
Question
Is there anything else I'm missing? I would like to avoid using JSONP, mostly because I require POST support.
Thanks for any pointers, and your help.
I didn't have the response headers set for the OPTIONS request. I was setting it for the GET/POST requests.
Following this blog helped:
http://zhentao-li.blogspot.com/2012/06/enable-cors-support-in-rest-services.html
Now when I hit the endpoint (a.foo.com/api/*) with the request method OPTIONS/GET/POST, I get the following headers:
Date: Wed, 08 Aug 2012 02:58:05 GMT
Connection: keep-alive
Content-Length: 0
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS
Server: Apache-Coyote/1.1
Access-Control-Max-Age: 1800
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Content-Type: text/plain; charset=UTF-8
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
I tested this out on Chrome. I wonder if there will be issues with IE! :)
I'd like for this to work with IE9 as well, but from what I read, I shouldn't get my hopes up.
Thanks #Strelok for your suggestions. And #sth and #xdazz.