PHP에서 404의 URL을 테스트하는 쉬운 방법은 무엇입니까?


152

나는 몇 가지 기본적인 긁기를 가르치고 있으며 때로는 코드에 공급하는 URL이 404를 반환한다는 것을 알았습니다. 이는 나머지 모든 코드를 요약합니다.

따라서 코드 상단에 URL이 404를 반환하는지 확인하는 테스트가 필요합니다.

이것은 간단한 작업처럼 보이지만 Google은 대답을하지 않습니다. 잘못된 것을 찾는 것이 걱정입니다.

한 블로그에서 이것을 사용하도록 권장했습니다.

$valid = @fsockopen($url, 80, $errno, $errstr, 30);

비어 있는지 아닌지 $ valid인지 확인하십시오.

그러나 문제를 일으키는 URL에 리디렉션이 있다고 생각하므로 모든 값에 대해 $ valid가 비어 있습니다. 아니면 다른 일을하고있을 수도 있습니다.

또한 "헤드 요청"을 살펴 보았지만 아직 플레이하거나 시도 할 수있는 실제 코드 예제를 아직 찾지 못했습니다.

제안? 그리고 컬에 관한 이것은 무엇입니까?

답변:


276

PHP의 curl바인딩을 사용하는 경우 다음을 사용 하여 오류 코드를 확인할 수 있습니다 curl_getinfo.

$handle = curl_init($url);
curl_setopt($handle,  CURLOPT_RETURNTRANSFER, TRUE);

/* Get the HTML or whatever is linked in $url. */
$response = curl_exec($handle);

/* Check for 404 (file not found). */
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
    /* Handle 404 here. */
}

curl_close($handle);

/* Handle $response here. */

1
cURL에 대해서는 아직 잘 모르므로 몇 가지 개념이 누락되었습니다. 아래의 $ response 변수로 무엇을해야합니까? 무엇이 포함되어 있습니까?

1
@ bflora, 나는 코드에서 실수를했다. (몇 초 후에 수정 될 것입니다.) PHP 사이트에서 curl_exec에 대한 문서를 볼 수 있습니다.
strager

4
@bflora $ response는 $ url의 내용을 포함하므로 특정 문자열의 내용 확인 등의 추가 작업을 수행 할 수 있습니다. 귀하의 경우, 당신은 404 상태에 관심이 있으므로 아마도 $ response에 대해 걱정할 필요가 없습니다.
Beau Simensen

5
전체 파일을 다운로드하는 대신로드 할 헤더를 원한다면 어떻게합니까?
patrick

13
@patrick 다음 curl_setopt($handle, CURLOPT_NOBODY, true);실행하기 전에 지정 해야합니다curl_exec
사용자

101

실행중인 php5 인 경우 다음을 사용할 수 있습니다.

$url = 'http://www.example.com';
print_r(get_headers($url, 1));

php4를 사용하는 사용자는 다음을 기여했습니다.

/**
This is a modified version of code from "stuart at sixletterwords dot com", at 14-Sep-2005 04:52. This version tries to emulate get_headers() function at PHP4. I think it works fairly well, and is simple. It is not the best emulation available, but it works.

Features:
- supports (and requires) full URLs.
- supports changing of default port in URL.
- stops downloading from socket as soon as end-of-headers is detected.

Limitations:
- only gets the root URL (see line with "GET / HTTP/1.1").
- don't support HTTPS (nor the default HTTPS port).
*/

if(!function_exists('get_headers'))
{
    function get_headers($url,$format=0)
    {
        $url=parse_url($url);
        $end = "\r\n\r\n";
        $fp = fsockopen($url['host'], (empty($url['port'])?80:$url['port']), $errno, $errstr, 30);
        if ($fp)
        {
            $out  = "GET / HTTP/1.1\r\n";
            $out .= "Host: ".$url['host']."\r\n";
            $out .= "Connection: Close\r\n\r\n";
            $var  = '';
            fwrite($fp, $out);
            while (!feof($fp))
            {
                $var.=fgets($fp, 1280);
                if(strpos($var,$end))
                    break;
            }
            fclose($fp);

            $var=preg_replace("/\r\n\r\n.*\$/",'',$var);
            $var=explode("\r\n",$var);
            if($format)
            {
                foreach($var as $i)
                {
                    if(preg_match('/^([a-zA-Z -]+): +(.*)$/',$i,$parts))
                        $v[$parts[1]]=$parts[2];
                }
                return $v;
            }
            else
                return $var;
        }
    }
}

