Source for file http_response_header.php

Documentation is available at http_response_header.php

  1. <?php
  2. /**
  3.  * HTTP Response Header Class
  4.  *
  5.  * HTTP Response Header ClassはHTTP Responseをコントロールするクラスです。
  6.  *
  7.  * @package http_response_header
  8.  * @access public
  9.  * @author http://purl.org/meta/me/
  10.  * @version http_response_header.php 1.0 2011-08-20
  11.  * @license Creative Commons License CC BY (http://creativecommons.org/licenses/by/3.0/)
  12.  */
  13.  
  14.     /**
  15.      * HTTP Status Codeの一覧。(ja)
  16.      *
  17.      * List of HTTP Status Code.(en)
  18.      *
  19.      * @var array 
  20.      * @access public
  21.      */
  22.     static $httpStatusCodes array(
  23.         100 => 'Continue',
  24.         101 => 'Switching Protocols',
  25.         200 => 'OK',
  26.         201 => 'Created',
  27.         202 => 'Accepted',
  28.         203 => 'Non-Authoritative Information',
  29.         204 => 'No Content',
  30.         205 => 'Reset Content',
  31.         206 => 'Partial Content',
  32.         226 => 'IM Used',
  33.         300 => 'Multiple Choices',
  34.         301 => 'Moved Permanently',
  35.         302 => 'Found',
  36.         303 => 'See Other',
  37.         304 => 'Not Modified',
  38.         305 => 'Use Proxy',
  39.         307 => 'Temporary Redirect',
  40.         400 => 'Bad Request',
  41.         401 => 'Unauthorized',
  42.         402 => 'Payment Required',
  43.         403 => 'Forbidden',
  44.         404 => 'Not Found',
  45.         405 => 'Method Not Allowed',
  46.         406 => 'Not Acceptable',
  47.         407 => 'Proxy Authentication Required',
  48.         408 => 'Request Time-out',
  49.         409 => 'Conflict',
  50.         410 => 'Gone',
  51.         411 => 'Length Required',
  52.         412 => 'Precondition Failed',
  53.         413 => 'Request Entity Too Large',
  54.         414 => 'Request-URI Too Large',
  55.         415 => 'Unsupported Media Type',
  56.         416 => 'Requested range not satisfiable',
  57.         417 => 'Expectation Failed',
  58.         500 => 'Internal Server Error',
  59.         501 => 'Not Implemented',
  60.         502 => 'Bad Gateway',
  61.         503 => 'Service Unavailable',
  62.         504 => 'Gateway Time-out',
  63.         505 => 'HTTP Version Not Supported',
  64.         509 => 'Bandwidth Limit Exceeded'
  65.     );
  66.  
  67.     /**
  68.      * HTTPのバージョン。(ja)
  69.      *
  70.      * HTTP Version.(en)
  71.      *
  72.      * @var string 
  73.      * @access public
  74.      */
  75.     static $httpVersion '1.0';
  76.  
  77.     /**
  78.      * HTTPのバージョン。(ja)
  79.      *
  80.      * Available HTTP Versions.(en)
  81.      *
  82.      * @var array 
  83.      * @access public
  84.      */
  85.     static $httpVersions array('1.0''1.1');
  86.  
  87.     /**
  88.      * 有効期限を設定します。(ja)
  89.      *
  90.      * Set the expiration date.(en)
  91.      *
  92.      * <code>
  93.      * HttpResponseHeader::expires(60 * 60);
  94.      *
  95.      * # 以下のようにレスポンスヘッダーを出力します。
  96.      * # Cache-Control: max-age=3600
  97.      * # Expires: Mon, 29 Aug 2011 10:31:06 GMT
  98.      * </code>
  99.      *
  100.      * @param integer $time 有効期限までの秒数(ja) Expiration Seconds(en)
  101.      * @return void 
  102.      * @access public
  103.      */
  104.     function expires($time{
  105.         self::header('Cache-Control''max-age=' $time);
  106.  
  107.         self::header('Expires'$time time());
  108.     }
  109.  
  110.     /**
  111.      * タイムスタンプをRFC 1123の日付形式に変換します。(ja)
  112.      *
  113.      * <code>
  114.      * HttpResponseHeader::date(1314600068);
  115.      *
  116.      * # 出力すると以下のようになります。
  117.      * # Mon, 29 Aug 2011 06:41:08 GMT
  118.      * </code>
  119.      *
  120.      * @param integer $timestamp タイムスタンプ(ja) Timestamp(en)
  121.      * @return string RFC 1123の日付形式(ja) RFC 1123 date format(en)
  122.      * @access public
  123.      */
  124.     function date($timestamp null{
  125.         if(is_null($timestamp)) {
  126.             $timestamp time();
  127.         }
  128.  
  129.         return gmdate('D, d M Y H:i:s'$timestamp' GMT';
  130.     }
  131.  
  132.     /**
  133.      * 既に出力したHTTP Response Headerを取得します。(ja)
  134.      *
  135.      * Get the HTTP Response Header output now.(en)
  136.      *
  137.      * @param mixed $name 取得したいフィールドを指定します。全てのフィールドを取得したい場合値は空でよいです。(ja) Specify the field to get.(en)
  138.      * @return mixed 文字列または配列(ja) string or array(en)
  139.      * @access public
  140.      */
  141.     function getHeader($name null{
  142.         $array array();
  143.  
  144.         $headersList headers_list();
  145.  
  146.         foreach($headersList as $key => $value{
  147.             preg_match('/^(.+?): (.+?)$/'$value$matches);
  148.  
  149.             $array[][$matches[1]] $matches[2];
  150.         }
  151.  
  152.         $headers call_user_func_array('array_merge_recursive'$array);
  153.  
  154.         if($name{
  155.             if(isset($headers[$name])) {
  156.                 return $headers[$name];
  157.             }
  158.  
  159.             return null;
  160.         }
  161.  
  162.         return $headers;
  163.     }
  164.  
  165.     /**
  166.      * リクエストされたHTTPのバージョン。(ja)
  167.      *
  168.      * Version of the HTTP request.(en)
  169.      *
  170.      * @return string HTTPのバージョン(ja) HTTP Version(en)
  171.      * @access public
  172.      */
  173.     function getHttpVersion({
  174.         if (isset($_SERVER['SERVER_PROTOCOL'])) {
  175.             return substr($_SERVER['SERVER_PROTOCOL']-3);
  176.         }
  177.  
  178.         return self::$httpVersion;
  179.     }
  180.  
  181.     /**
  182.      * gzipのエンコードを開始します。(ja)
  183.      *
  184.      * Start the encoding of gzip.(en)
  185.      *
  186.      * <code>
  187.      * HttpResponseHeader::gzip();
  188.      *
  189.      * # 以下のようにレスポンスヘッダーを出力します。
  190.      * # Vary: Accept-Encoding
  191.      * # Content-Encoding: gzip
  192.      * </code>
  193.      *
  194.      * @return mixed 成功した場合はContent-Encoding Headerの内容を、失敗した場合はfalseを返します。
  195.      * @access public
  196.      */
  197.     function gzip({
  198.         ob_start('ob_gzhandler');
  199.  
  200.         self::header('Vary''Accept-Encoding'false);
  201.  
  202.         if(isset($_SERVER['HTTP_ACCEPT_ENCODING'])) {
  203.             $encodings explode(','$_SERVER['HTTP_ACCEPT_ENCODING']);
  204.  
  205.             foreach($encodings as $value{
  206.                 if(in_array(strtolower(trim($value))array('gzip''deflate'))) {
  207.                     self::header('Content-Encoding'$value);
  208.  
  209.                     return $value;
  210.                 }
  211.             }
  212.         }
  213.  
  214.         return false;
  215.     }
  216.  
  217.     /**
  218.      * HTTP Response Headerを出力します。(ja)
  219.      *
  220.      * Print the HTTP Response Header(en)
  221.      *
  222.      * <code>
  223.      * HttpResponseHeader::header(array(
  224.      *     'ETag' => 'Etag Field value',
  225.      *     'Content-MD5' => 'Content-MD5 Field value',
  226.      *     'Last-Modified' => 1314600068
  227.      * ));
  228.      *
  229.      * # 以下のようにレスポンスヘッダーを出力します。
  230.      * # Etag: "d4289a42770d87be5a78cbcefcc1e3b76a07f94dd1005020736b6943e0e65bf07d97472739fb775ea7a8107ce024864def444d935f494e096f2bfd0382bb2e84"
  231.      * # Content-MD5: RhQI+teVkAukVCltE3K+yg==
  232.      * # Last-Modified: Mon, 29 Aug 2011 06:41:08 GMT
  233.      * </code>
  234.      *
  235.      * @param mixed $headers Headerの配列またはフィールド名(ja) Headers array or field name(en)
  236.      * @param mixed $replace 前に送信された類似のヘッダを置換するか。$headersがフィールド名の場合フィールドの内容
  237.       * @param boolean $_replace 
  238.      * @return void 
  239.      * @access public
  240.      */
  241.     function header($headers$replace true$_replace true{
  242.         if(!is_array($headers)) {
  243.             $headers array($headers => $replace);
  244.  
  245.             $replace $_replace;
  246.         }
  247.  
  248.         foreach($headers as $key => $value{
  249.             if(is_array($value)) {
  250.                 $firstKey reset(array_keys($value));
  251.  
  252.                 foreach($value as $_key => $_value{
  253.                     if($firstKey === $_key{
  254.                         self::header($key$_value$replace);
  255.                     else {
  256.                         self::header($key$_valuefalse);
  257.                     }
  258.                 }
  259.             else {
  260.                 if(($key === 'Date' || $key === 'Expires' || $key === 'Last-Modified'&& (is_numeric($value|| is_null($value))) {
  261.                     $value self::date($value);
  262.                 elseif($key === 'ETag' && !preg_match('/^(W\/)?"[a-zA-Z0-9\-]+"$/'$value)) {
  263.                     $value '"' hash('sha512'$value'"';
  264.                 elseif($key === 'Content-MD5' && strlen($value!== 24{
  265.                     $value base64_encode(md5($valuetrue));
  266.                 }
  267.  
  268.                 header($key ': ' $value$replace);
  269.             }
  270.         }
  271.     }
  272.  
  273.     /**
  274.      * HTML用のHeaderを出力します。(ja)
  275.      *
  276.      * Print the Header for HTML.(en)
  277.      *
  278.      * <code>
  279.      * HttpResponseHeader::htmlHeader();
  280.      *
  281.      * # 以下のようにレスポンスヘッダーを出力します。
  282.      * # Content-Style-Type: text/css
  283.      * # Content-Script-Type: text/javascript
  284.      * </code>
  285.      *
  286.      * @return void 
  287.      * @access public
  288.      */
  289.     function htmlHeader({
  290.         self::header(array(
  291.             'Content-Style-Type' => 'text/css',
  292.             'Content-Script-Type' => 'text/javascript',
  293.         ));
  294.     }
  295.  
  296.     /**
  297.      * Webブラウザーがキャッシュしない様に指示します。(ja)
  298.      *
  299.      * Instructs the Web browser not to cache.(en)
  300.      *
  301.      * <code>
  302.      * HttpResponseHeader::noCache();
  303.      *
  304.      * # 以下のようにレスポンスヘッダーを出力します。
  305.      * # Expires: Mon, 26 Jul 1997 05:00:00 GMT
  306.      * # Last-Modified: Mon, 29 Aug 2011 07:15:22 GMT
  307.      * # Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
  308.      * # Pragma: no-cache
  309.      * </code>
  310.      *
  311.      * @return void 
  312.      * @access public
  313.      */
  314.     function noCache({
  315.         self::header(array(
  316.             'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT',
  317.             'Last-Modified' => null,
  318.             'Cache-Control' => array(
  319.                 'no-store, no-cache, must-revalidate',
  320.                 'post-check=0, pre-check=0'
  321.             ),
  322.             'Pragma' => 'no-cache'
  323.         ));
  324.     }
  325.  
  326.     /**
  327.      * 条件が一致すれば"304 Not Modified"または"412 Precondition Failed"を出力します。(ja)
  328.      *
  329.      * Print the "304 Not Modified" or "412 Precondition Failed" if the conditions are matched.(en)
  330.      *
  331.      * @param boolean $exit PHPを終了するならばtrue(ja) If True, the closing PHP(en)
  332.      * @return mixed 
  333.      * @access public
  334.      */
  335.     function notModified($exit true{
  336.         $headers self::getHeader();
  337.  
  338.         $notModified false;
  339.  
  340.         if(isset($headers['ETag']&& isset($_SERVER['HTTP_IF_MATCH']&& $headers['ETag'!== $_SERVER['HTTP_IF_MATCH']{
  341.             self::statusCode(412);
  342.  
  343.             return 412;
  344.         elseif(isset($headers['Last-Modified']&& isset($_SERVER['HTTP_IF_UNMODIFIED_SINCE']&& strtotime($_SERVER['HTTP_IF_UNMODIFIED_SINCE']!== strtotime($headers['Last-Modified'])) {
  345.             self::statusCode(412);
  346.  
  347.             return 412;
  348.         }
  349.  
  350.         if(isset($headers['ETag']&& isset($_SERVER['HTTP_IF_NONE_MATCH']&& $headers['ETag'=== $_SERVER['HTTP_IF_NONE_MATCH']{
  351.             if(isset($_SERVER['REQUEST_METHOD']&& $_SERVER['REQUEST_METHOD'=== 'GET' || $_SERVER['REQUEST_METHOD'=== 'HEAD'{
  352.                 $notModified true;
  353.             else {
  354.                 self::statusCode(412);
  355.  
  356.                 return 412;
  357.             }
  358.         elseif(isset($headers['Last-Modified']&& isset($_SERVER['HTTP_IF_MODIFIED_SINCE']&& strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']=== strtotime($headers['Last-Modified'])) {
  359.             $notModified true;
  360.         }
  361.  
  362.         if($notModified{
  363.             self::statusCode(304);
  364.  
  365.             if($exit{
  366.                 ob_end_clean();
  367.                 exit;
  368.             }
  369.  
  370.             return 304;
  371.         }
  372.  
  373.         return false;
  374.     }
  375.  
  376.     /**
  377.      * パブリックなキャッシュをするように指示します。(ja)
  378.      *
  379.      * Public Cache(en)
  380.      *
  381.      * <code>
  382.      * HttpResponseHeader::publicCache();
  383.      *
  384.      * # 以下のようにレスポンスヘッダーを出力します。
  385.      * # Cache-Control: public
  386.      * # Pragma: public
  387.      * </code>
  388.      *
  389.      * @return void 
  390.      * @access public
  391.      */
  392.     function publicCache({
  393.         self::header(array(
  394.             'Cache-Control' => 'public',
  395.             'Pragma' => 'public'
  396.         ));
  397.     }
  398.  
  399.     /**
  400.      * 範囲リクエストに対応します。(ja)
  401.      *
  402.      * Corresponds to a Range Request.(en)
  403.      *
  404.      * @param string $content 
  405.      * @return mixed 
  406.      * @access public
  407.      */
  408.     function range($content null{
  409.         HttpResponseHeader::header('Accept-Ranges''bytes');
  410.  
  411.         if(isset($_SERVER['HTTP_RANGE']&& preg_match('/^bytes=([0-9]+)?-([0-9]+)?$/'$_SERVER['HTTP_RANGE']$matches)) {
  412.             $headers self::getHeader();
  413.  
  414.             if(isset($_SERVER['HTTP_IF_RANGE'])) {
  415.                 if(preg_match('/^(W\/)?"[a-zA-Z0-9\-]+"$/'$_SERVER['HTTP_IF_RANGE']&& isset($headers['ETag']&& $headers['ETag'!== $_SERVER['HTTP_IF_RANGE']{
  416.                     return false;
  417.                 elseif(isset($headers['Last-Modified']&& strtotime($_SERVER['HTTP_IF_RANGE']!== strtotime($headers['Last-Modified'])) {
  418.                     return false;
  419.                 elseif(!isset($headers['ETag']&& !isset($headers['Last-Modified'])) {
  420.                     return false;
  421.                 }
  422.             }
  423.  
  424.             $od false;
  425.  
  426.             if(!$content{
  427.                 $content ob_get_contents();
  428.  
  429.                 $od true;
  430.             }
  431.  
  432.             $size strlen($content);
  433.  
  434.             if(isset($matches[1]&& $matches[1=== ''{
  435.                 $matches[1null;
  436.             }
  437.  
  438.             if(isset($matches[2]&& $matches[2=== ''{
  439.                 $matches[2null;
  440.             }
  441.  
  442.             if(isset($matches[1]&& isset($matches[2])) {
  443.                 $offset $matches[1];
  444.  
  445.                 $length $matches[2$offset 1;
  446.  
  447.                 $total $matches[2];
  448.  
  449.                 if($total >= $size{
  450.                     $total $size 1;
  451.                 }
  452.             else {
  453.                 $length $size;
  454.  
  455.                 $total $size 1;
  456.  
  457.                 if(isset($matches[1]&& !isset($matches[2])) {
  458.                     $offset $matches[1];
  459.                 elseif(!isset($matches[1]&& isset($matches[2])) {
  460.                     $offset $size $matches[2];
  461.                 else {
  462.                     self::statusCode(416);
  463.  
  464.                     return 416;
  465.                 }
  466.             }
  467.  
  468.             if($offset >= $size || $offset $total{
  469.                 self::statusCode(416);
  470.  
  471.                 return 416;
  472.             }
  473.  
  474.             self::statusCode(206);
  475.  
  476.             self::header('Content-Range''bytes ' $offset '-' $total '/' $size);
  477.  
  478.             $content substr($content$offset$length);
  479.  
  480.             if($od{
  481.                 ob_clean();
  482.             }
  483.  
  484.             echo $content;
  485.  
  486.             return 206;
  487.         }
  488.  
  489.         return false;
  490.     }
  491.  
  492.     /**
  493.      * Serverの情報を出力します。(ja)
  494.      *
  495.      * Print the Server information.(en)
  496.      *
  497.      * <code>
  498.      * HttpResponseHeader::server('Apache/2.2');
  499.      *
  500.      * # 以下のようにレスポンスヘッダーを出力します。
  501.      * # Server: Apache/2.2
  502.      * </code>
  503.      *
  504.      * @param string $content 
  505.      * @return boolean 成功ならばtrueを、失敗ならばfalseを返す。
  506.      * @access public
  507.      */
  508.     function server($content null{
  509.         if($content{
  510.             self::header('Server'$content);
  511.  
  512.             return true;
  513.         elseif(isset($_SERVER['SERVER_SOFTWARE'])) {
  514.             self::header('Server'$_SERVER['SERVER_SOFTWARE']);
  515.  
  516.             return true;
  517.         }
  518.  
  519.         return false;
  520.     }
  521.  
  522.     /**
  523.      * HTTP Status Codeを出力します。(ja)
  524.      *
  525.      * Print the HTTP Status Code.(en)
  526.      *
  527.      * <code>
  528.      * HttpResponseHeader::statusCode(404);
  529.      *
  530.      * # 以下のようにレスポンスヘッダーを出力します。
  531.      * # HTTP/1.1 404 Not Found
  532.      * </code>
  533.      *
  534.      * @param integer $status HTTP Status Codeの番号(ja) The number of HTTP Status Code(en)
  535.      * @param string $httpVersion HTTPのバージョン(ja) HTTP Version(en)
  536.      * @return boolean 成功ならばtrueを、失敗ならばfalseを返します。
  537.      * @access public
  538.      */
  539.     function statusCode($status 200$httpVersion null{
  540.         if(!$httpVersion{
  541.             $httpVersion self::getHttpVersion();
  542.         }
  543.  
  544.         if(isset(self::$httpStatusCodes[$status])) {
  545.             header('HTTP/' $httpVersion ' ' $status ' ' self::$httpStatusCodes[$status]);
  546.  
  547.             return true;
  548.         }
  549.  
  550.         return false;
  551.     }
  552. }
  553. ?>

Documentation generated on Mon, 29 Aug 2011 11:22:14 +0000 by phpDocumentor 1.4.3