HTTP.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php
  2. /**
  3. * http 协议解析 相关
  4. * 简单的实现,可能会有bug,不要用于生产环境
  5. * @author walkor <worker-man@qq.com>
  6. * */
  7. class HTTP{
  8. /**
  9. * 构造函数
  10. */
  11. private function __construct(){}
  12. /**
  13. * http头
  14. * @var array
  15. */
  16. public static $header = array();
  17. /**
  18. * cookie
  19. * @var array
  20. */
  21. protected static $cookie = array();
  22. /**
  23. * 判断数据包是否全部接收完成
  24. *
  25. * @param string $data
  26. * @return int 0:完成 1:还要接收数据
  27. */
  28. public static function input($data)
  29. {
  30. // 查找\r\n\r\n
  31. $data_length = strlen($data);
  32. if(!strpos($data, "\r\n\r\n"))
  33. {
  34. return 1;
  35. }
  36. // POST请求还要读包体
  37. if(strpos($data, "POST"))
  38. {
  39. // 找Content-Length
  40. $match = array();
  41. if(preg_match("/\r\nContent-Length: ?(\d?)\r\n/", $data, $match))
  42. {
  43. $content_lenght = $match[1];
  44. }
  45. else
  46. {
  47. return 0;
  48. }
  49. // 看包体长度是否符合
  50. $tmp = explode("\r\n\r\n", $data);
  51. if(strlen($tmp[1]) >= $content_lenght)
  52. {
  53. return 0;
  54. }
  55. return 1;
  56. }
  57. else
  58. {
  59. return 0;
  60. }
  61. // var_export($header_data);
  62. return 0;
  63. }
  64. /**
  65. * 解析http协议包,并设置相应环境变量
  66. *
  67. * @param string $data
  68. * @return array
  69. */
  70. public static function decode($data)
  71. {
  72. $_SERVER = array(
  73. 'REQUEST_URI' => '/',
  74. 'HTTP_HOST' => '127.0.0.1',
  75. 'HTTP_COOKIE' => '',
  76. );
  77. $_POST = array();
  78. $_GET = array();
  79. $GLOBALS['HTTP_RAW_POST_DATA'] = array();
  80. // 将header分割成数组
  81. $header_data = explode("\r\n", $data);
  82. // 需要解析$_POST
  83. if(strpos($data, "POST") === 0)
  84. {
  85. $tmp = explode("\r\n\r\n", $data);
  86. parse_str($tmp[1], $_POST);
  87. // $GLOBALS['HTTP_RAW_POST_DATA']
  88. $GLOBALS['HTTP_RAW_POST_DATA'] = $tmp[1];
  89. }
  90. // REQUEST_URI
  91. $tmp = explode(' ', $header_data[0]);
  92. $_SERVER['REQUEST_URI'] = isset($tmp[1]) ? $tmp[1] : '/';
  93. // PHP_SELF
  94. $base_name = basename($_SERVER['REQUEST_URI']);
  95. $_SERVER['PHP_SELF'] = empty($base_name) ? 'index.php' : $base_name;
  96. unset($header_data[0]);
  97. foreach($header_data as $content)
  98. {
  99. // 解析HTTP_HOST
  100. if(strpos($content, 'Host') === 0)
  101. {
  102. $tmp = explode(':', $content);
  103. if(isset($tmp[1]))
  104. {
  105. $_SERVER['HTTP_HOST'] = $tmp[1];
  106. }
  107. if(isset($tmp[2]))
  108. {
  109. $_SERVER['SERVER_PORT'] = $tmp[2];
  110. }
  111. }
  112. // 解析Cookie
  113. elseif(strpos($content, 'Cookie') === 0)
  114. {
  115. $tmp = explode(' ', $content);
  116. if(isset($tmp[1]))
  117. {
  118. $_SERVER['HTTP_COOKIE'] = $tmp[1];
  119. }
  120. }
  121. }
  122. // 'REQUEST_TIME_FLOAT' => 1375774613.237,
  123. $_SERVER['REQUEST_TIME_FLOAT'] = microtime(true);
  124. $_SERVER['REQUEST_TIME'] = intval($_SERVER['REQUEST_TIME_FLOAT']);
  125. // GET
  126. parse_str(preg_replace('/^\/.*?\?/', '', $_SERVER['REQUEST_URI']), $_GET);
  127. unset($_GET['/']);
  128. }
  129. /**
  130. * 设置http头
  131. * @return bool
  132. */
  133. public static function header($content)
  134. {
  135. if(strpos($content, 'HTTP') === 0)
  136. {
  137. $key = 'Http-Code';
  138. }
  139. else
  140. {
  141. $key = strstr($content, ":", true);
  142. if(empty($key))
  143. {
  144. return false;
  145. }
  146. }
  147. self::$header[$key] = $content;
  148. return true;
  149. }
  150. /**
  151. *
  152. * @param string $name
  153. * @param string/int $value
  154. * @param int $expire
  155. */
  156. public static function setcookie($name, $value='', $expire=0)
  157. {
  158. // 待完善
  159. }
  160. /**
  161. * 清除header
  162. * @return void
  163. */
  164. public static function clear()
  165. {
  166. self::$header = array();
  167. }
  168. /**
  169. * 打包http协议,用于返回数据给nginx
  170. *
  171. * @param string $data
  172. * @return string
  173. */
  174. public static function encode($data)
  175. {
  176. // header
  177. $header = "Server: PHPServer/1.0\r\nContent-Length: ".strlen($data)."\r\n";
  178. // 没有Content-Type默认给个
  179. if(!isset(self::$header['Content-Type']))
  180. {
  181. $header = "Content-Type: text/html;charset=utf-8\r\n".$header;
  182. }
  183. // 没有http-code默认给个
  184. if(!isset(self::$header['Http-Code']))
  185. {
  186. $header = "HTTP/1.1 200 OK\r\n".$header;
  187. }
  188. else
  189. {
  190. $header = self::$header['Http-Code']."\r\n".$header;
  191. unset(self::$header['Http-Code']);
  192. }
  193. // 其它header
  194. foreach(self::$header as $content)
  195. {
  196. $header .= $content."\r\n";
  197. }
  198. $header .= "\r\n";
  199. self::clear();
  200. // 整个http包
  201. return $header.$data;
  202. }
  203. }