둘 다 다음과 유사한 결과를 갖습니다.

Array
(
    [0] => HTTP/1.1 200 OK
    [Date] => Sat, 29 May 2004 12:28:14 GMT
    [Server] => Apache/1.3.27 (Unix)  (Red-Hat/Linux)
    [Last-Modified] => Wed, 08 Jan 2003 23:11:55 GMT
    [ETag] => "3f80f-1b6-3e1cb03b"
    [Accept-Ranges] => bytes
    [Content-Length] => 438
    [Connection] => close
    [Content-Type] => text/html
)

따라서 헤더 응답이 정상인지 확인하십시오.

$headers = get_headers($url, 1);
if ($headers[0] == 'HTTP/1.1 200 OK') {
//valid 
}

if ($headers[0] == 'HTTP/1.1 301 Moved Permanently') {
//moved or redirect page
}

W3C 코드 및 정의


나는 당신의 대답을 몇 가지 형식으로 개선했으며 https 기능도 추가 get_headers($https_url,1,443);했습니다. 표준 get_headers()기능 이 아니더라도 작동 할 것이라고 확신합니다 . 자유롭게 테스트하고 상태에 따라 응답하십시오.
JamesM-SiteGen

1
php4에 대한 좋은 해결 방법이지만 이와 같은 경우 HEAD http 메서드가 있습니다.
vidstige

그래서 이것은 실제로 컬 방법보다 빠릅니다.
FLY

4
이 솔루션은 대상 URL이 404로 리디렉션 될 때 유효하지 않습니다.이 경우 $ headers [0]은 리디렉션 코드가되고 마지막 404 코드는 나중에 배열을 반환하는 곳에 추가됩니다.
roomcays

1
결과적으로 읽은 결과를 반향하는 대신 스크립트에서 상태 코드를 단순히 처리하려고 할 때 결과 문자열에서 실제 코드를 필터링하는 것이 PHP보다 가치가 있습니다.
Kzqai 2016 년

37

스 트래 거 코드를 사용하면 CURLINFO_HTTP_CODE에서 다른 코드를 확인할 수도 있습니다. 일부 웹 사이트는 404를보고하지 않고 단순히 사용자 지정 404 페이지로 리디렉션하고 302 (리디렉션) 또는 이와 유사한 것을 반환합니다. 실제 파일 (예 : robots.txt)이 서버에 존재하는지 여부를 확인하는 데 사용했습니다. 분명히 이런 종류의 파일은 존재하는 경우 리디렉션을 유발하지 않지만, 그렇지 않은 경우 이전에 404 코드가 없을 수있는 404 페이지로 리디렉션됩니다.

function is_404($url) {
    $handle = curl_init($url);
    curl_setopt($handle,  CURLOPT_RETURNTRANSFER, TRUE);

    /* Get the HTML or whatever is linked in $url. */
    $response = curl_exec($handle);

    /* Check for 404 (file not found). */
    $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
    curl_close($handle);

    /* If the document has loaded successfully without any redirection or error */
    if ($httpCode >= 200 && $httpCode < 300) {
        return false;
    } else {
        return true;
    }
}

5
"성공"의 사용 HTTP 코드 대신 404 일 ... 사용자는 얻을 수 있습니다 408 Request Timeout아닌404
기욤

일하는 리카의 매력. 이베이의 기사가 아직 온라인 상태인지 확인하는 데 사용합니다.
Nerdkowski

위의 코드가 https와 함께 작동 할 것으로 예상되는 사람들을 위해 다음을 추가하십시오.curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, FALSE);
Kirk Hammett

