【问题标题】:cURL POST request works, Guzzle 6 does notcURL POST 请求有效,Guzzle 6 无效
【发布时间】:2018-10-22 07:30:39
【问题描述】:

上下文:

一段时间以来,我一直在研究如何实现这项工作,但我只是不明白为什么 Guzzle 不能满足这个特定的请求。相同的初始化和请求结构在我拥有的一些基本单元测试中有效,但在 API 到 API 的通信方面,Guzzle 只是不合作。

问题:

我的意思是,它不包括我在$headers 数组中设置的标头,并且请求正文为空。

期望的结果:

为了确认这是 Guzzle 的问题,我用典型的 cURL 语法写出了请求,并且请求顺利通过。我只需要一些关于如何使用 Guzzle 进行这项工作的指导,因为我喜欢 Guzzle 提供的抽象 cURL 请求。

工作 cURL 请求:

    $headers = array(
        'Authorization: Bearer '.$sharedSecret,
        'Content-Type: application/x-www-form-urlencoded',
        'Accept: application/json',
        'Content-Length: '.strlen($loginDetails),
    );

    $curlOptions = array(
        CURLOPT_URL             => API_URL.'member/SessionManager',
        CURLOPT_HTTPHEADER      => $headers,
        CURLOPT_RETURNTRANSFER  => FALSE,
        CURLOPT_HEADER          => FALSE,
        CURLOPT_FOLLOWLOCATION  => FALSE,
        CURLOPT_ENCODING        => "",
        CURLOPT_USERAGENT       => "PORTAL",
        CURLOPT_AUTOREFERER     => TRUE,
        CURLOPT_CONNECTTIMEOUT  => 120,
        CURLOPT_TIMEOUT         => 120,
        CURLOPT_MAXREDIRS       => 10,
        CURLOPT_POST            => TRUE,
        CURLOPT_POSTFIELDS      => $loginDetails,
        CURLOPT_SSL_VERIFYHOST  => FALSE,
        CURLOPT_SSL_VERIFYPEER  => FALSE,
        CURLOPT_VERBOSE         => FALSE
    );

    try {
        $ch = curl_init();
        curl_setopt_array($ch,$curlOptions);
        $content    = curl_exec($ch);
        $err        = curl_errno($ch);
        $errmsg     = curl_error($ch);
        $response   = curl_getinfo($ch);
        curl_close($ch);

        if ($content === FALSE) {
            throw new Exception(curl_error($ch), curl_errno($ch));
        } else {
            return true;
        }
    } catch(Exception $e) {
        trigger_error(sprintf('Curl failed with error #%d: %s', $e->getCode(), $e->getMessage()), E_USER_ERROR);
    }

Guzzle 客户端在一个全局文件中初始化,该文件创建一个容器,用于存储我们在整个应用程序中使用的各种对象。我将它包括在内,以防我错过了 Guzzle 文档中没有的重要内容。

Guzzle 初始化:

$container['client'] = function ($c) {
    return new \GuzzleHttp\Client([
        'base_uri'          => API_URL,
        'timeout'           => 30.0,
        'allow_redirects'   => true,
        'verify'            => false,
        'verbose'           => true,
        [
            'headers'   => [
                'Authorization' => 'Bearer '.$sharedSecret,
            ]
        ],
    ]);
};

不工作的 Guzzle 请求:

    $headers = array(
        'Authorization' => 'Bearer '.$sharedSecret,
        'Content-Type'  => 'application/x-www-form-urlencoded',
        'Accept'        => 'application/json',
        'Content-Length'=> strlen($loginDetails),
    );

    try {
        $response = $this->client->post('/api/member/SessionManager',
            ['debug'            => true],
            ['headers'          => $headers],
            ['body'             => $loginDetails]
        );

        if($response) {
            $this->handleResponse($response);
        }

    } catch (GuzzleHttp\Exception\ClientException $e) {
        $response->getResponse();
        $responseBodyAsString = $response->getBody()->getContents();
    }

我是否在 Guzzle 初始化中删除 headers 数组,这并不重要。在请求中找不到 Authorization 标头(已通过 tcpdump、Wireshark 和接收 API 错误日志记录确认),并且 Guzzle 的调试输出没有显示我的标头,也没有我的请求正文在请求中的任何位置。

我很困惑为什么这不起作用,并且非常想了解。我可以走不使用 Guzzle 的路线,但由于简洁,我更愿意使用。任何意见将不胜感激。

【问题讨论】:

    标签: php guzzle6


    【解决方案1】:

    cURL请求中,被调用的API URL是

    API_URL.'member/SessionManager'

    Guzzle 请求中,被调用的 API URL 有额外的文本“/api/” (假设 API_URL 在两种情况下定义相同)

    new \GuzzleHttp\Client([ 'base_uri' => API_URL,

    ...

    $this->client->post('/api/member/SessionManager',

    【讨论】:

    • 我问这个已经几个月了,我才看到你的回答。问题是,端点处理路由的方式,wireshark 应该仍然显示请求中存在的那些标头。我会尝试你的解决方案,但我认为这是 Guzzle 的一个问题。我有几个他们的实施和他们的维护团队对支持查询没有响应。如果这能解决问题,我会为实现自定义请求处理程序而自责,并接受这个答案。
    【解决方案2】:

    感谢这个问题很老,但我想我会分享我的经验,因为我也在为此苦苦挣扎。相当于:

    CURLOPT_POSTFIELDS      => $loginDetails,
    

    在 Guzzle 中是:

    "query" => $loginDetails
    

    另外,我发现如果base_uri不以/结尾,Guzzle会误会。

    考虑到所有这些,您的 POST 请求应如下所示:

            $response = $this->client->post('api/member/SessionManager', // Removed the first / as it's part of the base_uri now
                ['debug'            => true],
                ['headers'          => $headers],
                ['query'            => $loginDetails] // Replaced "body" with "query"
            );
    

    【讨论】:

      猜你喜欢
      • 2018-05-27
      • 1970-01-01
      • 2014-09-18
      • 2023-03-19
      • 1970-01-01
      • 2015-05-25
      • 1970-01-01
      • 1970-01-01
      • 2018-10-27
      相关资源
      最近更新 更多