walkor пре 1 година
родитељ
комит
725dcffda0

+ 5 - 4
src/Connection/TcpConnection.php

@@ -664,6 +664,7 @@ class TcpConnection extends ConnectionInterface implements JsonSerializable
                         } catch (Throwable $e) {
                             $this->error($e);
                         }
+                        $request->properties = [];
                         $requests[$buffer] = clone $request;
                         return;
                     }
@@ -692,10 +693,10 @@ class TcpConnection extends ConnectionInterface implements JsonSerializable
                 } else {
                     // Get current package length.
                     try {
-                        /** @var ProtocolInterface $parser */
-                        $parser = $this->protocol;
-                        $this->currentPackageLength = $parser::input($this->recvBuffer, $this);
-                    } catch (Throwable) {
+                        $this->currentPackageLength = $this->protocol::input($this->recvBuffer, $this);
+                    } catch (Throwable $e) {
+                        $this->currentPackageLength = -1;
+                        Worker::safeEcho((string)$e);
                     }
                     // The packet length is unknown.
                     if ($this->currentPackageLength === 0) {

+ 33 - 19
src/Protocols/Http.php

@@ -90,18 +90,14 @@ class Http
         }
 
         $length = $crlfPos + 4;
-        $firstLine = explode(" ", strstr($buffer, "\r\n", true), 3);
-        if (!in_array($firstLine[0], ['GET', 'POST', 'OPTIONS', 'HEAD', 'DELETE', 'PUT', 'PATCH'])) {
-            $connection->close("HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n", true);
-            return 0;
-        }
-        $header = substr($buffer, 0, $crlfPos);
-        if (!str_contains($header, "\r\nHost: ") && $firstLine[2] === "HTTP/1.1") {
+        $method = strstr($buffer, ' ', true);
+        if (!in_array($method, ['GET', 'POST', 'OPTIONS', 'HEAD', 'DELETE', 'PUT', 'PATCH'])) {
             $connection->close("HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n", true);
             return 0;
         }
 
-        if ($pos = stripos($header, "\r\nContent-Length: ")) {
+        $header = substr($buffer, 0, $crlfPos);
+        if ($pos = strpos($header, "\r\nContent-Length: ")) {
             $length += (int)substr($header, $pos + 18, 10);
             $hasContentLength = true;
         } else if (preg_match("/\r\ncontent-length: ?(\d+)/i", $header, $match)) {
@@ -119,10 +115,10 @@ class Http
             $connection->close("HTTP/1.1 413 Payload Too Large\r\n\r\n", true);
             return 0;
         }
-
         return $length;
     }
 
+
     /**
      * Http decode.
      *
@@ -132,7 +128,22 @@ class Http
      */
     public static function decode(string $buffer, TcpConnection $connection): Request
     {
+        static $requests = [];
+        if (isset($requests[$buffer])) {
+            $request = $requests[$buffer];
+            $request->connection = $connection;
+            $connection->request = $request;
+            $request->properties = [];
+            return $request;
+        }
         $request = new static::$requestClass($buffer);
+        if (!isset($buffer[TcpConnection::MAX_CACHE_STRING_LENGTH])) {
+            $requests[$buffer] = $request;
+            if (\count($requests) > TcpConnection::MAX_CACHE_SIZE) {
+                unset($requests[key($requests)]);
+            }
+            $request = clone $request;
+        }
         $request->connection = $connection;
         $connection->request = $request;
         return $request;
@@ -154,21 +165,24 @@ class Http
 
         if (!is_object($response)) {
             $extHeader = '';
-            if ($connection->headers) {
-                foreach ($connection->headers as $name => $value) {
-                    if (is_array($value)) {
-                        foreach ($value as $item) {
-                            $extHeader .= "$name: $item\r\n";
-                        }
-                    } else {
-                        $extHeader .= "$name: $value\r\n";
+            $contentType = 'text/html;charset=utf-8';
+            foreach ($connection->headers as $name => $value) {
+                if ($name === 'Content-Type') {
+                    $contentType = $value;
+                    continue;
+                }
+                if (is_array($value)) {
+                    foreach ($value as $item) {
+                        $extHeader .= "$name: $item\r\n";
                     }
+                } else {
+                    $extHeader .= "$name: $value\r\n";
                 }
-                $connection->headers = [];
             }
+            $connection->headers = [];
             $response = (string)$response;
             $bodyLen = strlen($response);
-            return "HTTP/1.1 200 OK\r\nServer: workerman\r\n{$extHeader}Connection: keep-alive\r\nContent-Type: text/html;charset=utf-8\r\nContent-Length: $bodyLen\r\n\r\n$response";
+            return "HTTP/1.1 200 OK\r\nServer: workerman\r\n{$extHeader}Connection: keep-alive\r\nContent-Type: $contentType\r\nContent-Length: $bodyLen\r\n\r\n$response";
         }
 
         if ($connection->headers) {

+ 0 - 56
src/Protocols/Http/Request.php

@@ -107,13 +107,6 @@ class Request implements Stringable
     protected bool $isSafe = true;
 
     /**
-     * Is dirty.
-     *
-     * @var bool
-     */
-    protected bool $isDirty = false;
-
-    /**
      * Session id.
      *
      * @var mixed
@@ -145,19 +138,6 @@ class Request implements Stringable
     }
 
     /**
-     * Set get.
-     *
-     * @param array $get
-     * @return Request
-     */
-    public function setGet(array $get): Request
-    {
-        $this->isDirty = true;
-        $this->data['get'] = $get;
-        return $this;
-    }
-
-    /**
      * Get post.
      *
      * @param string|null $name
@@ -176,19 +156,6 @@ class Request implements Stringable
     }
 
     /**
-     * Set post.
-     *
-     * @param array $post
-     * @return Request
-     */
-    public function setPost(array $post): Request
-    {
-        $this->isDirty = true;
-        $this->data['post'] = $post;
-        return $this;
-    }
-
-    /**
      * Get header item by name.
      *
      * @param string|null $name
@@ -208,18 +175,6 @@ class Request implements Stringable
     }
 
     /**
-     * Set headers.
-     * @param array $headers
-     * @return $this
-     */
-    public function setHeaders(array $headers): Request
-    {
-        $this->isDirty = true;
-        $this->data['headers'] = $headers;
-        return $this;
-    }
-
-    /**
      * Get cookie item by name.
      *
      * @param string|null $name
@@ -799,15 +754,4 @@ class Request implements Stringable
         }
     }
 
-    /**
-     * @return void
-     */
-    public function __clone()
-    {
-        $this->properties = [];
-        if ($this->isDirty) {
-            unset($this->data['get'], $this->data['post'], $this->data['headers']);
-        }
-    }
-
 }

+ 3 - 3
src/Protocols/ProtocolInterface.php

@@ -27,13 +27,13 @@ interface ProtocolInterface
      * Check the integrity of the package.
      * Please return the length of package.
      * If length is unknown please return 0 that means waiting for more data.
-     * If the package has something wrong please return false the connection will be closed.
+     * If the package has something wrong please return -1 the connection will be closed.
      *
      * @param string $buffer
      * @param ConnectionInterface $connection
-     * @return int|false
+     * @return int
      */
-    public static function input(string $buffer, ConnectionInterface $connection): bool|int;
+    public static function input(string $buffer, ConnectionInterface $connection): int;
 
     /**
      * Decode package and emit onMessage($message) callback, $message is the result that decode returned.

+ 3 - 3
src/Protocols/Ws.php

@@ -61,13 +61,13 @@ class Ws
      *
      * @param string $buffer
      * @param AsyncTcpConnection $connection
-     * @return int|false
+     * @return int
      */
-    public static function input(string $buffer, AsyncTcpConnection $connection): bool|int
+    public static function input(string $buffer, AsyncTcpConnection $connection): int
     {
         if (empty($connection->context->handshakeStep)) {
             Worker::safeEcho("recv data before handshake. Buffer:" . bin2hex($buffer) . "\n");
-            return false;
+            return -1;
         }
         // Recv handshake response
         if ($connection->context->handshakeStep === 1) {

+ 0 - 6
tests/Unit/Protocols/HttpTest.php

@@ -40,12 +40,6 @@ it('tests ::input', function () {
             ->toBe(0);
     }, '400 Bad Request');
 
-    //HTTP 1.1 without Host header
-    testWithConnectionClose(function (TcpConnection $tcpConnection) use ($buffer) {
-        expect(Http::input(str_replace("Host: ", 'NotHost: ', $buffer), $tcpConnection))
-            ->toBe(0);
-    }, '400 Bad Request');
-
     //content-length exceeds connection max package size
     testWithConnectionClose(function (TcpConnection $tcpConnection) use ($buffer) {
         $tcpConnection->maxPackageSize = 10;