Parser.Class.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: phperstar
  5. * Date: 2020/11/6
  6. * Time: 10:31 AM
  7. */
  8. namespace Mall\Framework\Swoole\WebsocketClient;
  9. class Parser
  10. {
  11. const HTTP_EOF = "\r\n\r\n";
  12. protected $buffer;
  13. /**
  14. * 头部解析
  15. * @param $data
  16. * @return array
  17. */
  18. static function parseHeader($data)
  19. {
  20. $header = array();
  21. $header[0] = array();
  22. $meta = &$header[0];
  23. $parts = explode("\r\n\r\n", $data, 2);
  24. // parts[0] = HTTP头;
  25. // parts[1] = HTTP主体,GET请求没有body
  26. $headerLines = explode("\r\n", $parts[0]);
  27. // HTTP协议头,方法,路径,协议[RFC-2616 5.1]
  28. list($meta['method'], $meta['uri'], $meta['protocol']) = explode(' ', $headerLines[0], 3);
  29. //错误的HTTP请求
  30. if (empty($meta['method']) or empty($meta['uri']) or empty($meta['protocol']))
  31. {
  32. return false;
  33. }
  34. unset($headerLines[0]);
  35. //解析Header
  36. $header = array_merge($header, self::parseHeaderLine($headerLines));
  37. return $header;
  38. }
  39. /**
  40. * 传入一个字符串或者数组
  41. * @param $headerLines string/array
  42. * @return array
  43. */
  44. static function parseHeaderLine($headerLines)
  45. {
  46. if (is_string($headerLines))
  47. {
  48. $headerLines = explode("\r\n", $headerLines);
  49. }
  50. $header = array();
  51. foreach ($headerLines as $_h)
  52. {
  53. $_h = trim($_h);
  54. if (empty($_h)) continue;
  55. $_r = explode(':', $_h, 2);
  56. // 头字段名称首字母大写
  57. $keys = explode('-', $_r[0]);
  58. $keys = array_map("ucfirst", $keys);
  59. $key = implode('-', $keys);
  60. $value = isset($_r[1])?$_r[1]:'';
  61. $header[trim($key)] = trim($value);
  62. }
  63. return $header;
  64. }
  65. static function parseParams($str)
  66. {
  67. $params = array();
  68. $blocks = explode(";", $str);
  69. foreach ($blocks as $b)
  70. {
  71. $_r = explode("=", $b, 2);
  72. if(count($_r)==2)
  73. {
  74. list ($key, $value) = $_r;
  75. $params[trim($key)] = trim($value, "\r\n \t\"");
  76. }
  77. else
  78. {
  79. $params[$_r[0]] = '';
  80. }
  81. }
  82. return $params;
  83. }
  84. /**
  85. * 解析Body
  86. * @param $request \Swoole\Request
  87. */
  88. function parseBody(\Swoole\Request $request)
  89. {
  90. $cd = strstr($request->header['Content-Type'], 'boundary');
  91. if (isset($request->header['Content-Type']) and $cd !== false)
  92. {
  93. $this->parseFormData($request, $cd);
  94. }
  95. else
  96. {
  97. if (substr($request->header['Content-Type'], 0, 33) == 'application/x-www-form-urlencoded')
  98. {
  99. parse_str($request->body, $request->post);
  100. }
  101. }
  102. }
  103. /**
  104. * 解析Cookies
  105. * @param $request \Swoole\Request
  106. */
  107. function parseCookie(\Swoole\Request $request)
  108. {
  109. $request->cookie = self::parseParams($request->header['Cookie']);
  110. }
  111. /**
  112. * 解析form_data格式文件
  113. * @param $part
  114. * @param $request \Swoole\Request
  115. * @param $cd
  116. */
  117. static function parseFormData(\Swoole\Request $request, $cd)
  118. {
  119. $cd = '--' . str_replace('boundary=', '', $cd);
  120. $form = explode($cd, rtrim($request->body, "-")); //去掉末尾的--
  121. foreach ($form as $f)
  122. {
  123. if ($f === '')
  124. {
  125. continue;
  126. }
  127. $parts = explode("\r\n\r\n", trim($f));
  128. $header = self::parseHeaderLine($parts[0]);
  129. if (!isset($header['Content-Disposition']))
  130. {
  131. continue;
  132. }
  133. $meta = self::parseParams($header['Content-Disposition']);
  134. //filename字段表示它是一个文件
  135. if (!isset($meta['filename']))
  136. {
  137. if (count($parts) < 2)
  138. {
  139. $parts[1] = "";
  140. }
  141. //支持checkbox
  142. if (substr($meta['name'], -2) === '[]')
  143. {
  144. $request->post[substr($meta['name'], 0, -2)][] = trim($parts[1]);
  145. }
  146. else
  147. {
  148. $request->post[$meta['name']] = trim($parts[1], "\r\n");
  149. }
  150. }
  151. else
  152. {
  153. $tmp_file = tempnam('/tmp', 'sw');
  154. file_put_contents($tmp_file, $parts[1]);
  155. if (!isset($meta['name']))
  156. {
  157. $meta['name'] = 'file';
  158. }
  159. $request->files[$meta['name']] = array(
  160. 'name' => $meta['filename'],
  161. 'type' => $header['Content-Type'],
  162. 'size' => strlen($parts[1]),
  163. 'error' => UPLOAD_ERR_OK,
  164. 'tmp_name' => $tmp_file,
  165. );
  166. }
  167. }
  168. }
  169. /**
  170. * 头部http协议
  171. * @param $data
  172. * @return array
  173. */
  174. function parse($data)
  175. {
  176. $_header = strstr($data, self::HTTP_EOF, true);
  177. if ($_header === false)
  178. {
  179. $this->buffer = $data;
  180. }
  181. $header = self::parseHeader($_header);
  182. if ($header === false)
  183. {
  184. $this->isError = true;
  185. }
  186. $this->header = $header;
  187. return $header;
  188. }
  189. }