【问题标题】:CURL doesn't send POSTFIELDS correctly to some serversCURL 无法正确发送 POSTFIELDS 到某些服务器
【发布时间】:2014-04-29 16:13:37
【问题描述】:

我试过搜索,其他答案对我没有帮助。

我正在尝试通过 cURL 发送 POST 数据,但它仅适用于 一些 服务器。是什么赋予了?

我试过了:

if (!empty($data) && $usePost) {
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}

$data 包含一个数组,其键为 products,值为 JSON 字符串。

我也尝试过明确地使用查询:

if (!empty($data) && $usePost) {
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
}

但是,接收服务器上的$_POST 仍然给了我NULL

知道该怎么做吗?

这是整个方法:

public static function execCommand($command, $ch,$data=array(),$cookie_file='genCookie.txt', $usePost = false) {
    $url = $command;
    if (!empty($data) && !$usePost)
        $url .= '?' . http_build_query($data);
    elseif (isset($data['sessionid'])) {
        $url .= '?sessionid=' . $data['sessionid'];
        unset($data['sessionid']);
    }

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);
    curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; rv:21.0) Gecko/20100101 Firefox/21.0');
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

    if (!empty($data) && $usePost) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    }

    return curl_exec($ch);
}

我尝试回显$_REQUEST,所以它不在$_GET 中。我也试过file_get_contents('php://input'),但还是不行。

发送端和接收端都在 Apache 服务器上。

更重要的是,它在大多数服务器上工作,但只有一些忽略它。有没有更安全、更跨平台的方法来做到这一点?

【问题讨论】:

  • 什么服务器? IIS? Apache HTTPD?
  • 您可以粘贴完整的卷曲设置块吗?
  • 已更新。双方都是Apache,代码在原题中
  • 什么时候发生?当您更改客户端(存在此代码的服务器)或更改端点时? (接收帖子的服务器)?
  • 请添加您在客户端接收/评估 $_POST 的方式。

标签: php json curl


【解决方案1】:

我很难相信 Curl 没有向某些服务器发送“发布”字段(您共享的代码看起来不错)。我宁愿假设您在这些服务器上处理 POST 的方式有问题,或者您在其他地方做错了什么。

您可以使用 tcpdump 进行故障排除

$ sudo tcpdump -nl -w - -s0 -A -c 500 tcp port 80 | strings

现在,如果您运行如下示例代码:

<?php

class Curl {

    protected static function getCurlHandler( $url, $data = false, $headers = false ) {
        $ch =  curl_init(); 

        curl_setopt( $ch, CURLOPT_URL, $url );
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt( $ch, CURLOPT_HEADER, 0 );

        if( $headers ) {
            curl_setopt($ch, CURLINFO_HEADER_OUT, true);
            curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
        }

        if( $data ) {
            curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( $data ) );
        }

        return $ch;
    }

    protected static function exec( $ch ) {
        $output = curl_exec( $ch );

        // handle errors

        curl_close( $ch );
        return $output;
    }

    public static function get( $url, $headers = array() ) {
        $ch = self::getCurlHandler( $url, false, $headers );

        return self::exec( $ch );
    }

    public static function post( $url, $data = array(), $headers = array() ) {
        $ch = self::getCurlHandler( $url, $data, $headers );
        curl_setopt( $ch, CURLOPT_POST, 1 );

        return self::exec( $ch );
    }

    public static function put( $url, $data = array(), $headers = array() ) {
        $ch = self::getCurlHandler( $url, $data, $headers );
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");

        return self::exec( $ch );
    }

    public static function delete( $url, $data = array(), $headers = array() ) {
        $ch = self::getCurlHandler( $url, $data, $headers );
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");

        return self::exec( $ch );
    }

}


Curl::post( "http://www.google.com", array('q' => 'hello world'));

您应该在 TCPDUMP 输出中找到类似的内容

