CURL不会将POSTFIELDS正确发送到某些服务器

时间:2014-04-29 16:13:37

标签: php json curl

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

我正在尝试通过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服务器上。

更重要的是,它正在大多数服务器上运行,但只有某些忽略它。是否有更安全,更跨平台的方式来做到这一点?

6 个答案:

答案 0 :(得分:4)

我发现很难相信Curl没有向某些服务器发送“post”字段(您共享的代码看起来没问题)。我宁愿假设你在这些服务器上处理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请求。

答案 1 :(得分:1)

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

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

在这种情况下,我打电话给你的PHP服务器发起客户端的请求以及你要向服务器发送信息的服务器。

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

步骤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值的方式只是不在您的某些服务器上传输,这是您的失败点。

我很想知道通过这些结果返回的内容。

答案 2 :(得分:0)

如前所述,您可能需要执行tcpdump以确切了解数据如何进入服务器。

你可能正在使用curl运行'Expect'标题,可以禁用它:

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

通过禁用Expect标头,有一个perf。避免在客户端和服务器之间进行额外往返的优点,虽然以绕过服务器端的额外检查为代价(例如,强制执行最大的POST主体大小等等)。

希望它有所帮助。

答案 3 :(得分:0)

尝试使用http://req.uest.info/

进行调试

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

答案 4 :(得分:0)

  

更重要的是,它适用于大多数服务器,但只有一些服务器忽略它。

POST发送正常,但服务器不同。首先,比较PHP版本。

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

  

是否有更安全,更跨平台的方式来做到这一点?

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

答案 5 :(得分:0)

原来问题是接收服务器上的SSL。正在向HTTP而不是HTTPS发出请求,而不是给出错误或重定向,它只是在途中删除了POST(可能是重定向到HTTPS但无法通过POST同时吗?)