jQuery跨域请求

I'm trying to get a cross domain request to work. The relevant code is as follows:

var promise = $.ajax({
    type: 'GET',
    url: registerUrl,
    dataType: 'json',
    cache: false,
    crossDomain: true,
    xhrFields: { withCredentials: true },
    contentType: 'application/json'
});

I control the calling and receiving server, and this is response that I am getting:

Raw request (courtesy of Fiddler):

OPTIONS http://localhost:5080/mportal/registerChat?gsid=abcde&ul=100,200&_=1405022169353 HTTP/1.1
Host: localhost:5080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.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
Origin: http://localhost:53054
Access-Control-Request-Method: GET
Access-Control-Request-Headers: content-type
Connection: keep-alive

Raw response:

HTTP/1.1 200 OK
Date: Thu, 10 Jul 2014 19:56:11 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Content-Length: 0
Server: Jetty(8.1.4.v20120524)

Now, my understanding is that Allow-Origin: * for this preflight should be enough for Firefox / Chrome to let the request continue. Oddly enough, IE does no preflight for this request, and it works (despite throwing up a warning that it is not following the CORS specification).

Am I missing something here? I've tried setting every value on the ajax request I can think of, and the server looks to be responding with the appropriate response to the OPTIONS request.

The specific error message from firefox:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5080/mportal/registerChat?gsid=abcde&ul=100,200&_=1405022169353. This can be fixed by moving the resource to the same domain or enabling CORS.

What am I doing wrong? What can be changed to fix this?

EDIT: New request / response fields:

OPTIONS http://localhost:5080/mportal/registerChat?gsid=abcde&ul=100,200&_=1405026511996 HTTP/1.1
Host: localhost:5080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.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
Origin: http://localhost:53054
Access-Control-Request-Method: GET
Access-Control-Request-Headers: content-type
Connection: keep-alive

Response:

HTTP/1.1 200 OK
Date: Thu, 10 Jul 2014 21:08:38 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Credentials: true
Content-Length: 0
Server: Jetty(8.1.4.v20120524)

Now, fiddler also records the actual request:

GET http://localhost:5080/mportal/registerChat?gsid=abcde&ul=100,200&_=1405026511996 HTTP/1.1
Host: localhost:5080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Referer: http://localhost:53054/
Origin: http://localhost:53054
Connection: keep-alive

And the response:

HTTP/1.1 200 OK
Date: Thu, 10 Jul 2014 21:08:38 GMT
Content-Type: application/json;charset=ISO-8859-1
Content-Length: 175
Server: Jetty(8.1.4.v20120524)

{"status":true,"host":"<myServerName>","port":1935,"liveHost":"<myServerName>","livePort":5080,"gsid":"abcde","connCount":2,"maxConns":25000,"version":"1.0"}

However, firefox seems to be blocking the request and thus the ajax call always hits my fail handler. This seems odd...

Try setting

dataType:'html' 

(Where is the correct place to enable CORS?)

It looks like your request is asking for permission to send a content-type request header, and it requires permission to send credentials.

Your request headers appear to be correct as far as I can tell. However your response should contain two more headers:

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:content-type

Here is an example of a preflight request from another site I've worked on, and the preflight response:

Here is the preflight option requestion headers

Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:accept, applicationname
Access-Control-Request-Method:GET
Cache-Control:no-cache
Connection:keep-alive
Cookie:*sanitized cookie data*
Host:sanitized.domain.com
Origin:https://sanitized.domain.com
Pragma:no-cache
Referer:https://sanitized.domain.com/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36

Subsequently here is the preflight response headers:

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:applicationname
Access-Control-Allow-Origin:https://sanitized.domain.com
Cache-Control:no-cache
Connection:keep-alive
Content-Length:0
Date:Thu, 10 Jul 2014 20:19:25 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/8.0
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET

Notice the addition of the Access-Control-Allow-Credentials, and Access-Control-Allow-Headers headers. Also notice my request sent "accept" in the Access-Control-Request-Headers header, and the response didn't contain "accept". This is because "accept" is considered a simple header as defined here: http://www.w3.org/TR/cors/#simple-header. Additionally content-type qualifies as a simple header only when it's value is one of the following:

  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded

In your case since the content type is application/json, you would need a response header that contains "content-type", as displayed above.

UPDATE: Your request and response that occur after the preflighted request should contain the same CORS headers to prevent the browser from rejecting the request and/or response. At a bare minimum you'll want the response to contain the Access-Control-Allow-Credentials and the Access-Control-Allow-Origin headers.