PHP : HTTP 응답 코드를 보내는 방법?


답변:


461

방금이 질문을 발견하고 더 포괄적 인 답변이 필요하다고 생각했습니다.

현재 PHP 5.4 이 작업을 수행하는 세 가지 방법이 있습니다 :

자체적으로 응답 코드 조립 (PHP> = 4.0)

header()함수에는 HTTP 응답 라인을 감지하고이를 사용자 정의 라인으로 대체 할 수있는 특수 사용 사례가 있습니다.

header("HTTP/1.1 200 OK");

그러나 (Fast) CGI PHP는 특별한 처리가 필요합니다 :

$sapi_type = php_sapi_name();
if (substr($sapi_type, 0, 3) == 'cgi')
    header("Status: 404 Not Found");
else
    header("HTTP/1.1 404 Not Found");

참고 : 에 따르면 HTTP RFC는이유 문구는 하지만, 클라이언트 호환성을 위해 내가 (표준을 준수 함) 사용자 정의 문자열이 될 수 없는 이 임의의 문자열을 두는 것을 권장합니다.

참고 : PHP 4.0.1php_sapi_name() 필요

헤더 함수에 대한 세 번째 인수 (PHP> = 4.3)

첫 번째 변형을 사용할 때 분명히 몇 가지 문제가 있습니다. 내가 생각하는 것 중 가장 큰 것은 PHP 또는 웹 서버에 의해 부분적으로 구문 분석되고 문서화가 잘못되었다는 것입니다.

4.3 이후로 header함수에는 응답 코드를 다소 편하게 설정할 수있는 세 번째 인수가 있지만이를 사용하려면 첫 번째 인수가 비어 있지 않은 문자열이어야합니다. 두 가지 옵션이 있습니다.

header(':', true, 404);
header('X-PHP-Response-Code: 404', true, 404);

나는 두 번째를 추천합니다 . 첫 번째 테스트 한 모든 브라우저에서 작동하지만 일부 마이너 브라우저 또는 웹 크롤러에는 콜론 만 포함 된 헤더 행에 문제가있을 수 있습니다. 두 번째의 헤더 필드 이름입니다. 변형은 물론 어떤 방식으로도 표준화되지 않았으며 수정 될 수 있습니다.

http_response_code 함수 (PHP> = 5.4)

http_response_code()기능은 PHP 5.4에서 도입되었으며 훨씬 쉬워졌습니다.

http_response_code(404);

그게 다야.

적합성

다음은 5.4 이하의 호환성이 필요하지만 "새로운" http_response_code기능 의 기능을 원할 때 요리 한 기능입니다. PHP 4.3은 이전 버전과의 호환성이 충분하다고 생각하지만 결코 알지 못합니다 ...

// For 4.3.0 <= PHP <= 5.4.0
if (!function_exists('http_response_code'))
{
    function http_response_code($newcode = NULL)
    {
        static $code = 200;
        if($newcode !== NULL)
        {
            header('X-PHP-Response-Code: '.$newcode, true, $newcode);
            if(!headers_sent())
                $code = $newcode;
        }       
        return $code;
    }
}

10
PHP-FPM (FastCGI) header('X-PHP-Response-Code: 404', true, 404);에서 제대로 작동 하는지 확인할 수 있습니다.
Josh

@dualed (1)은 headers_sent()전화 한 직후에 항상 옳은 것은 아닙니다 header(). (2) 5.4 세계에서 http_response_text ()와 같은 것을 찾은 적이 있습니까? 적어도 이전 header ()는 상태 코드 뒤의 텍스트에 영향을 줄 수 있습니다.
Bob Stein

@ BobStein-VisiBone (1) headers_sent() 은 헤더를 추가 한 경우가 아니라 컨텐트가 이미 전송되어 더 이상 헤더를 추가 할 수없는 경우에 해당됩니다. (2) 죄송합니다. 다른 언어 불구하고 더 나은 지원이
dualed

1
@ Peerry 내가 이것을 제안하지 않는 이유는 콜론 전용을 제안하지 않는 이유와 같습니다. PHP는 이러한 "헤더"에서 발생하는 일이 정의되지 않았거나, 헤더 또는 상태를 설정하지 않거나, 잘못된 헤더를 추가 할 수 있습니다 (http 1.1 프로토콜 표준 에 콜론이 필요함) . )
dualed

8
나는 http_response_code당신이 echo무언가 후에 더 이상 작동하지 않는다는 것을 깨닫는 데 시간을 보냈습니다 . 도움이 되길 바랍니다.
Neptilo

40

