容器间PHP CURL请求问题:API容器无法读取POST数据排查求助
问题拆解与解决办法
嘿,我一眼就看到核心问题了——你更新后的CURL发的是JSON格式的请求,但你的API代码还在靠$_POST来拿数据,可PHP默认根本不会把JSON请求体解析到$_POST数组里啊!这就是为啥你一直拿到null的原因。
下面给你两个解决方案,选哪个看你需求:
方案一:改CURL发表单格式数据(适配现有API,最省事)
既然你的API原本是为表单提交写的,那直接让CURL发送标准的application/x-www-form-urlencoded格式数据就行,不用搞JSON:
$email = $_POST['email']; $password = $_POST['password']; // 用http_build_query生成符合表单规范的字符串 $data = http_build_query([ 'email' => $email, 'password' => $password ]); $headers = array( "Content-Type: application/x-www-form-urlencoded", // 明确告诉服务器这是表单数据 "Accept: application/json", ); pretty_var_dump($data); $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, 'http://127.0.0.1:86'); curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 加个CURL错误检查!这步超级重要,能帮你排查请求发没发出去 if(curl_errno($curl)) { die('CURL出错了:' . curl_error($curl)); } $curl_response = curl_exec($curl); curl_close($curl); $response = json_decode($curl_response, true); pretty_var_dump($response);
这样发的请求和普通网页表单提交一模一样,API里的$_POST['email']和$_POST['password']就能正常读到数据了。
方案二:改API解析JSON请求体(如果想保留JSON格式)
要是你非得用JSON传数据,那得在API里手动读取请求体并解析,加一段代码在API文件最开头:
// 判断请求是不是JSON类型 if ($_SERVER['CONTENT_TYPE'] === 'application/json') { // 读取原始的JSON请求内容 $json_content = file_get_contents('php://input'); // 把JSON转成关联数组 $post_data = json_decode($json_content, true); // 把解析后的数据赋值给$_POST,后面的代码不用大改 $_POST = $post_data ?: []; }
加完这段,API就能正确识别CURL发的JSON数据了,后面的逻辑不用动就能正常工作。
额外提醒几个关键点
- 容器网络问题:如果你是用Docker部署的容器,更新后的CURL用了
127.0.0.1:86,但要是API容器是用服务名(比如原来的api)注册的,那得用服务名访问,比如http://api:80,不然代理容器可能连不上API容器。 - SQL注入风险:你的API里直接把
$email拼进SQL语句里,这是要命的安全漏洞!必须用预处理语句来查数据库,示例代码给你:
// 用占位符代替直接拼接变量 $select_query = "SELECT user_password, user_id, user_email, user_status FROM user_login WHERE user_email = ?"; $stmt = $conn->prepare($select_query); $stmt->bind_param("s", $email); // 绑定变量,s表示字符串类型 $stmt->execute(); $result = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
这能彻底杜绝SQL注入,一定要改!
3. CURL错误排查:以后写CURL记得加错误检查,不然请求失败了你都不知道为啥,白浪费时间排查。
内容的提问来源于stack exchange,提问作者Aidan Campbell
相关产品推荐
相关产品推荐

