Keywords: CORS | jQuery | Cross-Origin Requests | Preflight Requests | XMLHttpRequest
Abstract: This article provides an in-depth analysis of the root causes behind jQuery CORS POST request failures, focusing on the impact of jQuery's automatically added x-requested-with header on CORS preflight requests. By comparing the implementation differences between native JavaScript and jQuery, it explains the working mechanism of CORS preflight in detail and offers comprehensive server-side configuration solutions and client-side code optimization recommendations. The discussion also covers version-specific differences in jQuery handling and key configuration points for non-simple headers, providing developers with complete technical guidance for resolving cross-origin request issues.
Problem Background and Phenomenon Analysis
In web development, Cross-Origin Resource Sharing (CORS) is a crucial mechanism for enabling cross-origin requests. Many developers have encountered situations where CORS POST requests succeed with native XMLHttpRequest but fail when switching to jQuery. This discrepancy primarily stems from differences in how these two approaches handle request headers.
Native JavaScript Implementation Analysis
The native JavaScript approach to CORS requests is relatively straightforward:
var request = new XMLHttpRequest();
var params = "action=something";
request.open('POST', url, 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);
This implementation uses only simple headers and does not trigger CORS preflight requests, thus functioning correctly.
Root Cause of jQuery Implementation Issues
jQuery's $.ajax method automatically adds an x-requested-with header for cross-origin requests:
$.ajax(url, {
type:"POST",
dataType:"json",
data:{action:"something"},
success:function(data, textStatus, jqXHR) {alert("success");},
error: function(jqXHR, textStatus, errorThrown) {alert("failure");}
});
This additional header qualifies as a non-simple header, triggering the browser's CORS preflight request. If the server is not properly configured with Access-Control-Allow-Headers to permit this header, the request will fail.
Detailed Explanation of CORS Preflight Mechanism
The CORS specification distinguishes between simple and non-simple requests. When a request includes non-simple headers (like x-requested-with) or uses non-simple methods, the browser first sends an OPTIONS preflight request. The server must respond correctly to this preflight request before the actual POST request can proceed.
Server-Side Configuration Solutions
For jQuery CORS requests, servers need proper preflight response configuration:
header('Access-Control-Allow-Origin: http://www.example.com');
header('Access-Control-Allow-Credentials: true');
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Max-Age: 604800');
header('Access-Control-Allow-Headers: x-requested-with');
exit(0);
}
Key configuration points:
Access-Control-Allow-Headersmust explicitly list permitted non-simple headers- Wildcard
*may not work in certain scenarios (e.g., when credentials are required) - Preflight responses require appropriate HTTP status codes
jQuery Version Differences and Handling
Starting from jQuery 1.5.2, the library no longer automatically adds the x-requested-with header to cross-origin requests. This means:
- jQuery 1.5.1 and earlier: Require server configuration of
Access-Control-Allow-Headers: x-requested-with - jQuery 1.5.2 and later: Default behavior avoids preflight requests, aligning more closely with native implementation
Potential Impact of Data Type Settings
Setting dataType: "json" may cause jQuery to send a Content-Type: application/json header, which also qualifies as a non-simple header and triggers preflight requests. Solutions include:
- Configuring the server to allow the
Content-Typeheader - Using
contentType: 'application/x-www-form-urlencoded'instead - Removing the
dataTypesetting to use jQuery defaults
Best Practice Recommendations
Based on practical development experience, the following best practices are recommended:
- Explicitly list permitted headers on the server side, avoiding wildcards
- Adjust client code and server configuration according to jQuery version
- Thoroughly inspect network requests in development environments to verify preflight request sending and responses
- Consider upgrading to newer jQuery versions for simplified CORS handling
- For complex scenarios, use the
beforeSendcallback to customize request headers
Conclusion
The fundamental reason for jQuery CORS POST request failures lies in the library's automatic addition of non-simple headers, which triggers the preflight request mechanism. By correctly configuring the server's Access-Control-Allow-Headers response header and understanding behavioral differences across jQuery versions, developers can effectively resolve cross-origin request issues. Additionally, paying attention to how data type settings affect request headers ensures smooth execution of the entire CORS process.