불행히도 @dualed가 제시 한 솔루션에는 다양한 결함이 있음을 발견했습니다.

  1. substr($sapi_type, 0, 3) == 'cgi'빠른 CGI를 탐지하는 데는 전혀 사용 되지 않습니다. PHP-FPM FastCGI Process Manager를 사용할 때 php_sapi_name()cpm이 아닌 fpm을 반환합니다

  2. Fasctcgi와 php-fpm은 @Josh가 언급 한 또 다른 버그를 노출시킵니다. header('X-PHP-Response-Code: 404', true, 404);-PHP-FPM (FastCGI)에서 사용 이 제대로 작동합니다

  3. header("HTTP/1.1 404 Not Found");프로토콜이 HTTP / 1.1이 아닌 경우 (예 : 'HTTP / 1.0') 실패 할 수 있습니다. 현재 프로토콜은 $_SERVER['SERVER_PROTOCOL'](PHP 4.1.0부터 사용 가능)

  4. 호출 http_response_code()결과에 예기치 않은 동작이 발생하는 경우가 2 가지 이상 있습니다.

    • PHP가 HTTP 응답 코드를 발견 할 때 이해하지 못하는 경우, PHP는 해당 코드를 동일한 그룹에서 알고있는 코드로 대체합니다. 예를 들어 "521 웹 서버가 다운되었습니다"는 "500 내부 서버 오류"로 바뀝니다. 다른 그룹 2xx, 3xx, 4xx의 다른 많은 일반적이지 않은 응답 코드가이 방식으로 처리됩니다.
    • php-fpm 및 nginx http_response_code () 함수가있는 서버에서 코드를 예상대로 변경할 수 있지만 메시지는 변경할 수 없습니다. 예를 들어 이상한 "404 OK"헤더가 나타날 수 있습니다. 이 문제는 또한 PHP 웹 사이트에서 사용자 의견 http://www.php.net/manual/en/function.http-response-code.php#112423에 의해 언급되었습니다 .

참고로 여기에는 HTTP 응답 상태 코드의 전체 목록이 있습니다 (이 목록에는 IETF 인터넷 표준 및 기타 IETF RFC의 코드가 포함되어 있습니다. 이들 중 대부분은 현재 PHP http_response_code 함수에서 지원되지 않습니다) : http : //en.wikipedia .org / wiki / List_of_HTTP_status_codes

다음을 호출하여이 버그를 쉽게 테스트 할 수 있습니다.

http_response_code(521);

서버가 "500 Internal Server Error"HTTP 응답 코드를 보내 서버를 호출하는 사용자 지정 클라이언트 응용 프로그램이 있고 추가 HTTP 코드가 필요한 경우 예기치 않은 오류가 발생합니다.


내 솔루션 (4.1.0 이후의 모든 PHP 버전) :

$httpStatusCode = 521;
$httpStatusMsg  = 'Web server is down';
$phpSapiName    = substr(php_sapi_name(), 0, 3);
if ($phpSapiName == 'cgi' || $phpSapiName == 'fpm') {
    header('Status: '.$httpStatusCode.' '.$httpStatusMsg);
} else {
    $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
    header($protocol.' '.$httpStatusCode.' '.$httpStatusMsg);
}

결론

http_response_code () 구현은 모든 HTTP 응답 코드를 지원하지 않으며 지정된 HTTP 응답 코드를 동일한 그룹의 다른 코드로 덮어 쓸 수 있습니다.

새로운 http_response_code () 함수는 관련된 모든 문제를 해결하지는 못하지만 새로운 버그가 발생하는 것을 최악으로 만듭니다.

@dualed가 제공하는 "호환성"솔루션은 적어도 PHP-FPM에서 예상대로 작동하지 않습니다.

@dualed가 제공하는 다른 솔루션에도 다양한 버그가 있습니다. 빠른 CGI 탐지는 PHP-FPM을 처리하지 않습니다. 현재 프로토콜이 감지되어야합니다.

모든 테스트와 의견을 부탁드립니다.


21

PHP 5.4부터 http_response_code()헤더 상태 코드를 가져오고 설정할 수 있습니다 .

여기 예가 있습니다 :

<?php

// Get the current response code and set a new one
var_dump(http_response_code(404));

// Get the new response code
var_dump(http_response_code());
?>

다음은 php.net에서이 함수의 문서입니다 :

http_response_code


내 경험상 이것이 가장 좋은 대답입니다.
Scruuffy

왜 var_dump ()를 사용합니까?
Tomas Gonzalez

그러나 echo 대신 var_dump ()를 사용하는 이유는 무엇입니까? 결과가 간단한 에코에 적합하지 않을 수 있습니까? 또는 심지어 print_r (). var_dump ()는 프로덕션 코드에 적합하지 않은 것 같습니다 ...
Tomas Gonzalez

그것은 큰 문제가되지 않습니다 @TomasGonzalez, 난 그냥 U 위해서 var_dump와 인쇄 모두에 의해 그 안에 무엇이 보여주고 싶었다 ()와 UR 권리는 중요하지 r에
세예드 알리의 Roshan

알 겠어. 내가 주목 한 것은 공식 문서에서 예제는 var_dump ()도 사용한다는 것입니다. 그래서 그렇게하는 이유가 궁금했습니다. 내가 놓친 것이있을 수 있습니다. php.net/manual/en/function.http-response-code.php
Tomas Gonzalez

