The AJAX request works fine, but the moment I add a header via beforeSend or headers, an OPTIONS pre-flight request is made and the GET request is aborted.
Code: $.ajax({
type: "GET",
crossDomain: true,
beforeSend: function (xhr)
{
xhr.setRequestHeader("session", $auth);
},
url: $url,
success: function (data) {
$('#something').html(data);
},
error: function (request, error) {
$('#something').html("<p>Error getting values</p>");
}
});
Similar AJAX Request w/o headers specified (the moment I add/modify header, an OPTIONS call is made)
Request GET /api/something?filter=1 HTTP/1.1
Referer http://app.xyz.dj/dashboard
Accept application/json, text/javascript, */*; q=0.01
Accept-Language en-US
Origin http://app.xyz.dj
Accept-Encoding gzip, deflate
User-Agent Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; MASMJS; rv:11.0) like Gecko
Host 162.243.13.172:8080
DNT 1
Connection Keep-Alive
Cache-Control no-cache
Similar Server Response Header (for GET request)
Response HTTP/1.1 200 OK
Server Apache-Coyote/1.1
Access-Control-Allow-Origin *
Access-Control-Allow-Methods GET, POST, DELETE, PUT, OPTIONS, HEAD
Access-Control-Allow-Headers Content-Type, Accept, X-Requested-With
Access-Control-Allow-Credentials true
Content-Type application/json
Transfer-Encoding chunked
Date Thu, 09 Jan 2014 14:43:07 GMT
What I am doing wrong?
Solved.
Thanks #JasonP for pointers. Changed Server Response Headers from
Access-Control-Allow-Headers:*
to specific ones
Access-Control-Allow-Headers: Content-Type, Accept, X-Requested-With, Session
and now it works!
Related
I have an Nginx with a simple index.thml running within a Docker. Everything works fine if I call it from a browser with http://localhost:8979/index.html, but when I call it from JQuery Ajax in another server (https://localhost:8447/) like this
$.ajax({
type: "GET",
url: "http://localhost:8979/index.html",
crossDomain: true,
success: function (data) {
$("#myDiv").html(data);
}
});
I obtain this error:
Access to XMLHttpRequest at 'http://localhost:8979/index.html' from origin 'https://localhost:8447' 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.
My Nginx configuration is this:
server {
listen 80;
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PUT';
add_header 'Access-Control-Allow-Headers' 'User-Agent,Keep-Alive,Content-Type';
}
}
I can see in Devtools this two requests:
General
Request URL: http://localhost:8979/index.html
Referrer Policy: strict-origin-when-cross-origin
Provisional headers are shown
Accept: */*
Access-Control-Allow-Origin: *
Referer
sec-ch-ua: "Chromium";v="86", "\"Not\\A;Brand";v="99", "Google Chrome";v="86"
sec-ch-ua-mobile: ?0
User-Agent: M
General
Request URL: http://localhost:8979/index.html
Request Method: OPTIONS
Status Code: 405 Not Allowed
Remote Address: [::1]:8979
Referrer Policy: strict-origin-when-cross-origin
Response Headers
Connection: keep-alive
Content-Length: 559
Content-Type: text/html
Date: Thu, 12 Nov 2020 17:54:48 GMT
Server: nginx/1.19.4
Request Headers
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: es-ES,es;q=0.9,zh-CN;q=0.8,zh;q=0.7
Access-Control-Request-Headers: access-control-allow-origin
Access-Control-Request-Method: GET
Connection: keep-alive
Host: localhost:8979
Origin: https://localhost:8447
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Windows NT 1....
My Docker file:
FROM nginx
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
COPY ./src/static /usr/share/nginx/html
Is the problem in the Ajax request or is a configuration issue?
Try this one:
map $request_method $options_content_type {
OPTIONS "text/plain";
}
map $request_method $options_content_length {
OPTIONS 0;
}
server {
listen 80;
location / {
if ($request_method = OPTIONS) { return 204; }
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PUT';
add_header 'Access-Control-Allow-Headers' 'User-Agent,Keep-Alive,Content-Type';
add_header Content-Type $options_content_type;
add_header Content-Length $options_content_length;
}
}
Beware! You are declaring GET, POST, OPTIONS, DELETE and PUT as allowed HTTP methods, but in fact nothing except GET (and now OPTIONS) will work with this configuration. Do you really need all the other methods?
I am using the below Ajax call to connect with Spring security from crossdomain (PhoneGap). The response I got is 200 OK - it has the expected response in JSON format. But the error event is getting fired due to CORS. On the Spring side, I have added a CORS filter to allow any type of URL (Access-Control-Allow-Origin = ' * ').
$.ajax({
type:'POST',
url: CONTEXTPATH + '/j_spring_security_check',
data: formData,
dataType: 'text json',
cache: false,
crossdomain: false,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Requested-With' : 'XMLHttpRequest',
},
success: function(data) {
},
error: function(data) {
}
});
The response in the browser console is:
POST XHR http://192.168.0.20:8080/startupbay/j_spring_security_check [HTTP/1.1 200 OK 260ms] Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://192.168.0.20:8080/startupbay/j_spring_security_check. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
The request and response headers are:
RESPONSE HEADER:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Content-Type, x-requested-with, Origin, Accept
Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS, PATCH, HEAD
Access-Control-Allow-Origin:*
Access-Control-Max-Age:86400
Access-Control-Request-Headers:x-requested-with
Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Content-Length:0
Date: Thu, 23 Feb 2017 06:14:39 GMT
Expires:0
Pragma:no-cache
Server:Apache-Coyote/1.1
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
REQUEST HEADER:
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
Access-Control-Request-Headers:x-requested-with
Access-Control-Request-Method:POST
Connection:keep-alive
Host:192.168.0.20:8080
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0
origin:http://192.168.0.20:3000
In the Error section, I looked for the error mentioned in 'xhr'. The statusText:error, responseText:'', status:0.
Please help me in resolving this issue.
When I set the crossdomain:true, that time in the browser console I can see only the OPTIONS request, but not followed by the POST request.
Just to add, this issue is appearing only for the '/j_spring_security_check' URL. For another URL, the same type setup is working fine.
Server side setup
JsonRoutes.setResponseHeaders({
"Cache-Control": "no-store",
"Pragma": "no-cache",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, PUT, POST, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With"
});
Client side setup
var getRecentPosts = function (token) {
$.ajax({
url: "http://localhost:3000/publications/recentPostsAndComments",
method: "GET",
headers: {
"Authorization": "Bearer " + token,
"Content-Type": "application/json"
},
// contentType: "application/json",
success: function (data, status, xhr) {
debugger
},
error: function (xhr, status, err) {
debugger
}
});
}
I always get caught inside the error callback because of the following error:
XMLHttpRequest cannot load http://localhost:3000/publications/recentPostsAndComments. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:5000' is therefore not allowed
access.
Is there anything noticeable that I am missing here?
Update:
in the network tab, I see one option request that succeeds, but I don't see a GET request that's supposed to be sent.
Remote Address:127.0.0.1:3000
Request URL:http://localhost:3000/publications/recentPostsAndComments
Request Method:OPTIONS
Status Code:200 OK
Response Headers
view source
connection:keep-alive
content-type:text/html; charset=utf-8
date:Sat, 19 Sep 2015 23:53:48 GMT
transfer-encoding:chunked
vary:Accept-Encoding
Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8,ko;q=0.6
Access-Control-Request-Headers:accept, authorization, content-type, x-requested-with
Access-Control-Request-Method:GET
Cache-Control:no-cache
Connection:keep-alive
Host:localhost:3000
Origin:http://localhost:5000
Pragma:no-cache
Referer:http://localhost:5000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36
This is what I sometimes use and it works great.
//Server Side PHP
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
header('Access-Control-Max-Age: 2000');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X- Requested-With');
?>
As you know, it should be placed before any code....
I'm developing an Azure MobileService / CordovaApp setup. The server runs locally and has the following setting to enable CORS:
<add name="Access-Control-Allow-Origin" value="*" />
The api can be called via browser using addresses like
http://localhost:59477/api/item/explore/A/B
The client script that's trying to depict this call is the following:
var client = new WindowsAzure.MobileServiceClient('http://localhost:59477/', 'http://localhost:59477/', '');
GetItems.addEventListener("click",
function ()
{
client.invokeApi("item/explore/A/B",
{
method: "get"
})
.done(
function (results)
{
alert(results.result.count);
},
function (error)
{
var xhr = error.request;
alert('Error - status code: ' + xhr.status + '; body: ' + xhr.responseText);
alert(error.message);
}
);
}
);
What I get is status 405 - Method not allowed, which I don't understand for two reasons:
The invoked Service Action is decorated with the [HttpGet] Attribute
The response headers seem to say GET is fine:
HTTP/1.1 405 Method Not Allowed
Allow: GET
Content-Length: 76
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
X-SourceFiles: =?UTF-8?B?RjpcQ29kZVxGb290UHJpbnRzXGZvb3RwcmludHMuU2VydmVyXEZvb3RwcmludHNTZXJ2aWNlXGFwaVxmb290cHJpbnRcZXhwbG9yZVw1MS4yNzcwMjJcNy4wNDA3ODM=?=
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
Date: Sat, 15 Aug 2015 18:08:30 GMT
Any idea what I can do to get this running?
Edit
The Raw request shows that, as already expected by Jeremy Foster, the client sends a request of the type OPTIONS:
OPTIONS http://localhost:59477/api/fp/get?id=1 HTTP/1.1
Host: localhost:59477
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://localhost:4400
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36
Access-Control-Request-Headers: accept, x-zumo-features, x-zumo-installation-id, x-zumo-version
Accept: */*
Referer: http://localhost:4400/index.html
Accept-Encoding: gzip, deflate, sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
I managed to support this request applying the [HttpOptions] attribute to my action method. Now I get a more or less valid response:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/8.0
X-SourceFiles: =?UTF-8?B?RjpcQ29kZVxGb290UHJpbnRzXGZvb3RwcmludHMuU2VydmVyXEZvb3RwcmludHNTZXJ2aWNlXGFwaVxmcFxnZXRcMQ==?=
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Date: Sun, 23 Aug 2015 19:34:21 GMT
Content-Length: 234
...
At least that's what fiddler tells me. The AzureMobileServiceClient throws yet another issue, which roughly translates as:
Cross-Origin request blocked, missing token 'x-zumo-installation-id' in CORS header row 'Access-Control-Allow-Headers' on CORS-Preflight-Channel
Turn on Fiddler and try your api call from the browser and then again using the Mobile Services client and compare your raw HTTP requests to see what's different.
Try to run through the CORS Support section of this blog post: http://azure.microsoft.com/blog/2014/07/28/azure-mobile-services-net-updates/.
A side note: The x-zumo-installation-id error you were getting was because the client requested access for a list of headers (see the Access-Control-Request-Headers in your request) and the server did not return that same list in the Access-Control-Allow-Headers header. Using the MS_CrossDomainOrigins setting as mentioned in the above blog post takes care of this by setting the allowed headers to * (all) by default.
Here is my AngularJS code, (it works fine if I remove the header option).
$http.get(env.apiURL()+'/banks', {
headers: {
'Authorization': 'Bearer '+localStorageService.get('access_token')
}
})
Here is the request:
OPTIONS /banks HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://localhost:8081
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36
Access-Control-Request-Headers: accept, authorization
Accept: */*
Referer: http://localhost:8081/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,vi;q=0.6
And response:
HTTP/1.1 404 Not Found
Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Origin: http://localhost:8081
Content-Type: text/plain; charset=utf-8
Date: Mon, 17 Mar 2014 11:05:20 GMT
Content-Length: 19
I added both Accept and Authorization header but the request still fails?
Does the capitalization (I mean authorization vs Authorization) result in that failure? If yes, how can I make AngularJS stop doing that?
if origin := req.Header.Get("Origin"); origin == "http://localhost:8081" {
rw.Header().Set("Access-Control-Allow-Origin", origin)
rw.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
rw.Header().Set("Access-Control-Allow-Headers",
"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}
Go server routing code:
r := mux.NewRouter()
r.HandleFunc("/banks", RetrieveAllBank).Methods("GET")
http.ListenAndServe(":8080", r)
OK, the issue because I fotgot to handle the "OPTIONS" request (to make a CORS browser will send a preflight OPTIONS request first and then the 'real' request if accepted by the server).
I only need to modify my Go server (see the comment):
func main() {
r := mux.NewRouter()
r.HandleFunc("/banks", RetrieveAllBank).Methods("GET")
http.ListenAndServe(":8080", &MyServer{r})
}
type MyServer struct {
r *mux.Router
}
func (s *IMoneyServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if origin := req.Header.Get("Origin"); origin == "http://localhost:8081" {
rw.Header().Set("Access-Control-Allow-Origin", origin)
rw.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
rw.Header().Set("Access-Control-Allow-Headers",
"Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}
// Stop here if its Preflighted OPTIONS request
if req.Method == "OPTIONS" {
return
}
// Lets Gorilla work
s.r.ServeHTTP(rw, req)
}