그러나 합법적 인 302 리디렉션이 있으면 404 = true를 반환합니까?
Robert Sinclair

22

strager가 제안했듯이 cURL을 사용하십시오. curl_setopt 를 사용하여 CURLOPT_NOBODY를 설정 하여 전체 페이지 다운로드를 건너 뛸 수도 있습니다 (헤더 만 원함).


1
헤더 만 확인해야하는 경우보다 효율적인 대안을 제공합니다. =]
strager

16

가장 쉬운 해결책을 찾고 있다면 php5에서 한 번에 시도 할 수 있습니다.

file_get_contents('www.yoursite.com');
//and check by echoing
echo $http_response_header[0];

3
btw,이 작업과 URL 404를 수행하면 경고가 발생하여 출력이 발생합니다.
Chris K

보다 쉬운 작업 $ isExists = @file_get_contents ( 'www.yoursite.com'); if ($ isExists! == true) {echo "404 수율"}
Tebe

시험해 보시고 404를 잡으십시오
Garet Claborn

7

나는이 대답을 여기 에서 발견 했다 .

if(($twitter_XML_raw=file_get_contents($timeline))==false){
    // Retrieve HTTP status code
    list($version,$status_code,$msg) = explode(' ',$http_response_header[0], 3);

    // Check the HTTP Status code
    switch($status_code) {
        case 200:
                $error_status="200: Success";
                break;
        case 401:
                $error_status="401: Login failure.  Try logging out and back in.  Password are ONLY used when posting.";
                break;
        case 400:
                $error_status="400: Invalid request.  You may have exceeded your rate limit.";
                break;
        case 404:
                $error_status="404: Not found.  This shouldn't happen.  Please let me know what happened using the feedback link above.";
                break;
        case 500:
                $error_status="500: Twitter servers replied with an error. Hopefully they'll be OK soon!";
                break;
        case 502:
                $error_status="502: Twitter servers may be down or being upgraded. Hopefully they'll be OK soon!";
                break;
        case 503:
                $error_status="503: Twitter service unavailable. Hopefully they'll be OK soon!";
                break;
        default:
                $error_status="Undocumented error: " . $status_code;
                break;
    }

기본적으로 "file get contents"메소드를 사용하여 URL을 검색하면 http 응답 헤더 변수가 상태 코드로 자동 채워집니다.


2
흥미 롭습니다. 전 그 마법에 대해 들어 본 적이 없습니다. php.net/manual/en/reserved.variables.httpresponseheader.php
Frank Farmer

2
아이러니 - 링크는 404
함자 말리크

6

URL이 200을 반환하지 않으면 true가됩니다.

function check_404($url) {
   $headers=get_headers($url, 1);
   if ($headers[0]!='HTTP/1.1 200 OK') return true; else return false;
}

URL에서 간단한 bool check를 수행하려는 경우 cURL을 사용하는 것보다 훨씬 빠릅니다. 감사합니다.
Drmzindec

5

부록; 성능을 고려한 3 가지 방법을 테스트했습니다.

적어도 내 테스트 환경에서 결과는 다음과 같습니다.

컬 승리

이 테스트는 헤더 (noBody) 만 필요하다는 것을 고려하여 수행됩니다. 자신을 테스트하십시오 :

$url = "http://de.wikipedia.org/wiki/Pinocchio";

$start_time = microtime(TRUE);
$headers = get_headers($url);
echo $headers[0]."<br>";
$end_time = microtime(TRUE);
echo $end_time - $start_time."<br>";


$start_time = microtime(TRUE);
$response = file_get_contents($url);
echo $http_response_header[0]."<br>";
$end_time = microtime(TRUE);
echo $end_time - $start_time."<br>";

$start_time = microtime(TRUE);
$handle = curl_init($url);
curl_setopt($handle,  CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($handle, CURLOPT_NOBODY, 1); // and *only* get the header 
/* Get the HTML or whatever is linked in $url. */
$response = curl_exec($handle);
/* Check for 404 (file not found). */
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
// if($httpCode == 404) {
    // /* Handle 404 here. */
// }
echo $httpCode."<br>";
curl_close($handle);
$end_time = microtime(TRUE);
echo $end_time - $start_time."<br>";

3

큰 대답에 대한 추가 힌트로 :

제안 된 솔루션의 변형을 사용할 때 PHP 설정 'max_execution_time'으로 인해 오류가 발생했습니다. 그래서 내가 한 일은 다음과 같습니다.

set_time_limit(120);
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_NOBODY, true);
$result = curl_exec($curl);
set_time_limit(ini_get('max_execution_time'));
curl_close($curl);

먼저 시간 제한을 더 높은 초 수로 설정하고 결국 PHP 설정에 정의 된 값으로 다시 설정했습니다.


hhhmmmm ... 게다가 ... 코드는 적은 리소스를 소비하여 콘텐츠를 반환하지 않습니다 ... 거부로 전송을 false로 추가하면 사람들이 여러 호출을 사용할 때 많은 리소스를 절약 할 수 있습니다 ... 초보자는 많이 생각하지 않습니다 그리고 그것은 40 위로 투표의 이유 ... 괜찮아 ...
Jayapal Chandran

3
<?php

$url= 'www.something.com';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, true);   
curl_setopt($ch, CURLOPT_NOBODY, true);    
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.4");
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
curl_setopt($ch, CURLOPT_ENCODING, "gzip");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$output = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);


