使用jQuery AJAX配合PHP代理请求数据返回空字符串如何解决
问题根因分析
你的代码主要存在3个核心错误,导致请求返回空:
- Content-Type头冲突:
makePostRequest方法中设置了Content-Type: application/json的请求头,但initCurl方法又全局追加了Content-Type: application/x-www-form-urlencoded头,两个冲突的头会导致目标接口无法正常解析请求参数,直接返回异常或空响应。同时你调用http_build_query生成的是表单格式的请求体,和你设置的json头完全不匹配。 - 缺少CURL错误排查逻辑:当前代码中
curl_exec执行失败时会返回布尔值false,直接输出会被转换为空字符串,你看不到具体的错误信息(比如PHP环境没开curl扩展、网络不通、SSL证书验证失败等常见问题)。 - 请求头重复覆盖问题:
makePutOrPostCurl方法中传入的自定义请求头,没有覆盖initCurl中设置的默认头,导致自定义头不生效。
修复后的代码
proxy.php 代码
<?php // 先开启错误提示方便排查,调试完可以关掉 error_reporting(E_ALL); ini_set('display_errors', 1); $url = $_REQUEST["url"]; if(!$url) { echo "You need to pass in a target URL."; return; } // 允许跨域访问代理接口,如果你前端和代理同域可以去掉 header("Access-Control-Allow-Origin: *"); header("Access-Control-Allow-Methods: GET, POST, OPTIONS"); $response = ""; switch (getMethod()) { case 'POST': $response = makePostRequest(getPostData(), $url); break; case 'GET': $response = makeGetRequest($url); break; default: echo "This proxy only supports POST AND GET REQUESTS."; return; } // 把目标接口的Content-Type返回给前端,避免解析异常 $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE); header("Content-Type: $contentType"); echo $response; function getMethod() { return $_SERVER["REQUEST_METHOD"]; } function getPostData() { // 如果目标接口需要json格式,这里改成json_encode($_POST) return http_build_query($_POST); } function makePostRequest($data, $url) { // 请求体是表单格式,头就对应表单格式,不要写json $httpHeader = array( 'Content-Type: application/x-www-form-urlencoded', 'Content-Length: ' . strlen($data) ); return makePutOrPostCurl('POST', $data, true, $httpHeader, $url); } function makeGetRequest($url) { $ch = initCurl($url, []); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 关闭SSL验证,避免本地调试时https接口报错,生产环境可以打开 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $response = curl_exec($ch); // 打印curl错误方便排查 if(curl_errno($ch)) { echo 'Curl error: ' . curl_error($ch); } curl_close($ch); return $response; } function makePutOrPostCurl($type, $data, $returnTransfer, $httpHeader, $url) { $ch = initCurl($url, $httpHeader); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $type); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, $returnTransfer); // 关闭SSL验证 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $response = curl_exec($ch); if(curl_errno($ch)) { echo 'Curl error: ' . curl_error($ch); } curl_close($ch); return $response; } // 新增参数接收自定义头,覆盖默认头 function initCurl($url, $customHeaders = []) { $defaultHeaders = array( 'Content-Type: application/x-www-form-urlencoded' ); // 合并头,自定义头覆盖默认头 $headers = array_merge($defaultHeaders, $customHeaders); $ch = curl_init($url); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36'); return $ch; } ?>
script.js 代码不需要大改,补充错误回调方便排查即可:
$(document).ready(function () { $.ajax({ url: 'proxy.php?url=https://reqres.in/api/users', type: 'POST', data: { name: 'Zlatan Ibrahimovic' }, success: function (data) { console.log('POST结果:', data); }, error: function (xhr, err) { console.log('POST报错:', err, xhr.responseText); } }); $.get('proxy.php?url=https://reqres.in/api/users', function (data) { console.log('GET结果:', data); }).fail(function(xhr, err) { console.log('GET报错:', err, xhr.responseText); }); });
额外排查点
- 先确认你的PHP环境开启了curl扩展:新建一个php文件写入
<?php phpinfo(); ?>,访问后搜索curl看是否启用 - 直接在浏览器地址栏访问
你的代理地址/proxy.php?url=https://reqres.in/api/users,看是否能直接返回接口数据,如果可以说明PHP代理正常,问题在前端请求路径 - 如果是POST请求需要传JSON格式参数,把
getPostData方法的返回值改成json_encode($_POST),同时把makePostRequest里的Content-Type改成application/json即可
内容的提问来源于stack exchange,提问作者Adam Mann
相关产品推荐
相关产品推荐