10

출력 버퍼링을 사용하지 않는 경우 본문의 출력 전에이 행을 추가하십시오.

header("HTTP/1.1 200 OK");

메시지 부분 ( 'OK')을 적절한 메시지로 바꾸고 상태 코드를 적절한 코드 (404, 501 등)로 바꿉니다.


2
우리가 넣은 메시지 (OK를 원격으로 바꾸는 것)는 무엇 일 수 있는가?
FMaz008

이것은 나를 위해 일했습니다. PHP 5.3을 사용하는 웹 사이트에서 문의 양식을 작성하고있었습니다. 그리고이 솔루션은 저에게 효과적이었습니다. 응답 텍스트와 AJAX 요청 완료 실패 기능에 대한이 HTTP 코드를 제공합니다. 그게 내가 원하는 전부 야
Surjith SM

7

환경을로드 할 때 Wordpress가 404를 제공하여 여기에 있다면 문제를 해결해야합니다.

define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
status_header( 200 );
//$wp_query->is_404=false; // if necessary

문제는 Status : 404 Not Found 헤더를 전송했기 때문입니다. 당신은 그것을 무시해야합니다. 이것은 또한 작동합니다 :

define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
header("HTTP/1.1 200 OK");
header("Status: 200 All rosy");

헤더 ( "HTTP / 1.1 200 OK"); http_response_code (201); header ( "상태 : 200 모든 장미 빛"); // 일
alpc



2

PHP 버전에이 기능이 포함되어 있지 않은 경우 :

<?php

function http_response_code($code = NULL) {
        if ($code !== NULL) {
            switch ($code) {
                case 100: $text = 'Continue';
                    break;
                case 101: $text = 'Switching Protocols';
                    break;
                case 200: $text = 'OK';
                    break;
                case 201: $text = 'Created';
                    break;
                case 202: $text = 'Accepted';
                    break;
                case 203: $text = 'Non-Authoritative Information';
                    break;
                case 204: $text = 'No Content';
                    break;
                case 205: $text = 'Reset Content';
                    break;
                case 206: $text = 'Partial Content';
                    break;
                case 300: $text = 'Multiple Choices';
                    break;
                case 301: $text = 'Moved Permanently';
                    break;
                case 302: $text = 'Moved Temporarily';
                    break;
                case 303: $text = 'See Other';
                    break;
                case 304: $text = 'Not Modified';
                    break;
                case 305: $text = 'Use Proxy';
                    break;
                case 400: $text = 'Bad Request';
                    break;
                case 401: $text = 'Unauthorized';
                    break;
                case 402: $text = 'Payment Required';
                    break;
                case 403: $text = 'Forbidden';
                    break;
                case 404: $text = 'Not Found';
                    break;
                case 405: $text = 'Method Not Allowed';
                    break;
                case 406: $text = 'Not Acceptable';
                    break;
                case 407: $text = 'Proxy Authentication Required';
                    break;
                case 408: $text = 'Request Time-out';
                    break;
                case 409: $text = 'Conflict';
                    break;
                case 410: $text = 'Gone';
                    break;
                case 411: $text = 'Length Required';
                    break;
                case 412: $text = 'Precondition Failed';
                    break;
                case 413: $text = 'Request Entity Too Large';
                    break;
                case 414: $text = 'Request-URI Too Large';
                    break;
                case 415: $text = 'Unsupported Media Type';
                    break;
                case 500: $text = 'Internal Server Error';
                    break;
                case 501: $text = 'Not Implemented';
                    break;
                case 502: $text = 'Bad Gateway';
                    break;
                case 503: $text = 'Service Unavailable';
                    break;
                case 504: $text = 'Gateway Time-out';
                    break;
                case 505: $text = 'HTTP Version not supported';
                    break;
                default:
                    exit('Unknown http status code "' . htmlentities($code) . '"');
                    break;
            }
            $protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
            header($protocol . ' ' . $code . ' ' . $text);
            $GLOBALS['http_response_code'] = $code;
        } else {
            $code = (isset($GLOBALS['http_response_code']) ? $GLOBALS['http_response_code'] : 200);
        }
        return $code;
    }

1

두 가지 환경을 통해 http_response_code에서 다른 반환 값을 얻을 수 있습니다.

  1. 웹 서버 환경
  2. CLI 환경

웹 서버 환경에서 응답 코드를 제공했거나 응답 코드를 제공하지 않으면 이전 값을 반환하여 현재 값을 인쇄합니다. 기본값은 200 (확인)입니다.

CLI 환경에서 응답 코드를 제공하면 true가 반환되고 response_code를 제공하지 않으면 false가 반환됩니다.

Response_code의 리턴 값 웹 서버 환경 예제 :

var_dump(http_respone_code(500)); // int(200)
var_dump(http_response_code()); // int(500)

Response_code의 리턴 값 CLI 환경 예 :

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