echo $httpcode;
?>

3

여기 짧은 해결책이 있습니다.

$handle = curl_init($uri);
curl_setopt($handle,  CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($handle,CURLOPT_HTTPHEADER,array ("Accept: application/rdf+xml"));
curl_setopt($handle, CURLOPT_NOBODY, true);
curl_exec($handle);
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
if($httpCode == 200||$httpCode == 303) 
{
    echo "you might get a reply";
}
curl_close($handle);

귀하의 경우, application/rdf+xml사용하는 것으로 변경할 수 있습니다.


2

이 함수는 PHP 7에서 URL의 상태 코드를 반환합니다.

/**
 * @param string $url
 * @return int
 */
function getHttpResponseCode(string $url): int
{
    $headers = get_headers($url);
    return substr($headers[0], 9, 3);
}

예:

echo getHttpResponseCode('https://www.google.com');
//displays: 200

1

이 코드를 사용하여 링크 상태를 확인할 수 있습니다.

<?php

function get_url_status($url, $timeout = 10) 
{
$ch = curl_init();
// set cURL options
$opts = array(CURLOPT_RETURNTRANSFER => true, // do not output to browser
            CURLOPT_URL => $url,            // set URL
            CURLOPT_NOBODY => true,         // do a HEAD request only
            CURLOPT_TIMEOUT => $timeout);   // set timeout
curl_setopt_array($ch, $opts);
curl_exec($ch); // do it!
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE); // find HTTP status
curl_close($ch); // close handle
echo $status; //or return $status;
    //example checking
    if ($status == '302') { echo 'HEY, redirection';}
}

get_url_status('http://yourpage.comm');
?>

0

이것은 단지 코드 조각이며 희망은 당신을 위해 작동합니다.

            $ch = @curl_init();
            @curl_setopt($ch, CURLOPT_URL, 'http://example.com');
            @curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1");
            @curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
            @curl_setopt($ch, CURLOPT_TIMEOUT, 10);

            $response       = @curl_exec($ch);
            $errno          = @curl_errno($ch);
            $error          = @curl_error($ch);

                    $response = $response;
                    $info = @curl_getinfo($ch);
return $info['http_code'];

0

방법이 있습니다!

<?php

$url = "http://www.google.com";

if(@file_get_contents($url)){
echo "Url Exists!";
} else {
echo "Url Doesn't Exist!";
}

?>

이 간단한 스크립트는 단순히 소스 코드의 URL을 요청합니다. 요청이 성공적으로 완료되면 "URL Exists!"가 출력됩니다. 그렇지 않으면 "URL이 없습니다!"가 출력됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.