PHP - `get_headers`为有效的URL返回“400 Bad Request”和“403 Forbidden”?

时间:2016-08-24 02:23:30

标签: php get-headers

说明底部的工作解决方案!

我正在运行PHP 5.4,并试图获取URL列表的标题。

在大多数情况下,一切正常,但有三个网址导致问题(可能更多,更广泛的测试)。

'http://www.alealimay.com'
'http://www.thelovelist.net'
'http://www.bleedingcool.com'

所有三个网站在浏览器中都能正常运行,并产生以下标题响应:

(来自Safari)

successful headers

请注意,所有三个标头响应均为Code = 200

但是使用get_headers ...

通过PHP检索标头
stream_context_set_default(array('http' => array('method' => "HEAD")));
$headers = get_headers($url, 1);
stream_context_set_default(array('http' => array('method' => "GET")));

...返回以下内容:

url  ......  "http://www.alealimay.com"

headers
|    0  ............................  "HTTP/1.0 400 Bad Request"
|    content-length  ...............  "378"
|    X-Synthetic  ..................  "true"
|    expires  ......................  "Thu, 01 Jan 1970 00:00:00 UTC"
|    pragma  .......................  "no-cache"
|    cache-control  ................  "no-cache, must-revalidate"
|    content-type  .................  "text/html; charset=UTF-8"
|    connection  ...................  "close"
|    date  .........................  "Wed, 24 Aug 2016 01:26:21 UTC"
|    X-ContextId  ..................  "QIFB0I8V/xsTFMREg"
|    X-Via  ........................  "1.0 echo109"



url  ......  "http://www.thelovelist.net"

headers
|    0  ............................  "HTTP/1.0 400 Bad Request"
|    content-length  ...............  "378"
|    X-Synthetic  ..................  "true"
|    expires  ......................  "Thu, 01 Jan 1970 00:00:00 UTC"
|    pragma  .......................  "no-cache"
|    cache-control  ................  "no-cache, must-revalidate"
|    content-type  .................  "text/html; charset=UTF-8"
|    connection  ...................  "close"
|    date  .........................  "Wed, 24 Aug 2016 01:26:22 UTC"
|    X-ContextId  ..................  "aNKvf2RB/bIMjWyjW"
|    X-Via  ........................  "1.0 echo103"



url  ......  "http://www.bleedingcool.com"

headers
|    0  ............................  "HTTP/1.1 403 Forbidden"
|    Server  .......................  "Sucuri/Cloudproxy"
|    Date  .........................  "Wed, 24 Aug 2016 01:26:22 GMT"
|    Content-Type  .................  "text/html"
|    Content-Length  ...............  "5311"
|    Connection  ...................  "close"
|    Vary  .........................  "Accept-Encoding"
|    ETag  .........................  "\"57b7f28e-14bf\""
|    X-XSS-Protection  .............  "1; mode=block"
|    X-Frame-Options  ..............  "SAMEORIGIN"
|    X-Content-Type-Options  .......  "nosniff"
|    X-Sucuri-ID  ..................  "11005"

无论是否更改stream_context

,都是如此
//stream_context_set_default(array('http' => array('method' => "HEAD")));
$headers = get_headers($url, 1);
//stream_context_set_default(array('http' => array('method' => "GET")));

产生相同的结果。

没有任何警告或错误被抛出(通常使用@get_headers抑制错误,但两种方式都没有区别。)

我已检查了我的php.ini,并将allow_url_fopen设置为On

我前往stream_get_meta_data,对CURL解决方案不感兴趣。 stream_get_meta_data(及其随附的fopen)会在与get_headers相同的位置失败,因此在这种情况下修复一个将会解决问题。

通常,如果存在重定向,则输出如下:

url  ......  "http://www.startingURL.com/"

headers
|    0  ............................  "HTTP/1.1 301 Moved Permanently"
|    1  ............................  "HTTP/1.1 200 OK"
|    Date
|    |    "Wed, 24 Aug 2016 02:02:29 GMT"
|    |    "Wed, 24 Aug 2016 02:02:32 GMT"
|    
|    Server
|    |    "Apache"
|    |    "Apache"
|    
|    Location  .....................  "http://finishingURL.com/"
|    Connection
|    |    "close"
|    |    "close"
|    
|    Content-Type
|    |    "text/html; charset=UTF-8"
|    |    "text/html; charset=UTF-8"
|    
|    Link  .........................  "; rel=\"https://api.w.org/\", ; rel=shortlink"

网站如何在浏览器中运行,但在使用get_headers时失败?

有各种SO帖子讨论相同的事情,但所有这些的解决方案都不属于这种情况:

POST requires Content-Length(我正在发送HEAD请求,不会返回任何内容)

URL contains UTF-8 data(这些网址中的唯一字符全部来自拉丁字母)

Cannot send a URL with spaces in it(这些网址都是无空间的,并且在各方面都很普通)

的解决方案!

(感谢Max在下面的答案中指出我在正确的轨道上。)

问题是因为没有预定义的user_agent,没有在php.ini中设置,或在代码中声明它。

因此,我更改user_agent以模仿浏览器,执行操作,然后将其还原为说明值(可能为空白)。

$OriginalUserAgent = ini_get('user_agent');
ini_set('user_agent', 'Mozilla/5.0');

$headers = @get_headers($url, 1);

ini_set('user_agent', $OriginalUserAgent);

找到用户代理更改here

1 个答案:

答案 0 :(得分:6)

之所以发生这种情况,是因为所有这三个站点都在检查请求和响应的UserAgent标头,如果无法匹配则会出现错误。 get_headers函数不发送此标头。您可以尝试使用cURL和此代码段来获取网站内容:

$url = 'http://www.alealimay.com';
$c = curl_init($url);
curl_setopt($c, CURLOPT_USERAGENT, 'curl/7.48.0');
curl_exec($c);
var_dump(curl_getinfo($c));

<强> UPD: 没有必要使用cURL来设置用户代理标头。它也可以使用ini_set('user_agent', 'Mozilla/5.0');完成,然后get_headers函数将使用配置的值。