【问题标题】:Error fetching http headers in SoapClient在 SoapClient 中获取 http 标头时出错
【发布时间】:2012-03-13 07:03:06
【问题描述】:

我正在尝试在远程主机上通过 https 调用 WS:远程端口,我得到:

获取 http 标头时出错

使用 PHP5 SoapClient;我可以通过$client->__getFunctions() 获取函数列表,但是当我调用$client->myFunction(...) 时,我总是会收到此错误。

我用谷歌搜索,发现在 php.ini 中增加 default_socket_timeout 应该可以解决它,但它不起作用。

谁能给我建议一个解决方案?

编辑:这里是代码:

$wsdl="myWSDL";

$client = new SoapClient($wsdl,array('connection_timeout'=>5,'trace'=>true,'soap_version'=>SOAP_1_2));

var_dump($client->__getFunctions());

try {
    $response=$client->myFunction("1","2","3");
         } catch (SoapFault $fault) {
    var_dump($fault);
    }
}

总是以错误结束。

我该如何解决这个问题?

【问题讨论】:

  • 嗯...ini_set('user_agent','somerandomuseragent'); 有帮助吗?您是否尝试过手动请求该服务?
  • 如果我通过 Lynx 或 curl 向 WS 发出手动请求,它运行良好;尝试设置 user_agent 但没有成功
  • 此错误消息经常出现在 default_socket_timeout 之后。你能用 ini_set 增加它的值吗?
  • @Cris 嗨 Cris,你解决了这个问题吗?我也遇到了同样的问题,我需要纠正这个问题:)
  • 这仍然可能是该错误的原因之一。为我工作。谢谢

标签: php soap-client


【解决方案1】:

当 SOAP 响应超过 default_socket_timeout 值时,通常会出现此错误。 (See this link.)

来自 SoapClient 构造函数的注意事项:connection_timeout 选项用于定义连接到服务的超时值,而不是用于其响应的超时。

你可以像这样增加它:

ini_set('default_socket_timeout', 600); // or whatever new value you want

这应该告诉您超时是否是问题,或者您是否有其他问题。请记住,您不应将此作为永久解决方案,而应先看看它是否能消除错误,然后再继续调查 SOAP 服务响应如此缓慢的原因。如果服务一直这么慢,您可能不得不考虑离线/批处理。

【讨论】:

  • 我尝试将其增加到 600 但总是得到 ["faultstring"]=> string(27) "Error Fetching http headers"
  • 好的,然后重试上面 Wrikken 的建议,除了它不是 ini_set 而是数组中的另一个选项传递给构造函数。我猜他是根据PHP #37054 提出这个建议的,你的错误可能是相似的。尝试使用 curl 和 -H "User-Agent:" 手动请求,看看响应中是否有 Location 标头。
  • 感谢您的关注;我已经按照您的建议尝试了,但没有办法;当我卷曲时,我看到 ...它有帮助吗?
  • 老实说,您是否曾允许用户坐在那里等待 600 秒 以得到响应?到目前为止,我已经找到了 3 个关于这个问题的 stackoverflow 帖子,并且人们一直在建议“增加时间限制”。答案不被接受也就不足为奇了。我还没有解决这个问题,但我怀疑这是一个与网络/套接字相关的问题,通常会导致此问题。
  • 老实说,这不是一个很好的答案 - 600 秒只是我通过添加一个额外的零得出的一个愚蠢的高数字 :-) 公平地说,我只是想作为一个试验来看看如果它阻止了错误,这意味着您可以衡量实际的响应时间。但如果这确实是问题所在,并且响应时间超过 60 秒,那么我想解决响应时间问题会更恰当!
【解决方案2】:

只是想在我的具体情况下分享这个问题的解决方案(我有相同的症状)。在我的场景中,事实证明 Web 服务提供的 ssl 证书不再受信任。事实证明,这是由于客户端安装的新防火墙干扰了 SOAP 请求,但最终结果是证书没有得到正确的服务/信任。

追踪起来有点困难,因为 SoapClient 调用(即使 trace=1)并没有提供非常有用的反馈。

我能够通过以下方式证明不受信任的证书:

