CURL无法将POSTFIELDS正确发送到某些服务器

i2loujxw  于 2022-11-13  发布在  其他
关注(0)|答案(6)|浏览(212)

我试过搜索,其他的答案对我没有帮助。
我试图通过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服务器上。
更重要的是,它在大多数服务器上都能正常工作,但只有一些服务器忽略了它。有没有更安全、更跨平台的方法来做到这一点?

rbl8hiat

rbl8hiat1#

我发现很难相信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请求。

hec6srdp

hec6srdp2#

您的替代方案是使用wget,它本质上是从一个位置下载一个文件。它可能会有点慢,因为您需要打开您下载的文件并删除空间。我不相信它的伸缩性很好,它不会适合POST请求。cURL使用端口80工作,这是基本的浏览器端口。这意味着如果你可以通过浏览器访问它,cURL就可以工作。
通过您提供的有限信息,我可以提供一些故障排除提示。
在本例中,我调用的是启动请求的PHP服务器客户端和向服务器发送信息的服务器。
首先你应该做的是确保这在你的服务器上是工作的。检查你的源代码。
第一步:尝试提交一个表单,并确保$_POST返回信息。如果它返回了,你可以继续。如果它没有返回,你有一个非常非常奇怪的bug。我很想知道你是否在这些不同的服务器上使用了不同的操作系统。
第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变量执行同样的操作,并回显一个return。

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

我建议这样做的原因是我不确定你是如何检查你的$_POST值的,看看你的cURL响应是否得到了你看不到的信息也无妨。这意味着你存储$_POST值的方式在你的一些服务器上没有传输,这就是你的失败点。
我将有兴趣找出通过这些结果返回什么。

t8e9dugd

t8e9dugd3#

尝试使用http://req.uest.info/进行调试
你也检查了你的原始服务器的日志吗?

oknrviil

oknrviil4#

更重要的是,它在大多数服务器上都能正常工作,但只有一些服务器忽略了它。
POST发送正常,但服务器不同。对于初学者,比较PHP版本。
例如:因为PHP4.2.0register_globals是关闭的,如果接收端重复使用$foo VS $_POST['foo']这样的变量名,可能会给予类似的NULL结果。
是否有更安全、更跨平台的方法来实现这一点?
不,POST是发送数据的好方法。但是请记住,除非使用加密或https,否则数据是以明文形式通过线路发送的。

bis0qfac

bis0qfac5#

结果发现问题出在接收服务器上的SSL上。请求是向HTTP而不是HTTPS发出的,并且没有给出错误或重定向,而是在途中简单地丢弃了POST(也许它重定向到HTTPS,但未能通过POST?)

9rygscc1

9rygscc16#

如前所述,您可能需要执行tcpdump以确切地查看数据如何到达服务器。
您可能会遇到带有curl的“Expect”标题,该标题可以禁用:
http://the-stickman.com/web-development/php-and-curl-disabling-100-continue-header/
通过禁用Expect标头,可以避免客户端和服务器之间的额外往返,尽管代价是绕过服务器端的额外检查(例如,强制执行最大POST主体大小等)。

相关问题