As always I will try to put my questions sweet and clean, as much as I can.
I have to send CORS as a requirement request and I'm doing it through $.ajax and it looks like this:
$.ajaxSetup({
beforeSend: function (jqXHR, options) {
options.url = Utils.setUrlHostname(options.url);
options.xhrFields = {
withCredentials: true
};
jqXHR.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
}
});
On the server side (php - zend framework) I'm handling headers like this:
public function OPTIONS_ProxyAction()
{
$this->getResponse()->setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST, PUT, DELETE');
$this->getResponse()->setHeader('Access-Control-Allow-Headers', 'Content-Type, x-requested-with');
$this->getResponse()->setHeader('Access-Control-Allow-Credentials', 'true');
$this->getResponse()->setBody(null);
$this->_helper->viewRenderer->setNoRender(true);
}
The preflight request headers looks fine and I'm getting 200 OK:
Request Headers:
Host: domain1111.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:38.0) Gecko/20100101 Firefox/38.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: https://domain2222.com
Access-Control-Request-Method: GET (this is seen as OPTIONS in network tab)
Access-Control-Request-Headers: x-requested-with
Connection: keep-alive
Cache-Control: max-age=0
And Response Headers:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: X-Requested-With, Content-Type
Access-Control-Allow-Methods: OPTIONS, GET, POST, PUT, DELETE
Access-Control-Allow-Origin: https://domain2222.com
Cache-Control: max-age=0, s-maxage=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection: Keep-Alive
Content-Length: 0
Content-Type: text/html
Date: Thu, 11 Jun 2015 08:40:42 GMT
Etag: "d41d8cd98f00b204e9800998ecf8427e"
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Keep-Alive: timeout=5, max=100
Pragma: no-cache
Server: Apache
Vary: X-CDN
X-Frame-Options: SAMEORIGIN
X-Ua-Compatible: IE=edge,chrome=1
I'm getting empty response which is fine, and a new request is sent to the same address, but the method is GET instead of OPTIONS and it looks like this:
Request Headers:
Host: domain1111.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:38.0) Gecko/20100101 Firefox/38.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Referer: https://domain2222.com/some/request
Origin: https://domain1111.com
Cookie: s1=533C36A9095C003A;
BGUID=some complicated guid here
Connection: keep-alive
Cache-Control: max-age=0
And Response:
Access-Control-Allow-Origin: https://domain2222.com
Cache-Control: max-age=0, s-maxage=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection: Keep-Alive
Content-Length: 3278
Content-Type: application/json
Date: Thu, 11 Jun 2015 08:40:43 GMT
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Keep-Alive: timeout=5, max=99
Pragma: no-cache
Server: Apache
Vary: X-CDN
X-Frame-Options: SAMEORIGIN
The problem is that after the real request is sent, I'm getting in Firefox:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://domain1111.com/some/request. (Reason: expected 'true' in CORS header 'Access-Control-Allow-Credentials')
And similarly in Chrome:
XMLHttpRequest cannot load https://domain1111.com/some/request. Credentials flag is 'true', but the 'Access-Control-Allow-Credentials' header is ''. It must be 'true' to allow credentials.
Those errors occur when the second CORS request is finished. So after the first preflight request is sent, it returns with 200 OK and an empty response, which is fine; after the second request is sent I'm getting the errors listed above, with no data returned.
Additionally, the Response tab in Firefox is giving me this message:
SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 on the JSON data
I'm not sure whether during second request the property 'withCredential' is sent as well or not, and maybe the server is not returning:
'Access-Control-Allow-Credentials', 'true'
Why it's happening only with OPTIONS requests?
Should I return those headers from the server, no matter what request method is? Or maybe there is something wrong with ajaxSetup? Maybe it shouldn't sent 'withCredentials: true' within the second CORS request?
Update:
The problem has been fixed by adding Access-Control-Allow-Credentials: true, to all responses returned by the server (PUT, GET, POST, DELETE, OPTIONS)