【问题标题】:PHP cURL gives an error but works fine in POSTMANPHP cURL 出现错误,但在 POSTMAN 中工作正常
【发布时间】:2017-12-27 06:25:26
【问题描述】:

我对 PHP cURL 有一些问题。我尝试使用 PHP cURL 从 API 获取数据。这是我在 PHP 中的 cURL 代码:

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://www.example.com/dos/AW/API",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{\"Filter\" : {\"IsActive\" : \"True\",\"OutputSelector\" : \"Name\"}}",
  CURLOPT_HTTPHEADER => array(
    "API_ACTION: GetItem",
    "API_KEY: MHlIARzQqxVpOg2dUxH4q9w7bx3pOL6K",
    "Accept: application/json"
  ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

?>

使用该代码,我可以获得响应,但响应包含一些错误。我还尝试使用POSTMAN 进行检查,API 工作正常,因为我得到了相同数据的成功响应。我的问题是:“我的cURL 代码有什么问题可以解释为什么我在使用cURL 时出现错误并且我在POSTMAN 中得到了成功响应”?

如果有人可以帮助我,我将不胜感激。 非常感谢。

【问题讨论】:

  • 请参阅stackoverflow.com/questions/13596799/… 并检查您的 CURLOPT_POSTFIELDS 是否为 field1=value&field2=value2 等字符串。然后我认为您缺少 curl_setopt($ch,CURLOPT_POST, 1) 来进行 POST。
  • 您收到什么响应代码?还是什么错误?
  • @BenRoob 也许你可以举一些例子?
  • @BartoszKowalczyk 我刚刚收到错误消息作为回应
  • @Antonio 请告诉我们哪个错误消息;)

标签: php api curl postman


【解决方案1】:

鉴于您没有向我们展示成功的邮递员请求,我们无法确定您犯了什么错误,也就是说,您在这里犯了几个明显的错误。

首先,在调试 curl 代码时,使用 CURLOPT_VERBOSE ,它会在调试 curl 请求时为您提供很多有用的信息(如果您这样做了,您可能会注意到 Postman 请求的 content-type 完全不同来自 curl 的 content-type http 标头 - 稍后会详细介绍)

​​>

其次,当你想要一个 POST 请求时,不要使用CURLOPT_CUSTOMREQUEST,使用CURLOPT_POST

第三,当将字符串传递给 CURLOPT_POSTFIELDS 时,内容类型隐式变为 Content-Type: application/x-www-urlencoded,除非您覆盖它。而且你显然不是发送 x-www-urlencoded 数据,而是 JSON 编码的数据,所以你的内容类型都是错误的,它应该是 Content-type: application/json

第四,您可以根据需要对 json 进行硬编码,但是如果您对其进行 json_encode 编码,代码看起来会更漂亮

第五,不检查返回类型,不要使用setopt/setopt_array。

解决所有这些问题,您最终会得到如下结果:

function ecurl_setopt_array($ch, array $options) {
    if (! curl_setopt_array ( $ch, $options )) {
        throw new \RuntimeException ( 'curl_setopt_array failed. ' . curl_errno ( $ch ) . ': ' . curl_error ( $ch ) );
    }
}

$curl = curl_init ();

ecurl_setopt_array ( $curl, array (
        CURLOPT_URL => "https://www.example.com/dos/AW/API",
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_ENCODING => "",
        CURLOPT_MAXREDIRS => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_VERBOSE => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode ( array (
                'Filter' => array (
                        'IsActive' => 'True',
                        'OutputSelector' => 'Name' 
                ) 
        ) ),
        CURLOPT_HTTPHEADER => array (
                "API_ACTION: GetItem",
                "API_KEY: MHlIARzQqxVpOg2dUxH4q9w7bx3pOL6K",
                "Accept: application/json",
                'Content-Type: application/json' 
        ) 
) );

$response = curl_exec ( $curl );
$err = curl_error ( $curl );

curl_close ( $curl );

if ($err) {
    echo "cURL Error #:" . $err;
} else {
    echo $response;
}

编辑:修复了 json 数据,当我编写它时,我没有看到 isActive 不是实际的布尔值,而是字符串文字 True - 我错误地将其编码为 json 布尔值 true,抱歉, 固定的。 (尽管我怀疑它应该是一个布尔值,并且您的原始代码只是对其进行了错误的编码,也许您应该在 api 文档中仔细检查 isActive 的类型,假设有一个)

【讨论】:

  • 我知道有什么问题。将ecurl_setopt_array 替换为curl_setopt_array 即可。
  • 在 POST 中使用 CURLOPT_POST 而不是 CURLOPT_CUSTOMREQUEST 是否有实际理由,还是纯粹是语义上的?我已经使用了后者很多没有问题。
  • @MagnusBull 是的。引用the official libcurl documentationMany people have wrongly used this option to replace the entire request with their own, including multiple headers and POST contents. While that might work in many cases, it will cause libcurl to send invalid requests and it could possibly confuse the remote server badly. Use CURLOPT_POST and CURLOPT_POSTFIELDS to set POST data. Use CURLOPT_HTTPHEADER to replace or extend the set of headers sent by libcurl. Use CURLOPT_HTTP_VERSION to change HTTP version.,嗯
  • @MagnusBull 我个人注意到的是 CURLOPT_CUSTOMREQUEST 会覆盖其他所有内容,并且很粘;当您使用 CUSTOMREQUEST 时,CURLOPT_HTTPGETCURLOPT_PUTCURLOPT_POST 不再正常工作,因为 CUSTOMREQUEST 会覆盖所有这些。无论如何,官方 libcurl 文档说“不要将 CUSTOMREQUEST 用于 POST 请求,它可能会导致 curl 发送格式错误的请求”,这应该是足够的理由。
【解决方案2】:

@Antonio,您得到的响应来自另一端,可能是您遗漏了一些限制另一端查询处理的东西。尝试打印 http_code,或使用 curl_getinfo 获取完整信息。

如果响应码是200,那么你可以从另一端请求验证请求。

PS:由于回购限制,无法发表评论。

【讨论】:

  • 在响应行下方的代码中使用以下行 $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  • 使用 CURLOPT_VERBOSE - 它提供的信息比 curl_getinfo 的所有选项加起来还要多。
猜你喜欢
  • 2018-03-04
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 2021-01-26
  • 2021-01-18
  • 2018-04-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多