406使用Guzzle但不通过浏览器,或命令行cURL或wget

时间:2016-06-22 05:09:26

标签: php curl rss guzzle

我们有一个使用Guzzle 5的php网络应用程序来下载Wordpress RSS提要。

除了这个Feed https://www.socialquant.net/blog/feed/

之外,它的工作正常

此网站的所有者 希望我们提取Feed,并且不会故意尝试阻止访问。

我可以使用android:weekDayTextAppearance="@style/weekDayTextAppearance" android:dateTextAppearance="@style/appTextAppearance" android:unfocusedMonthDateColor="@color/colorLoginBtn" android:selectedWeekBackgroundColor="@color/colorLoginBtn" android:weekSeparatorLineColor="@color/colorLoginBtn" android:focusedMonthDateColor="@color/colorLoginBtn" android:weekNumberColor="@color/colorLoginBtn" wget从我的本地计算机和生产网络服务器(我们最初发现问题)成功下载该文件,但没有特殊选项。

这发生过一次,我们认为问题是由Apache上的mod_security引起的,并且通过添加任意User-Agent标头解决了这个问题。但是那个时候我能够在命令行上一致地重现这个问题,这次它只能通过Guzzle / PHP失败

我已将浏览器请求中的响应标头复制到问题Feed,另一个Feed正在运行。我划掉了那些相同的东西并留下了下面的

curl

这并没有提供太多的见解。 gzip内容编码跳出来了,我正在尝试使用gzip找到另一个工作源来验证这一点,但它应该无关紧要,因为Guzzle的默认模式是自动处理编码。我们使用相同的设置从使用gzip的CDN下载图像。

有人有任何想法吗?谢谢:))

修改

使用Guzzle 5.3.0

代码:

$ client = new \ GuzzleHttp \ Client();

Server:Apache/2.2.22
Vary:User-Agent
X-Powered-By:PHP/5.3.29
Content-Encoding:gzip

Server:Apache
Vary:Accept-Encoding
X-Powered-By:PHP/5.5.30

2 个答案:

答案 0 :(得分:3)

我担心我的问题没有正确的解决方案,但我让它再次运作。

tl; dr version

这是User-Agent标头,将其更改为其他任何可用的工具。

wget调用失败:

wget -d --header="User-Agent: Mozilla/4.0"  https://www.socialquant.net/blog/feed/ 

但这有效

wget -d --header="User-Agent: SomeRandomText" https://www.socialquant.net/blog/feed/

有了这个,下面的PHP现在也有效:

require 'vendor/autoload.php';

$client = new \GuzzleHttp\Client();
$feed = 'https://www.socialquant.net/blog/feed/';

try {

    $res = $client->get( 
        $feed, 
        [
            'headers' => [
                'User-Agent' => 'SomeRandomText',
            ]
        ]
    );
    echo $res->getBody();
} catch (\Exception $e) {
    echo 'Exception: ' . $e->getMessage();
} 

我的想法

我按照您的指示开始使用wgetcurl,这在没有设置特殊标题或选项时有效。在浏览器中打开它也有效。我也试过在没有User-Agent设置的情况下使用Guzzle,这也有效。

User-Agent设置为Mozilla/4.0甚至Mozilla/5.0后,它开始失败406 Not Acceptable

根据HTTP Status Code definitions,406意味着

  

请求标识的资源只能生成响应实体,这些响应实体的内容特征根据请求中发送的接受标头不可接受。

理论上,添加AcceptAccept-Encoding标题可以解决问题,但事实并非如此。不是通过Guzzle或wget

然后我找到Mozilla Developer Network definition表示:

  

当执行服务器驱动的内容协商后,Web服务器未找到符合用户代理指定条件的任何内容时,将发送此响应。

这种情况再次指向User-Agent。这让我相信你确实是正确的,mod_security做了一些奇怪的事情。我确信客户端服务器上对mod_security或Apache的更新添加了一条规则,以便以特定方式解析Mozilla/*个用户代理,因为发送User-Agent: Mozilla/4.0 ()也有效。

这就是为什么我说我没有适合您的解决方案。即使客户希望您提取Feed,他们(或他们的托管)仍然可以控制规则。

注意:我注意到我的IP在406次尝试失败后被列入黑名单,之后我不得不等待一小时才能再次访问该网站。很可能是mod_security规则。 mod_security 可能甚至可以通过您的用户代理接收自动请求并开始阻止它或使用406拒绝它。

答案 1 :(得分:0)

我也没有为您提供解决方案,因为我也遇到了同样的问题(除了我得到错误503并且它在60%的时间内失败)。如果您找到了解决方案,请告诉我。

但是,我想与您分享我最近的研究中发现的内容。我发现某些用户代理对我来说比其他用户代理更好。这让我相信Donovan并不是这样说的(至少对我而言)。

当我将User-Agent设置为null时,它会100%的时间工作。但是,我还没有提出任何大的请求,因为我害怕被禁止IP,因为我知道我会提出一个大请求。

当我对请求本身执行var_dump时,我看到很多包含Guzzle标记的数组。我在想,也许亚马逊检测服务可以说我欺骗了标题?我不知道。

希望你明白这一点。