PHP file_get_contents 在HTTP请求中返回不一致的部分数据。

问题描述 投票:0回答:1

我试图使用PHP SoapClient来执行对第三方应用程序的请求。 当我创建SoapClient对象时,我得到一个关于WSDL数据过早结束的错误。 在尝试诊断这个错误时,我发现WSDL URI的file_get_contents()并没有返回整个XML。 事实上,它经常返回不同数量的WSDL。 这是我的测试程序。

$xml = file_get_contents('https://webservices3.autotask.net/atservices/1.6/atws.wsdl');
echo $xml . "\n";
echo strlen($xml). "\n";

我每次得到大约57k字节(195628是正确的值),有时更多,很少得到整个XML。 我相信这是PHP的问题,因为一个shell循环调用curl或wget 100次,100%都会返回整个文件。 我使用的是 PHP 5.4.16,我知道这已经是老版本了(2013 年),但是这个过程工作了大约一个月,然后就完全停止了。

我试过改变超时、HTTP 协议版本、PHP 内存设置,但我不明白为什么 file_get_contents 会有这样的行为。 感谢任何建议。

Curl测试。

for a in $( seq 1 100 ); do curl -o wsdl.$a https://webservices3.autotask.net/atservices/1.6/atws.wsdl; done

Wget测试

for a in $( seq 1 100 ); do wget -O wsdl.$a https://webservices3.autotask.net/atservices/1.6/atws.wsdl; done

更新1:

将maxlen设置为某个愚蠢的大数并不影响行为。

$xml = file_get_contents('https://webservices3.autotask.net/atservices/1.6/atws.wsdl', false, null, 0, 999999);
echo $xml . "\n";
echo strlen($xml). "\n";

更新2:将maxlen设置为一个愚蠢的大数并不影响行为。

$ curl -s -D /dev/stderr -- https://webservices3.autotask.net/atservices/1.6/atws.wsdl > /dev/null
HTTP/1.1 200 OK
Content-Type: text/xml
Last-Modified: Wed, 29 Apr 2020 14:38:25 GMT
Accept-Ranges: bytes
ETag: "39163cd7331ed61:0"
Server: Microsoft-IIS/8.5
X-Powered-By: ASP.NET
Content-Security-Policy: default-src 'self' https: *;script-src 'self' 'unsafe-inline' 'unsafe-eval' https: *;style-src 'self' 'unsafe-inline';img-src 'self' https://walkme.psa.datto.com/Images/ data: https://www.datto.com/img/
Date: Fri, 08 May 2020 15:22:28 GMT
Content-Length: 195628

以下是 PHP 报告的响应头。

$xml = file_get_contents('https://webservices3.autotask.net/atservices/1.6/atws.wsdl');
echo $xml . "\n";
echo strlen($xml). "\n";
echo var_dump($http_response_header);

array(11) {
  [0]=> string(15) "HTTP/1.1 200 OK"
  [1]=> string(22) "Content-Type: text/xml"
  [2]=> string(44) "Last-Modified: Wed, 29 Apr 2020 14:38:25 GMT"
  [3]=> string(20) "Accept-Ranges: bytes"
  [4]=> string(25) "ETag: "39163cd7331ed61:0""
  [5]=> string(25) "Server: Microsoft-IIS/8.5"
  [6]=> string(21) "X-Powered-By: ASP.NET"
  [7]=> string(228) "Content-Security-Policy: default-src 'self' https: *;script-src 'self' 'unsafe-inline' 'unsafe-eval' https: *;style-src 'self' 'unsafe-inline';img-src 'self' https://walkme.psa.datto.com/Images/ data: https://www.datto.com/img/ "
  [8]=> string(35) "Date: Fri, 08 May 2020 15:26:54 GMT"
  [9]=> string(22) "Connection: keep-alive"
  [10]=> string(22) "Content-Length: 195628"
}

