Explorar o código

support upload file

walkor %!s(int64=10) %!d(string=hai) anos
pai
achega
4d9f9dea65
Modificáronse 1 ficheiros con 79 adicións e 31 borrados
  1. 79 31
      Workerman/Protocols/Http.php

+ 79 - 31
Workerman/Protocols/Http.php

@@ -21,19 +21,15 @@ class Http implements \Workerman\Protocols\ProtocolInterface
         {
             // find Content-Length
             $match = array();
-            if(preg_match("/\r\nContent-Length: ?(\d*)\r\n/", $header, $match))
+            if(preg_match("/\r\nContent-Length: ?(\d+)/", $header, $match))
             {
                 $content_lenght = $match[1];
+                return $content_lenght;
             }
             else
             {
                 return 0;
             }
-            if($content_lenght <= strlen($body))
-            {
-                return strlen($header)+4+$content_lenght;
-            }
-            return 0;
         }
         else
         {
@@ -45,7 +41,7 @@ class Http implements \Workerman\Protocols\ProtocolInterface
     public static function decode($recv_buffer, ConnectionInterface $connection)
     {
         // 初始化
-        $_POST = $_GET = $_COOKIE = $_REQUEST = $_SESSION =  array();
+        $_POST = $_GET = $_COOKIE = $_REQUEST = $_SESSION = $_FILES =  array();
         $GLOBALS['HTTP_RAW_POST_DATA'] = '';
         // 清空上次的数据
         HttpCache::$header = array();
@@ -65,25 +61,15 @@ class Http implements \Workerman\Protocols\ProtocolInterface
               'HTTP_ACCEPT_ENCODING' => '',
               'HTTP_COOKIE' => '',
               'HTTP_CONNECTION' => '',
-              'REQUEST_TIME' => 0,
               'REMOTE_ADDR' => '',
               'REMOTE_PORT' => '0',
            );
         
         // 将header分割成数组
-        $header_data = explode("\r\n", $recv_buffer);
+        list($http_header, $http_body) = explode("\r\n\r\n", $recv_buffer, 2);
+        $header_data = explode("\r\n", $http_header);
         
         list($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'], $_SERVER['SERVER_PROTOCOL']) = explode(' ', $header_data[0]);
-        // 需要解析$_POST
-        if($_SERVER['REQUEST_METHOD'] == 'POST')
-        {
-            $tmp = explode("\r\n\r\n", $recv_buffer, 2);
-            parse_str($tmp[1], $_POST);
-        
-            // $GLOBALS['HTTP_RAW_POST_DATA']
-            $GLOBALS['HTTP_RAW_POST_DATA'] = $tmp[1];
-            unset($header_data[count($header_data) - 1]);
-        }
         
         unset($header_data[0]);
         foreach($header_data as $content)
@@ -105,7 +91,7 @@ class Http implements \Workerman\Protocols\ProtocolInterface
                     $_SERVER['SERVER_NAME'] = $tmp[0];
                     if(isset($tmp[1]))
                     {
-                        $_SERVER['SERVER_PORT'] = (int)$tmp[1];
+                        $_SERVER['SERVER_PORT'] = $tmp[1];
                     }
                     break;
                 // cookie
@@ -134,14 +120,6 @@ class Http implements \Workerman\Protocols\ProtocolInterface
                 // connection
                 case 'connection':
                     $_SERVER['HTTP_CONNECTION'] = $value;
-                    if(strtolower($value) === 'keep-alive')
-                    {
-                        HttpCache::$header['Connection'] = 'Connection: Keep-Alive';
-                    }
-                    else
-                    {
-                        HttpCache::$header['Connection'] = 'Connection: Closed';
-                    }
                     break;
                 case 'referer':
                     $_SERVER['HTTP_REFERER'] = $value;
@@ -152,12 +130,34 @@ class Http implements \Workerman\Protocols\ProtocolInterface
                 case 'if-none-match':
                     $_SERVER['HTTP_IF_NONE_MATCH'] = $value;
                     break;
+                case 'content-type':
+                    if(!preg_match('/boundary="?(\S+)"?/', $value, $match))
+                    {
+                        $_SERVER['CONTENT_TYPE'] = $value;
+                    }
+                    else
+                    {
+                        $_SERVER['CONTENT_TYPE'] = 'multipart/form-data';
+                        $http_post_boundary = '--'.$match[1];
+                    }
+                    break;
             }
         }
         
-        // 'REQUEST_TIME_FLOAT' => 1375774613.237,
-        $_SERVER['REQUEST_TIME_FLOAT'] = microtime(true);
-        $_SERVER['REQUEST_TIME'] = intval($_SERVER['REQUEST_TIME_FLOAT']);
+        // 需要解析$_POST
+        if($_SERVER['REQUEST_METHOD'] == 'POST')
+        {
+            if(isset($_SERVER['CONTENT_TYPE']) && $_SERVER['CONTENT_TYPE'] == 'multipart/form-data')
+            {
+                self::parseUploadFiles($http_body, $http_post_boundary);
+            }
+            else
+            {
+                parse_str($http_body, $_POST);
+                // $GLOBALS['HTTP_RAW_POST_DATA']
+                $GLOBALS['HTTP_RAW_POST_DATA'] = $http_body;
+            }
+        }
         
         // QUERY_STRING
         $_SERVER['QUERY_STRING'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY);
@@ -377,6 +377,54 @@ class Http implements \Workerman\Protocols\ProtocolInterface
     {
         return __DIR__.'/Http/mime.types';
     }
+    
+     /**
+     * 解析$_FILES
+     */
+    protected function parseUploadFiles($http_body, $http_post_boundary)
+    {
+        $http_body = substr($http_body, 0, strlen($http_body) - (strlen($http_post_boundary) + 4));
+        $boundary_data_array = explode($http_post_boundary."\r\n", $http_body);
+        if($boundary_data_array[0] === '')
+        {
+            unset($boundary_data_array[0]);
+        }
+        foreach($boundary_data_array as $boundary_data_buffer)
+        {
+            list($boundary_header_buffer, $boundary_value) = explode("\r\n\r\n", $boundary_data_buffer, 2);
+            // 去掉末尾\r\n
+            $boundary_value = substr($boundary_value, 0, -2);
+            foreach (explode("\r\n", $boundary_header_buffer) as $item)
+            {
+                list($header_key, $header_value) = explode(": ", $item);
+                $header_key = strtolower($header_key);
+                switch ($header_key)
+                {
+                    case "content-disposition":
+                        // 是文件
+                        if(preg_match('/name=".*?"; filename="(.*?)"$/', $header_value, $match))
+                        {
+                            $_FILES[] = array(
+                                'file_name' => $match[1],
+                                'file_data' => $boundary_value,
+                                'file_size' => strlen($boundary_value),
+                            );
+                            continue;
+                        }
+                        // 是post field
+                        else
+                        {
+                            // 收集post
+                            if(preg_match('/name="(.*?)"$/', $header_value, $match))
+                            {
+                                $_POST[$match[1]] = $boundary_value;
+                            }
+                        }
+                        break;
+                }
+            }
+        }
+    }
 }
 
 /**