<?php /** * Created by PhpStorm. * User: phperstar * Date: 2020/11/6 * Time: 10:31 AM */ namespace Mall\Framework\Swoole\WebsocketClient; class Parser { const HTTP_EOF = "\r\n\r\n"; protected $buffer; /** * 头部解析 * @param $data * @return array */ static function parseHeader($data) { $header = array(); $header[0] = array(); $meta = &$header[0]; $parts = explode("\r\n\r\n", $data, 2); // parts[0] = HTTP头; // parts[1] = HTTP主体,GET请求没有body $headerLines = explode("\r\n", $parts[0]); // HTTP协议头,方法,路径,协议[RFC-2616 5.1] list($meta['method'], $meta['uri'], $meta['protocol']) = explode(' ', $headerLines[0], 3); //错误的HTTP请求 if (empty($meta['method']) or empty($meta['uri']) or empty($meta['protocol'])) { return false; } unset($headerLines[0]); //解析Header $header = array_merge($header, self::parseHeaderLine($headerLines)); return $header; } /** * 传入一个字符串或者数组 * @param $headerLines string/array * @return array */ static function parseHeaderLine($headerLines) { if (is_string($headerLines)) { $headerLines = explode("\r\n", $headerLines); } $header = array(); foreach ($headerLines as $_h) { $_h = trim($_h); if (empty($_h)) continue; $_r = explode(':', $_h, 2); // 头字段名称首字母大写 $keys = explode('-', $_r[0]); $keys = array_map("ucfirst", $keys); $key = implode('-', $keys); $value = isset($_r[1])?$_r[1]:''; $header[trim($key)] = trim($value); } return $header; } static function parseParams($str) { $params = array(); $blocks = explode(";", $str); foreach ($blocks as $b) { $_r = explode("=", $b, 2); if(count($_r)==2) { list ($key, $value) = $_r; $params[trim($key)] = trim($value, "\r\n \t\""); } else { $params[$_r[0]] = ''; } } return $params; } /** * 解析Body * @param $request \Swoole\Request */ function parseBody(\Swoole\Request $request) { $cd = strstr($request->header['Content-Type'], 'boundary'); if (isset($request->header['Content-Type']) and $cd !== false) { $this->parseFormData($request, $cd); } else { if (substr($request->header['Content-Type'], 0, 33) == 'application/x-www-form-urlencoded') { parse_str($request->body, $request->post); } } } /** * 解析Cookies * @param $request \Swoole\Request */ function parseCookie(\Swoole\Request $request) { $request->cookie = self::parseParams($request->header['Cookie']); } /** * 解析form_data格式文件 * @param $part * @param $request \Swoole\Request * @param $cd */ static function parseFormData(\Swoole\Request $request, $cd) { $cd = '--' . str_replace('boundary=', '', $cd); $form = explode($cd, rtrim($request->body, "-")); //去掉末尾的-- foreach ($form as $f) { if ($f === '') { continue; } $parts = explode("\r\n\r\n", trim($f)); $header = self::parseHeaderLine($parts[0]); if (!isset($header['Content-Disposition'])) { continue; } $meta = self::parseParams($header['Content-Disposition']); //filename字段表示它是一个文件 if (!isset($meta['filename'])) { if (count($parts) < 2) { $parts[1] = ""; } //支持checkbox if (substr($meta['name'], -2) === '[]') { $request->post[substr($meta['name'], 0, -2)][] = trim($parts[1]); } else { $request->post[$meta['name']] = trim($parts[1], "\r\n"); } } else { $tmp_file = tempnam('/tmp', 'sw'); file_put_contents($tmp_file, $parts[1]); if (!isset($meta['name'])) { $meta['name'] = 'file'; } $request->files[$meta['name']] = array( 'name' => $meta['filename'], 'type' => $header['Content-Type'], 'size' => strlen($parts[1]), 'error' => UPLOAD_ERR_OK, 'tmp_name' => $tmp_file, ); } } } /** * 头部http协议 * @param $data * @return array */ function parse($data) { $_header = strstr($data, self::HTTP_EOF, true); if ($_header === false) { $this->buffer = $data; } $header = self::parseHeader($_header); if ($header === false) { $this->isError = true; } $this->header = $header; return $header; } }