更新 3: PHP 的 Content-Length 头文件损坏。

使用 gzip 时,PHP 的 Content-Length 头文件损坏。

$ctx = stream_context_create(array(
    'http' => array(
        'header' => "Accept-Encoding: gzip\r\n"
     )
));
$xml = file_get_contents('https://webservices3.autotask.net/atservices/1.6/atws.wsdl', false, $ctx);
echo var_dump($http_response_header);

array(12) {
  [0]=> string(15) "HTTP/1.1 200 OK"
  [1]=> string(22) "Content-Type: text/xml"
  [2]=> string(44) "Last-Modified: Wed, 29 Apr 2020 14:35:51 GMT"
  [3]=> string(20) "Accept-Ranges: bytes"
  [4]=> string(24) "ETag: "b376e7b331ed61:0""
  [5]=> string(25) "Server: Microsoft-IIS/8.5"
  [6]=> string(21) "X-Powered-By: ASP.NET"
  [7]=> string(228) "Content-Security-Policy: default-src 'self' https: *;script-src 'self' 'unsafe-inline' 'unsafe-eval' https: *;style-src 'self' 'unsafe-inline';img-src 'self' https://walkme.psa.datto.com/Images/ data: https://www.datto.com/img/ "
  [8]=> string(35) "Date: Fri, 08 May 2020 15:44:12 GMT"
  [9]=> string(22) "Connection: keep-alive"
  [10]=> string(22) "ntCoent-Length: 195628"
  [11]=> string(22) "Content-Encoding: gzip"

}

更新4:

来自使用gzip的curl的头文件(注意它们看起来是正确的)。

$ curl --compressed -s -D /dev/stderr -- https://webservices3.autotask.net/atservices/1.6/atws.wsdl > /dev/null
HTTP/1.1 200 OK
Content-Type: text/xml
Content-Encoding: gzip
Last-Modified: Wed, 29 Apr 2020 14:35:51 GMT
Accept-Ranges: bytes
ETag: "807d37b331ed61:0"
Vary: Accept-Encoding
Server: Microsoft-IIS/8.5
X-Powered-By: ASP.NET
Content-Security-Policy: default-src 'self' https: *;script-src 'self' 'unsafe-inline' 'unsafe-eval' https: *;style-src 'self' 'unsafe-inline';img-src 'self' https://walkme.psa.datto.com/Images/ data: https://www.datto.com/img/
Date: Fri, 08 May 2020 16:12:13 GMT
Content-Length: 13192

我可以强制SoapClient不使用gzip,这确实解决了这个问题,尽管效率不高。 我们仍然没有找到 PHP 弄乱头文件的根本原因。

// Autotask Client options
$auth_opts = array(
    'login'    => $username,
    'password' => $password,
    'trace'    => 1,
    'http'     => array(
        'header' => array(
            'Accept-Encoding' => 'identity' // here be dragons
        )
    )
);

更新 5.我们确认这个问题仍然可以重现。

我们确认这个问题在 PHP 7.2 中仍然可以重现。 我已经打开了一个 虫子 与PHP团队。

php file-get-contents
1个回答
0
投票

webservices3.autotask.net在响应中出现了错误的头。

HTTP/1.1 200 OK
Content-Type: text/xml
Accept-Ranges: bytes
Server: Microsoft-IIS/8.5
X-Powered-By: ASP.NET
Cteonnt-Length: 195628
Cache-Control: private
Content-Encoding: gzip
Transfer-Encoding: chunked

注意: Cteonnt-Length: 195628 应该是 Content-Length: 195628

这就是为什么 file_get_contents 不能正确处理请求。

所以,修复响应或设置 maxlen

UPD:这是乱七八糟的头。这个应该可以用 https:/stackoverflow.coma85820423849743。


0
投票

这似乎是PHP的一个错误。 有一个 虫子 问题结尾处的报告。

© www.soinside.com 2019 - 2024. All rights reserved.