POST / HTTP/1.1
Host: www.google.com
Accept: */*
Content-Length: 13
Content-Type: application/x-www-form-urlencoded
q=hello+world

最后一行是最有趣的部分,它清楚地表明 CURL 发送了一个带有所需数据的 POST 请求。

【讨论】:

    【解决方案2】:

    您的替代方法是使用wget,它实质上是从某个位置下载文件。它可能会慢一些,因为您需要打开下载的文件并删除空间。我不相信它可以很好地扩展,并且对于POST 请求不会有好处。 cURL 使用端口 80 工作,这是基本的浏览器端口。这意味着如果您可以通过浏览器访问它,cURL 就可以工作。

    通过您提供的有限信息,我可以提供一些故障排除提示。

    在这种情况下,我将启动请求的 PHP 服务器称为 client,而您正在向 server 发送信息的服务器。

    您应该做的第一件事是确保这在您的服务器上运行。检查您的源代码。

    步骤 1. 尝试提交表单并确保 $_POST 返回信息。如果是这样,您可以继续前进。如果没有,你有一个非常非常奇怪的错误。我很想知道您是否在这些不同的服务器上使用不同的操作系统。

    第 2 步。检查您的服务器 sessionid。确保您的客户希望他们通过GET 来。我知道这似乎很明显,但很多时候显而易见的是失败的根源。如果您的sessionid 失败,您的服务器会做什么?确保您的处理脚本返回如下内容:

    if(session_is_registered($_GET['sessionid']) {
        echo "This is a registered session.";
        $_POST['debugSessionExists'] = true;
    } else {
        echo "This sesion does not exist.";
        $_POST['debugSessionExists'] = false;
    }
    

    感谢echo,您应该也可以在您的客户端上吐出返回数据。

    第 3 步。对所有 $_POST 变量执行相同操作并回显返回。

    foreach($_POST as $key=>$value) {
        echo "{$key} exists and has the value of $value.<BR />";
    }
    echo "Done checking $_POSTs.";
    

    我建议这样做的原因是因为我不确定您迄今为止是如何检查您的 $_POST 值的,并且查看您的 cURL 响应是否获取您未看到的信息并没有什么坏处。这意味着您存储 $_POST 值的方式并没有在您的某些服务器上传输,这就是您的失败点。

    我有兴趣了解这些结果返回的内容。

    【讨论】:

      【解决方案3】:

      如前所述,您可能需要执行 tcpdump 才能准确了解数据是如何到达服务器的。

      您可能会遇到带有 curl 的“Expect”标头,可以禁用该标头:

      http://the-stickman.com/web-development/php-and-curl-disabling-100-continue-header/

      通过禁用 Expect 标头,有一个性能。避免客户端和服务器之间额外往返的优势,尽管代价是绕过服务器端的额外检查(例如强制执行最大 POST 正文大小等......)。

      希望对你有帮助。

      【讨论】:

        【解决方案4】:

        尝试使用http://req.uest.info/进行调试

        您还检查过您的原始服务器的日志吗?

        【讨论】:

          【解决方案5】:

          更重要的是,它可以在大多数服务器上运行,但只有一些服务器忽略它。

          POST 发送正常,但服务器不同。对于初学者,请比较 PHP 版本。

          例如; since PHP 4.2.0 register_globals is off,如果接收端重用变量名称,如 $foo VS $_POST['foo'],则可能会给出类似的 NULL 结果。

          有没有更安全、更跨平台的方法来做到这一点?

          不,POST 是发送数据的好方法。但请记住,除非您使用加密或 https,否则数据是通过网络以明文形式发送的。

          【讨论】:

            【解决方案6】:

            原来问题在于接收服务器上的 SSL。请求是发给HTTP而不是HTTPS,它没有给出错误或重定向,只是在途中丢弃了POST(也许它重定向到HTTPS但未能同时传递POST?)

            【讨论】:

              猜你喜欢
              • 2014-12-07
              • 2018-12-18
              • 2017-12-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-05-17
              • 1970-01-01
              • 2013-09-24
              相关资源
              最近更新 更多