Http.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. <?php
  2. namespace App\Common\Protocols\Http;
  3. /**
  4. * 判断http协议的数据包是否完整
  5. * @param string $http_string
  6. * @return integer 0表示完整 否则还需要integer长度的数据
  7. */
  8. function http_input($http_string)
  9. {
  10. // 查找\r\n\r\n
  11. $data_length = strlen($http_string);
  12. if(!strpos($http_string, "\r\n\r\n"))
  13. {
  14. return 1;
  15. }
  16. // POST请求还要读包体
  17. if(strpos($http_string, "POST"))
  18. {
  19. // 找Content-Length
  20. $match = array();
  21. if(preg_match("/\r\nContent-Length: ?(\d?)\r\n/", $http_string, $match))
  22. {
  23. $content_lenght = $match[1];
  24. }
  25. else
  26. {
  27. return 0;
  28. }
  29. // 看包体长度是否符合
  30. $tmp = explode("\r\n\r\n", $http_string, 2);
  31. $remain_length = $content_lenght - strlen($tmp[1]);
  32. return $remain_length >= 0 ? $remain_length : 0;
  33. }
  34. return 0;
  35. }
  36. /**
  37. * 解析http协议,设置$_POST $_GET $_COOKIE $_REQUEST
  38. * @param string $http_string
  39. */
  40. function http_start($http_string, $SERVER = array())
  41. {
  42. // 初始化
  43. $_POST = $_GET = $_COOKIE = $_REQUEST = $_SESSION = array();
  44. $GLOBALS['HTTP_RAW_POST_DATA'] = '';
  45. // 清空上次的数据
  46. HttpCache::$header = array();
  47. HttpCache::$instance = new HttpCache();
  48. // 需要设置的变量名
  49. $_SERVER = array (
  50. 'QUERY_STRING' => '',
  51. 'REQUEST_METHOD' => '',
  52. 'REQUEST_URI' => '',
  53. 'SERVER_PROTOCOL' => 'HTTP/1.1',
  54. 'GATEWAY_INTERFACE' => 'CGI/1.1',
  55. 'SERVER_SOFTWARE' => 'workerman/2.1',
  56. 'SERVER_NAME' => '',
  57. 'HTTP_HOST' => '',
  58. 'HTTP_USER_AGENT' => '',
  59. 'HTTP_ACCEPT' => '',
  60. 'HTTP_ACCEPT_LANGUAGE' => '',
  61. 'HTTP_ACCEPT_ENCODING' => '',
  62. 'HTTP_COOKIE' => '',
  63. 'HTTP_CONNECTION' => '',
  64. 'REQUEST_TIME' => 0,
  65. 'SCRIPT_NAME' => '',//$SERVER传递
  66. 'REMOTE_ADDR' => '',// $SERVER传递
  67. 'REMOTE_PORT' => '0',// $SERVER传递
  68. 'SERVER_ADDR' => '', // $SERVER传递
  69. 'DOCUMENT_ROOT' => '',//$SERVER传递
  70. 'SCRIPT_FILENAME' => '',// $SERVER传递
  71. 'SERVER_PORT' => '80',
  72. 'PHP_SELF' => '', // 设置成SCRIPT_NAME
  73. );
  74. // 将header分割成数组
  75. $header_data = explode("\r\n", $http_string);
  76. list($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'], $_SERVER['SERVER_PROTOCOL']) = explode(' ', $header_data[0]);
  77. // 需要解析$_POST
  78. if($_SERVER['REQUEST_METHOD'] == 'POST')
  79. {
  80. $tmp = explode("\r\n\r\n", $http_string, 2);
  81. parse_str($tmp[1], $_POST);
  82. // $GLOBALS['HTTP_RAW_POST_DATA']
  83. $GLOBALS['HTTP_RAW_POST_DATA'] = $tmp[1];
  84. unset($header_data[count($header_data) - 1]);
  85. }
  86. unset($header_data[0]);
  87. foreach($header_data as $content)
  88. {
  89. // \r\n\r\n
  90. if(empty($content))
  91. {
  92. continue;
  93. }
  94. list($key, $value) = explode(':', $content, 2);
  95. $key = strtolower($key);
  96. $value = trim($value);
  97. switch($key)
  98. {
  99. // HTTP_HOST
  100. case 'host':
  101. $_SERVER['HTTP_HOST'] = $value;
  102. $tmp = explode(':', $value);
  103. $_SERVER['SERVER_NAME'] = $tmp[0];
  104. if(isset($tmp[1]))
  105. {
  106. $_SERVER['SERVER_PORT'] = $tmp[1];
  107. }
  108. break;
  109. // cookie
  110. case 'cookie':
  111. {
  112. $_SERVER['HTTP_COOKIE'] = $value;
  113. parse_str(str_replace('; ', '&', $_SERVER['HTTP_COOKIE']), $_COOKIE);
  114. }
  115. break;
  116. // user-agent
  117. case 'user-agent':
  118. $_SERVER['HTTP_USER_AGENT'] = $value;
  119. break;
  120. // accept
  121. case 'accept':
  122. $_SERVER['HTTP_ACCEPT'] = $value;
  123. break;
  124. // accept-language
  125. case 'accept-language':
  126. $_SERVER['HTTP_ACCEPT_LANGUAGE'] = $value;
  127. break;
  128. // accept-encoding
  129. case 'accept-encoding':
  130. $_SERVER['HTTP_ACCEPT_ENCODING'] = $value;
  131. break;
  132. // connection
  133. case 'connection':
  134. $_SERVER['HTTP_CONNECTION'] = $value;
  135. break;
  136. case 'referer':
  137. $_SERVER['HTTP_REFERER'] = $value;
  138. break;
  139. case 'if-modified-since':
  140. $_SERVER['HTTP_IF_MODIFIED_SINCE'] = $value;
  141. break;
  142. case 'if-none-match':
  143. $_SERVER['HTTP_IF_NONE_MATCH'] = $value;
  144. break;
  145. }
  146. }
  147. // 'REQUEST_TIME_FLOAT' => 1375774613.237,
  148. $_SERVER['REQUEST_TIME_FLOAT'] = microtime(true);
  149. $_SERVER['REQUEST_TIME'] = intval($_SERVER['REQUEST_TIME_FLOAT']);
  150. // QUERY_STRING
  151. $_SERVER['QUERY_STRING'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY);
  152. // GET
  153. parse_str($_SERVER['QUERY_STRING'], $_GET);
  154. // REQUEST
  155. $_REQUEST = array_merge($_GET, $_POST);
  156. // 合并传递的值
  157. $_SERVER = array_merge($_SERVER, $SERVER);
  158. // PHP_SELF
  159. if($_SERVER['SCRIPT_NAME'] && !$_SERVER['PHP_SELF'])
  160. {
  161. $_SERVER['PHP_SELF'] = $_SERVER['SCRIPT_NAME'];
  162. }
  163. }
  164. function http_end($content)
  165. {
  166. // 没有http-code默认给个
  167. if(!isset(HttpCache::$header['Http-Code']))
  168. {
  169. $header = "HTTP/1.1 200 OK\r\n";
  170. }
  171. else
  172. {
  173. $header = HttpCache::$header['Http-Code']."\r\n";
  174. unset(HttpCache::$header['Http-Code']);
  175. }
  176. // 没有Content-Type默认给个
  177. if(!isset(HttpCache::$header['Content-Type']))
  178. {
  179. $header .= "Content-Type: text/html;charset=utf-8\r\n";
  180. }
  181. // 其它header
  182. foreach(HttpCache::$header as $key=>$item)
  183. {
  184. if('Set-Cookie' == $key && is_array($item))
  185. {
  186. foreach($item as $it)
  187. {
  188. $header .= $it."\r\n";
  189. }
  190. }
  191. else
  192. {
  193. $header .= $item."\r\n";
  194. }
  195. }
  196. // header
  197. $header .= "Server: WorkerMan/2.1\r\nContent-Length: ".strlen($content)."\r\n";
  198. $header .= "\r\n";
  199. HttpCache::$header = array();
  200. // 保存cookie
  201. session_write_close();
  202. $_POST = $_GET = $_COOKIE = $_REQUEST = $_SESSION = array();
  203. $GLOBALS['HTTP_RAW_POST_DATA'] = '';
  204. HttpCache::$instance = null;
  205. // 整个http包
  206. return $header.$content;
  207. }
  208. /**
  209. * 设置http头
  210. * @return bool
  211. */
  212. function header($content, $replace = true, $http_response_code = 0)
  213. {
  214. if(!defined('WORKERMAN_ROOT_DIR'))
  215. {
  216. if($http_response_code != 0)
  217. {
  218. return \header($content, $replace, $http_response_code);
  219. }
  220. else
  221. {
  222. return \header($content, $replace);
  223. }
  224. }
  225. if(strpos($content, 'HTTP') === 0)
  226. {
  227. $key = 'Http-Code';
  228. }
  229. else
  230. {
  231. $key = strstr($content, ":", true);
  232. if(empty($key))
  233. {
  234. return false;
  235. }
  236. }
  237. if(isset(HttpCache::$codes[$http_response_code]))
  238. {
  239. HttpCache::$header['Http-Code'] = 'HTTP/1.1 ' . HttpCache::$codes[$http_response_code];
  240. }
  241. if($key == 'Set-Cookie')
  242. {
  243. HttpCache::$header[$key][] = $content;
  244. }
  245. else
  246. {
  247. HttpCache::$header[$key] = $content;
  248. }
  249. if('location' == strtolower($key))
  250. {
  251. header('HTTP/1.1 302 Moved Temporarily');
  252. }
  253. return true;
  254. }
  255. /**
  256. * 删除一个header
  257. * @param string $name
  258. * @return void
  259. */
  260. function header_remove($name)
  261. {
  262. if(!defined('WORKERMAN_ROOT_DIR'))
  263. {
  264. return \header_remove($name);
  265. }
  266. unset( HttpCache::$header[$name]);
  267. }
  268. /**
  269. * 设置cookie
  270. * @param string $name
  271. * @param string $value
  272. * @param integer $maxage
  273. * @param string $path
  274. * @param string $domain
  275. * @param bool $secure
  276. * @param bool $HTTPOnly
  277. */
  278. function setcookie($name, $value = '', $maxage = 0, $path = '', $domain = '', $secure = false, $HTTPOnly = false) {
  279. if(!defined('WORKERMAN_ROOT_DIR'))
  280. {
  281. return \setcookie($name, $value, $maxage, $path, $domain, $secure, $HTTPOnly);
  282. }
  283. header(
  284. 'Set-Cookie: ' . $name . '=' . rawurlencode($value)
  285. . (empty($domain) ? '' : '; Domain=' . $domain)
  286. . (empty($maxage) ? '' : '; Max-Age=' . $maxage)
  287. . (empty($path) ? '' : '; Path=' . $path)
  288. . (!$secure ? '' : '; Secure')
  289. . (!$HTTPOnly ? '' : '; HttpOnly'), false);
  290. }
  291. /**
  292. * session_start
  293. *
  294. */
  295. function session_start()
  296. {
  297. if(!defined('WORKERMAN_ROOT_DIR'))
  298. {
  299. return \session_start();
  300. }
  301. if(HttpCache::$instance->sessionStarted)
  302. {
  303. echo "already sessionStarted\nn";
  304. return true;
  305. }
  306. HttpCache::$instance->sessionStarted = true;
  307. // 没有sid,则创建一个session文件,生成一个sid
  308. if(!isset($_COOKIE[HttpCache::$sessionName]) || !is_file(HttpCache::$sessionPath . '/sess_' . $_COOKIE[HttpCache::$sessionName]))
  309. {
  310. $file_name = tempnam(HttpCache::$sessionPath, 'sess_');
  311. if(!$file_name)
  312. {
  313. return false;
  314. }
  315. HttpCache::$instance->sessionFile = $file_name;
  316. $session_id = substr(basename($file_name), strlen('sess_'));
  317. return setcookie(
  318. HttpCache::$sessionName
  319. , $session_id
  320. , ini_get('session.cookie_lifetime')
  321. , ini_get('session.cookie_path')
  322. , ini_get('session.cookie_domain')
  323. , ini_get('session.cookie_secure')
  324. , ini_get('session.cookie_httponly')
  325. );
  326. }
  327. if(!HttpCache::$instance->sessionFile)
  328. {
  329. HttpCache::$instance->sessionFile = HttpCache::$sessionPath . '/sess_' . $_COOKIE[HttpCache::$sessionName];
  330. }
  331. // 有sid则打开文件,读取session值
  332. if(HttpCache::$instance->sessionFile)
  333. {
  334. $raw = file_get_contents(HttpCache::$instance->sessionFile);
  335. if($raw)
  336. {
  337. session_decode($raw);
  338. }
  339. }
  340. }
  341. /**
  342. * 保存session
  343. */
  344. function session_write_close()
  345. {
  346. if(!defined('WORKERMAN_ROOT_DIR'))
  347. {
  348. return \session_write_close();
  349. }
  350. if(!empty(HttpCache::$instance->sessionStarted) && !empty($_SESSION))
  351. {
  352. $session_str = session_encode();
  353. if($session_str && HttpCache::$instance->sessionFile)
  354. {
  355. return file_put_contents(HttpCache::$instance->sessionFile, $session_str);
  356. }
  357. }
  358. return empty($_SESSION);
  359. }
  360. /**
  361. * 退出
  362. * @param string $msg
  363. * @throws \Exception
  364. */
  365. function jump_exit($msg = '')
  366. {
  367. if(!defined('WORKERMAN_ROOT_DIR'))
  368. {
  369. return exit($msg);
  370. }
  371. if($msg)
  372. {
  373. echo $msg;
  374. }
  375. throw new \Exception('jump_exit');
  376. }
  377. /**
  378. * 解析http协议数据包 缓存先关
  379. * @author walkor
  380. */
  381. class HttpCache
  382. {
  383. public static $codes = array(
  384. 100 => 'Continue',
  385. 101 => 'Switching Protocols',
  386. 200 => 'OK',
  387. 201 => 'Created',
  388. 202 => 'Accepted',
  389. 203 => 'Non-Authoritative Information',
  390. 204 => 'No Content',
  391. 205 => 'Reset Content',
  392. 206 => 'Partial Content',
  393. 300 => 'Multiple Choices',
  394. 301 => 'Moved Permanently',
  395. 302 => 'Found',
  396. 303 => 'See Other',
  397. 304 => 'Not Modified',
  398. 305 => 'Use Proxy',
  399. 306 => '(Unused)',
  400. 307 => 'Temporary Redirect',
  401. 400 => 'Bad Request',
  402. 401 => 'Unauthorized',
  403. 402 => 'Payment Required',
  404. 403 => 'Forbidden',
  405. 404 => 'Not Found',
  406. 405 => 'Method Not Allowed',
  407. 406 => 'Not Acceptable',
  408. 407 => 'Proxy Authentication Required',
  409. 408 => 'Request Timeout',
  410. 409 => 'Conflict',
  411. 410 => 'Gone',
  412. 411 => 'Length Required',
  413. 412 => 'Precondition Failed',
  414. 413 => 'Request Entity Too Large',
  415. 414 => 'Request-URI Too Long',
  416. 415 => 'Unsupported Media Type',
  417. 416 => 'Requested Range Not Satisfiable',
  418. 417 => 'Expectation Failed',
  419. 422 => 'Unprocessable Entity',
  420. 423 => 'Locked',
  421. 500 => 'Internal Server Error',
  422. 501 => 'Not Implemented',
  423. 502 => 'Bad Gateway',
  424. 503 => 'Service Unavailable',
  425. 504 => 'Gateway Timeout',
  426. 505 => 'HTTP Version Not Supported',
  427. );
  428. public static $instance = null;
  429. public static $header = array();
  430. public static $sessionPath = '';
  431. public static $sessionName = '';
  432. public $sessionStarted = false;
  433. public $sessionFile = '';
  434. public static function init()
  435. {
  436. self::$sessionName = ini_get('session.name');
  437. self::$sessionPath = session_save_path();
  438. if(!self::$sessionPath)
  439. {
  440. self::$sessionPath = sys_get_temp_dir();
  441. }
  442. @\session_start();
  443. }
  444. }