Keywords: CORS | Preflight Request | Cross-Origin Resource Sharing
Abstract: This article provides an in-depth exploration of the CORS preflight request mechanism, detailing how browsers send preflight requests using the OPTIONS method and how servers should properly respond with critical headers like Access-Control-Allow-Methods and Access-Control-Allow-Headers. Through concrete code examples, it demonstrates complete implementation solutions for WCF services and jQuery clients, helping developers thoroughly resolve preflight issues in cross-origin requests.
Overview of Preflight Request Mechanism
Cross-Origin Resource Sharing (CORS) is the core mechanism in modern web development for handling cross-origin requests. When a browser detects that a cross-origin request does not meet the criteria for a simple request, it automatically initiates a preflight request—an HTTP request using the OPTIONS method—to confirm whether the target server permits the actual cross-origin request.
Workflow of Preflight Requests
The essence of preflight requests lies in the negotiation process between the browser and the server. Before sending the actual request, the browser first sends an OPTIONS request containing critical request headers:
Origin: http://yourdomain.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Custom-Header
The server must correctly respond to these request headers by returning corresponding control headers:
Access-Control-Allow-Origin: http://yourdomain.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: X-Custom-Header
Server-Side Implementation Details
Implementing CORS support in WCF services requires proper handling of OPTIONS requests. Below is a complete WCF service configuration example:
public class CorsEnabledMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
var httpRequest = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
if (httpRequest.Method == "OPTIONS")
{
var httpResponse = new HttpResponseMessageProperty();
httpResponse.Headers.Add("Access-Control-Allow-Origin", "http://localhost");
httpResponse.Headers.Add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
httpResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, X-Custom-Header");
OperationContext.Current.OutgoingMessageProperties.Add(HttpResponseMessageProperty.Name, httpResponse);
}
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
// Handle CORS headers for actual requests
}
}
Client-Side Implementation Solutions
In jQuery clients, while the library itself handles preflight requests, developers need to understand its working principles. Here is a complete cross-origin request example:
$.ajax({
url: 'http://api.example.com/service',
type: 'POST',
contentType: 'application/json',
headers: {
'X-Custom-Header': 'custom-value'
},
data: JSON.stringify({ key: 'value' }),
success: function(response) {
console.log('Request successful:', response);
},
error: function(xhr, status, error) {
console.error('Request failed:', error);
}
});
Common Issues and Solutions
In practical development, preflight requests may encounter various problems. The most common issues include servers not properly handling OPTIONS requests or returning incorrect Content-Types. As illustrated in the referenced article's Flask API example, when an OPTIONS request returns a text/html content type, the browser will reject subsequent actual requests.
The solution is to ensure the server returns correct responses for OPTIONS requests:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Best Practice Recommendations
To ensure the CORS preflight mechanism functions correctly, it is recommended to follow these best practices:
- Always properly implement OPTIONS request handling on the server side
- Explicitly specify allowed HTTP methods and request headers, avoiding wildcards
- Reasonably set Access-Control-Max-Age to reduce unnecessary preflight requests
- Restrict Access-Control-Allow-Origin to specific domains in production environments
- Thoroughly test various edge cases to ensure the preflight mechanism is stable and reliable
By deeply understanding the working principles of the CORS preflight mechanism and implementing correct solutions, developers can effectively resolve various issues in cross-origin requests and build more robust web applications.