CORS预检拦截API请求求助:WordPress主题跨域调用DVLA API失败
解决WordPress子主题中跨域API请求的CORS问题
问题详情
用标准HTML、PHP、JavaScript制作WordPress子主题时,调用英国DVLA车辆查询API(https://driver-vehicle-licensing.api.gov.uk/vehicle-enquiry/v1/vehicles)遇到CORS拦截。关闭Chrome安全限制后,函数逻辑能正常返回车辆详情,但正常模式下控制台报错:
"Failed preflight check, access-control-allow-origin header is missing"
明确这是跨域问题,但尝试添加access-control-allow-origin响应头后毫无效果,本地MAMP服务器、生产服务器甚至单HTML文件中都存在该问题。
前端请求代码(来自front-page.php):
<script> function submitReg() { var url = "https://driver-vehicle-licensing.api.gov.uk/vehicle-enquiry/v1/vehicles"; var xhr = new XMLHttpRequest(); xhr.open("POST", url); xhr.setRequestHeader("x-api-key", "APIKEYPLACEHOLDER"); xhr.setRequestHeader("Content-Type", "application/json"); xhr.onreadystatechange = function() { if (xhr.readyState === 4){ console.log(xhr.status); console.log(xhr.responseText); } }; var reg = document.getElementById("inputReg"); var data = JSON.stringify({"registrationNumber": reg.value}); xhr.send(data); } </script>
已尝试但无效的方法
- 修改
.htaccess文件(请求域名为example.com):
# BEGIN WordPress # The directives (lines) between "BEGIN WordPress" and "END WordPress" are # dynamically generated, and should only be modified via WordPress filters. # Any changes to the directives between these markers will be overwritten. Header set Access-Control-Allow-Origin "example.com" Header set Access-Control-Allow-Credentials true Header set Access-Control-Allow-Methods "POST, GET" # END WordPress
- 在header.php和front-page.php顶部添加PHP头信息:
<?php header('Access-Control-Allow-Origin: *'); ?>
正确解决方案:后端代理
前端直接请求第三方API时,对方服务器未配置允许你的域名跨域,此时在自己服务器加CORS头完全无效——必须通过后端代理转发请求。
步骤1:创建代理PHP文件
在WordPress子主题目录下新建proxy-vehicle-api.php,代码如下:
<?php // 允许你的前端域名跨域(替换为实际域名) header("Access-Control-Allow-Origin: https://example.com"); header("Access-Control-Allow-Methods: POST"); header("Access-Control-Allow-Headers: Content-Type"); // 获取前端发送的POST数据 $data = file_get_contents('php://input'); // 初始化cURL请求 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://driver-vehicle-licensing.api.gov.uk/vehicle-enquiry/v1/vehicles"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 携带API密钥和请求头 curl_setopt($ch, CURLOPT_HTTPHEADER, array( "x-api-key: 你的真实API密钥", // 替换为你的API密钥 "Content-Type: application/json" )); // 执行请求并获取响应 $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // 将响应返回给前端 http_response_code($httpCode); echo $response; curl_close($ch); ?>
步骤2:修改前端请求地址
把前端JS中的请求URL改成代理文件的路径,示例:
<script> function submitReg() { // 替换为你的代理文件实际路径 var url = "/wp-content/themes/你的子主题文件夹/proxy-vehicle-api.php"; var xhr = new XMLHttpRequest(); xhr.open("POST", url); xhr.setRequestHeader("Content-Type", "application/json"); xhr.onreadystatechange = function() { if (xhr.readyState === 4){ console.log(xhr.status); console.log(xhr.responseText); } }; var reg = document.getElementById("inputReg"); var data = JSON.stringify({"registrationNumber": reg.value}); xhr.send(data); } </script>
注意事项
- 确保你的服务器已开启cURL扩展
- API密钥放在后端,避免前端泄露
- 如果需要携带Cookie等凭证,需调整
Access-Control-Allow-Credentials并在前端请求中设置withCredentials: true
内容的提问来源于stack exchange,提问作者user3512002
相关产品推荐
相关产品推荐

