技术讲座:CORS 预检请求(Preflight)与自定义 Header 的关系
引言
跨源资源共享(CORS)是一种机制,它允许一个资源(比如一个网页)从不同的源请求另一个源的资源。在实现这一机制的过程中,浏览器会发送一个预检请求(Preflight)来询问服务器是否允许实际的请求。本文将深入探讨为什么自定义 Header 会触发一次额外的 OPTIONS 请求,并提供一些工程级的代码示例。
CORS 预检请求(Preflight)
当浏览器需要从一个不同的源(源指的是协议+域名+端口)请求资源时,它会首先发送一个预检请求(OPTIONS)。这个请求的目的是询问服务器是否允许实际请求,以及哪些HTTP方法和头部信息可以被使用。
预检请求的格式如下:
OPTIONS /resource HTTP/1.1
Host: example.com
Origin: http://client.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Custom-Header
在这个请求中,Access-Control-Request-Method 指定了实际请求将要使用的方法,而 Access-Control-Request-Headers 指定了实际请求将要使用的自定义头部。
自定义 Header 触发额外的 OPTIONS 请求
当预检请求中包含了自定义 Header 时,服务器需要检查这个头部是否被允许。由于服务器可能不认识这个自定义头部,它需要再次确认是否允许使用这个头部。这就导致了额外的 OPTIONS 请求。
示例:使用 PHP 处理预检请求
以下是一个使用 PHP 处理预检请求的示例:
<?php
// 检查是否是预检请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
// 允许的HTTP方法
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
// 允许的头部信息
header('Access-Control-Allow-Headers: X-Custom-Header, Content-Type');
// 允许的来源
header('Access-Control-Allow-Origin: http://client.com');
// 预检请求的响应体为空
header('Content-Length: 0');
// 状态码
http_response_code(204);
exit;
}
// 处理实际的请求
// ...
?>
在这个示例中,当接收到一个预检请求时,服务器会设置一些响应头,包括允许的HTTP方法、头部信息和来源。如果服务器不认识 X-Custom-Header,它将再次发送一个预检请求来确认是否允许使用这个头部。
示例:使用 Python 处理预检请求
以下是一个使用 Python 处理预检请求的示例:
from flask import Flask, request, make_response
app = Flask(__name__)
@app.route('/resource', methods=['GET', 'POST', 'OPTIONS'])
def resource():
if request.method == 'OPTIONS':
response = make_response()
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
response.headers['Access-Control-Allow-Headers'] = 'X-Custom-Header, Content-Type'
response.headers['Access-Control-Allow-Origin'] = 'http://client.com'
response.headers['Content-Length'] = '0'
response.status_code = 204
return response
else:
# 处理实际的请求
# ...
return 'Resource content'
if __name__ == '__main__':
app.run()
在这个示例中,我们使用了 Flask 框架来处理预检请求。当接收到一个预检请求时,服务器会设置一些响应头,包括允许的HTTP方法、头部信息和来源。
总结
本文深入探讨了 CORS 预检请求(Preflight)与自定义 Header 的关系。当预检请求中包含了自定义 Header 时,服务器需要检查这个头部是否被允许,这可能导致额外的 OPTIONS 请求。通过提供 PHP 和 Python 的代码示例,我们展示了如何处理预检请求并设置相应的响应头。
在实际开发中,了解 CORS 预检请求的工作原理对于确保跨源资源共享的正确实现至关重要。希望本文能够帮助您更好地理解这一机制。