【问题标题】:json api output via bash curl vs output via php curl通过 bash curl 输出的 json api 与通过 php curl 输出
【发布时间】:2021-09-17 13:21:51
【问题描述】:

环境:

  • Ubuntu 18.04.5 LTS
  • PHP 7.2.24-0ubuntu0.18.04.7
  • 卷曲 7.58.0

一般行为: 我正在使用 php cUrl 与 json rest api 连接。其中,api 规范显示了登录过程。

成功时,api 返回 http 级别 200 和类似的成功 json 字符串

{
"token":"ey...RU",
"expiration":"2021-07-07T00:39:45"
}

如果失败(假密码等),它会返回 http 级别 401 和类似的 json 字符串

{
  "type": "https://tools.ietf.org/html/rfc7235#section-3.1",
  "title": "Unauthorized",
  "status": 401,
  "traceId": "00-009af152168b684da1a6a543d11a3357-63fd91f4be1fc443-00"
}

我基本上在How to curl via php 处克隆了解决方案,但没有更改它返回 411 并且没有正文。我尝试了不同的接受标头,但没有成功。我还尝试了内容长度标头,但无济于事。我终于确定了那些使用 bash curl 方法的人。

要点: 在成功案例和失败案例中都需要 json 字符串。实际上,这适用于命令行领域,但仅适用于具有正确凭据的 php curl 的情况。

api 中还有其他几个 msg,它们返回各种 http 级别的失败代码,使用 bash curl,返回 json 字符串 - php curl 不返回。

实际结果: 使用具有正确凭据的任一方法,都会收到成功的 json 字符串(给出令牌和过期时间,如上所示)。

如果凭据不正确,bash curl 返回失败的 json 字符串:

> curl  -X POST "https://<api endpoint url>/api/Authenticate/login" \
      -H  "accept: text/plain" -H  "Content-Type: application/json-patch+json" \
      -d "{\"username\":\"valid_username\",\"password\":\"bogus_password\"}"

    {"type":"https://tools.ietf.org/html/rfc7235#section-3.1",
    "title":"Unauthorized",
    "status":401,
    "traceId":"00-a4edb6cfca5918499f1bfaa073206118-da71a7d85e582448-00"}

尝试使用 php curl 使用虚假凭据登录,但没有:

$curl = curl_init();

curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');

curl_setopt($curl, CURLOPT_URL, '<the real json endpoint uri>);
curl_setopt($curl, CURLOPT_FAILONERROR, true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

curl_setopt($curl, CURLOPT_VERBOSE, true);  
# curl_setopt($curl, CURLOPT_STDERR, $out);   

$hdrs = ["accept: text/plain",
         "Content-Type: application/json-patch+json"
        ];
curl_setopt($curl, CURLOPT_HTTPHEADER, $hdrs);

$params = ['username' => 'valid_username',
           'password' => 'bogus password'
          ];
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($params));
// json_encode sanitization omitted here for clarity

$output = curl_exec($curl);

$responseCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if("200" != $responseCode)
    $responseCode .= "  -  " . curl_error($curl);

$info = curl_getinfo($curl);
curl_close($curl);


print("==========\n\n");

printf("output: %s \n", var_export($output, true));
printf("responseCode: %s \n", $responseCode);
printf("info: %s \n", print_r($info, true));

print("==========\n\n");

输出: 注意没有失败的json主体。

* Trying 2xx.xxx.xx.xx...
* TCP_NODELAY set
* Connected to <the real json endpoint uri> (2xx.xxx.xx.xx) port 443 (#0)
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: CN=*.<the real json endpoint uri>
*  start date: Jun 22 15:31:01 2021 GMT
*  expire date: Sep 20 15:31:00 2021 GMT
*  subjectAltName: host "<the real json endpoint uri>" matched cert's "<the real json endpoint uri>"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
> POST /api/Authenticate/login HTTP/1.1
Host: <the real json endpoint uri>
accept: text/plain
Content-Type: application/json-patch+json
Content-Length: 73

* upload completely sent off: 73 out of 73 bytes
* The requested URL returned error: 401 Unauthorized
* stopped the pause stream!
* Closing connection 0
   
==========

output: false   
 
responseCode: 401  -  The requested URL returned error: 401 Unauthorized   
 
info: Array
(
    [url] => https://<the real json endpoint uri>
    [content_type] => 
    [http_code] => 401
    [header_size] => 0
    [request_size] => 237
    [filetime] => -1
    [ssl_verify_result] => 0
    [redirect_count] => 0
    [total_time] => 0.625
    [namelookup_time] => 0.060492
    [connect_time] => 0.156226
    [pretransfer_time] => 0.428025
    [size_upload] => 73
    [size_download] => 0
    [speed_download] => 0
    [speed_upload] => 116
    [download_content_length] => -1
    [upload_content_length] => 73
    [starttransfer_time] => 0.624949
    [redirect_time] => 0
    [redirect_url] => 
    [primary_ip] => 2xx.xxx.xx.xx
    [certinfo] => Array
        (
        )

    [primary_port] => 443
    [local_ip] => 10.10.10.105
    [local_port] => 42192
)

==========

问题: php curl如何获取并显示401情况下的失败json response/body?

【问题讨论】:

  • // json_encode sanitization omitted here for clarity 这是一个巨大的危险信号,因为json_encode() 输出应该需要no“清理”。
  • 您将 CURLOPT_FAILONERROR 设置为 true,这意味着 cURL 将不再在状态码 >= 400 的响应中返回请求正文。
  • @CBroe - 谢谢,谢谢,谢谢!如果您做出评论回答,我会检查它是否被接受。你修好了,你值得称赞:)
  • @sammitch - 不,但返回码可以。

标签: php json bash curl


【解决方案1】:

没有更改它返回 411 并且没有正文。

您已将 CURLOPT_FAILONERROR 设置为 true,这意味着 cURL 将不再在状态码 >= 400 的响应中返回请求正文。

删除它,无论状态码表示成功还是某种失败,都应该得到响应正文。

【讨论】:

    猜你喜欢
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    • 2013-08-04
    • 2014-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多