openssl s_client -connect <web service host>:<port>

我知道这不会解决每个人的问题,但希望它对某人有所帮助。无论哪种方式,我认为重要的是要意识到此错误的原因(故障代码:“HTTP”故障字符串:“错误获取 http 标头”)通常是网络/套接字/协议/通信问题,而不是简单地“不允许足够请求的时间”。我无法想象扩展 default_socket_timeout 值会经常解决这个问题,即使这样,首先解决为什么它这么慢的问题肯定会更好。

【讨论】:

    【解决方案3】:

    我想为时已晚,但我也有同样的问题。我尝试了套接字超时,但它不起作用。 我的问题是客户端和服务器在同一个物理服务器中。客户端代码在同一个物理服务器中工作时,我收到此错误,但是,将相同的客户端代码移动到我的本地主机,请求服务器,(客户端和服务器在两个不同的机器中执行)一切正常。

    也许这可以帮助别人!

    【讨论】:

    • 这可能是因为主机名解析为您的公共 IP 并且路由器不知道如何正确处理它(只需将您的主机名添加到主机文件并将其指向 127.0.0.1)或因为服务器的公共端口和私有端口可能不同。
    【解决方案4】:

    我遇到了同样的问题并尝试了上述所有解决方案。遗憾的是没有任何效果。

    1. 套接字超时(无效)
    2. 用户代理(无效)
    3. SoapClient 配置,cache_wsdlKeep-Alive 等...

    我通过添加 compression 标头属性解决了我的问题。当您希望得到 gzip 压缩格式的响应时,这实际上是必需的。

    //set the Headers of Soap Client. 
    $client = new SoapClient($wsdlUrl, array(
        'trace' => true, 
        'keep_alive' => true,
        'connection_timeout' => 5000,
        'cache_wsdl' => WSDL_CACHE_NONE,
        'compression'   => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP | SOAP_COMPRESSION_DEFLATE,
    ));
    

    希望对你有帮助。

    祝你好运。

    【讨论】:

    • 太棒了!压缩参数帮助了我!
    • 'user_agent' => 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0',将使响应时间减少 100%
    【解决方案5】:

    'keep_alive' 设置为 false 对我有用:

    new SoapClient($api_url, array('keep_alive' => false));
    

    【讨论】:

      【解决方案6】:

      对我有用的配置是在我的 php 脚本中定义以下参数:

      ini_set('default_socket_timeout', 5000);
      $client = new \SoapClient($url,array(
          'trace' =>true,
          'connection_timeout' => 5000,
          'cache_wsdl' => WSDL_CACHE_NONE,
          'keep_alive' => false,
      ));
      

      请发表评论。

      根据我对这个问题的经验,最重要的参数定义是

      ini_set('default_socket_timeout', 5000);
      

      在我的测试过程中,我将 default_socket_timeout 定义为 5 秒,并且立即引发了错误“获取 http 标头错误”。

      希望对你有帮助!

      【讨论】:

        【解决方案7】:

        为了完整起见,我只是想补充一下,类似于 Manachi 我收到了这条消息,因为我使用的客户端证书需要一个密码,而我不小心在密码的末尾有一个额外的字符。这篇文章只是为要研究的内容提供另一个建议。如果主机需要使用客户端证书(通过 local_cert 参数),请确保提供正确的证书路径和正确的密码(如果需要)。如果不这样做,您很可能会看到同样的错误消息。

        【讨论】:

          【解决方案8】:

          上述技术都不适合我。

          当我分析来自 __getLastRequestHeaders 的请求标头时,我看到了以下内容:

          POST /index.php/api/index/index/?SID=012345 HTTP/1.1 Host: www.XYZ.com

          我一直使用的 API URL 不同,例如 www.ABC.com。我将 API URL 更改为 www.XYZ.com/index.php/api?wsdl,然后它就可以工作了。

          两个 URL 从同一服务器返回相同的 WSDL,但只允许一次登录。

          【讨论】:

            【解决方案9】:

            我遇到了这个问题,我检查了,就我而言,是防火墙。 PHP 没有正确显示错误。为了执行请求,防火墙回答:

            HTTP/1.1 200 OK
            Content-Type: text/html; charset=utf-8
            ...
            <html
            ...
            <h1>Direct Access IP is not allowed</h1>
            ...
            </html>
            

            SoapClient 需要 SOAP 信封,但会收到 HTML 代码。 这就是为什么 PHP 会响应:“Error Fetching Http Headers”,因为它无法理解他收到的响应。要解决此问题,请联系您的网络管理员以确认是否有任何防火墙、NAT 或代理阻碍,然后要求他们做出必要的安排。

            【讨论】:

            • 注意:在 SoapClient 布尔选项中,不知道为什么,只传递 0 和 1。示例:array ( ... 'trace' => 1, 'exceptions' => 0, .. .);
            【解决方案10】:

            请检查响应 HTTP 标头。就我而言,在 API 站点上设置了以下标头:

            <IfModule mod_headers.c>
                Header set Connection keep-alive
            </IfModule>
            

            PHP SoapClient 似乎无法处理该选项。结果,响应正文为空,但响应标头中的内容长度已正确设置。 p>

            删除该行或将其更改为“关闭”解决了我的问题。

            【讨论】:

              【解决方案11】:

              我遇到了同样的问题,并通过禁用 keep_alive 尝试了以下操作。

              $api_proxy = new SoapClient($api_url, array('trace' => true, 'keep_alive' => false));
              

              但是,这对我不起作用。对我有用的是禁用 SOAP 缓存。它似乎一直在缓存错误的请求,禁用后我实际上注意到我的请求执行得更快。

              在 linux 服务器上,您可以在 /etc/php.ini 文件中找到它。

              查找soap.wsdl_cache_enabled=1 并将其更改为soap.wsdl_cache_enabled=0

              不要忘记重新加载 apache。 service httpd reload

              【讨论】:

                【解决方案12】:

                此错误的另一个可能原因可能是某些 OpenSSL 操作留下未清除的错误。将这段代码放在 SOAP 请求之前以清除它们:

                while (openssl_error_string()) {}
                

                【讨论】:

                  【解决方案13】:

                  我遇到了同样的错误,在我的情况下,我发送请求的服务器正在回复 504 Gateway Time-out 错误。直到我在浏览器中访问 SOAP 请求所请求的 URL 时才意识到这一点:

                  例如。 https://soap-request-domain-here.com/path/to/file.wsdl

                  【讨论】:

                    【解决方案14】:

                    我们在每第二次调用SoapClient::__soapCall(,) 时遇到Error fetching http headers。然而,并不是每个soap端点/soap服务器都受到影响。

                    事实证明,切换到http 对所有服务器都可靠地工作,但通过https/secure HTTP 的连接显示了上述症状。 openssl_error_string() as suggested by Furgas 没有返回任何错误。

                    事实证明,行为不端的soap服务器在每次响应时都会发送一个HTTP标头,这会导致soap客户端在第二次soap调用时阻塞: Connection: Upgrade, close。表现良好的服务器没有在连续响应时发送Upgrade

                    什么对我们有用:

                    • keep_alive设置为false,如mentioned by Thiago
                    • 通过 .htaccess 文件取消设置 Upgrade- 和 Connection-headers

                    虽然行为良好的肥皂服务器不需要这些,但行为不端的服务器曾经需要将 keep_alive 设置为 false 并取消设置标头。

                    # .htaccess
                    Header unset Upgrade
                    Header unset Connection
                    

                    根本原因仍不清楚,但有一个bug report at Apache 与使用 HTTPS 时的升级标头有关。

                    【讨论】:

                      【解决方案15】:

                      在 Zend SOAP 客户端的最新版本中,根本没有“connection_timeout”和“Keep_alive”参数。

                      您可以看到我作为图像附加的代码。解决此问题的唯一方法是增加 php.ini 中的默认套接字超时

                      default_socket_timeout = 1000
                      

                      希望它能解决您的问题。如果可行,请点赞。

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 2011-06-17
                        • 2012-05-26
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2010-10-29
                        • 1970-01-01
                        相关资源
                        最近更新 更多