From 7b2b6897e5d4bfce1e38032a48b6deacd91d21d2 Mon Sep 17 00:00:00 2001 From: Chris Boden Date: Sun, 14 Apr 2013 18:22:35 -0400 Subject: [PATCH] HTTP Decouple spike --- src/Ratchet/Http/HttpServer.php | 99 ++++++++++++++++++++++++ src/Ratchet/Http/HttpServerInterface.php | 14 ++++ src/Ratchet/WebSocket/WsServer.php | 48 ++++++------ 3 files changed, 138 insertions(+), 23 deletions(-) create mode 100644 src/Ratchet/Http/HttpServer.php create mode 100644 src/Ratchet/Http/HttpServerInterface.php diff --git a/src/Ratchet/Http/HttpServer.php b/src/Ratchet/Http/HttpServer.php new file mode 100644 index 0000000..3af5aed --- /dev/null +++ b/src/Ratchet/Http/HttpServer.php @@ -0,0 +1,99 @@ +_decorating = $component; + $this->_reqParser = new HttpRequestParser; + } + + /** + * @{inheritdoc} + */ + public function onOpen(ConnectionInterface $conn) { + $conn->Http = new \StdClass; + $conn->Http->headers = false; + } + + /** + * @{inheritdoc} + */ + public function onMessage(ConnectionInterface $from, $msg) { + if (true !== $from->Http->headers) { + try { + if (null === ($request = $this->_reqParser->onMessage($from, $msg))) { + return; + } + } catch (\OverflowException $oe) { + return $this->close($from, 413); + } + + // check routes, return 404 or onOpen the route + + $from->Http->headers = true; + $from->Http->request = $request; + + return $this->_decorating->onOpen($from, $request); + } + + $this->_decorating->onMessage($from, $msg); + } + + /** + * @{inheritdoc} + */ + public function onClose(ConnectionInterface $conn) { + if ($conn->Http->headers) { + $this->_decorating->onClose($conn); + } + } + + /** + * @{inheritdoc} + */ + public function onError(ConnectionInterface $conn, \Exception $e) { + if ($conn->Http->headers) { + $this->_decorating->onError($conn, $e); + } else { + $conn->close(); + } + } + + /** + * Close a connection with an HTTP response + * @param \Ratchet\ConnectionInterface $conn + * @param int $code HTTP status code + * @return void + */ + protected function close(ConnectionInterface $conn, $code = 400) { + $response = new Response($code, array( + 'X-Powered-By' => \Ratchet\VERSION + )); + + $conn->send((string)$response); + $conn->close(); + } +} diff --git a/src/Ratchet/Http/HttpServerInterface.php b/src/Ratchet/Http/HttpServerInterface.php new file mode 100644 index 0000000..2f62238 --- /dev/null +++ b/src/Ratchet/Http/HttpServerInterface.php @@ -0,0 +1,14 @@ +WebSocket = new \StdClass; + public function onOpen(ConnectionInterface $conn, RequestInterface $headers = null) { + $conn->WebSocket = new \StdClass; + $conn->WebSocket->request = $headers; $conn->WebSocket->established = false; + + $this->attemptUpgrade($conn); } /** @@ -92,46 +98,42 @@ class WsServer implements MessageComponentInterface { return $from->WebSocket->version->onMessage($this->connections[$from], $msg); } - if (isset($from->WebSocket->request)) { - $from->WebSocket->request->getBody()->write($msg); + $this->attemptUpgrade($from, $msg); + } + + protected function attemptUpgrade(ConnectionInterface $conn, $data = '') { + if ('' !== $data) { + $conn->WebSocket->request->getBody()->write($data); } else { - try { - if (null === ($request = $this->reqParser->onMessage($from, $msg))) { - return; - } - } catch (\OverflowException $oe) { - return $this->close($from, 413); + if (!$this->versioner->isVersionEnabled($conn->WebSocket->request)) { + return $this->close($conn); } - if (!$this->versioner->isVersionEnabled($request)) { - return $this->close($from); - } - - $from->WebSocket->request = $request; - $from->WebSocket->version = $this->versioner->getVersion($request); + $conn->WebSocket->request = $conn->WebSocket->request; + $conn->WebSocket->version = $this->versioner->getVersion($conn->WebSocket->request); } try { - $response = $from->WebSocket->version->handshake($from->WebSocket->request); + $response = $conn->WebSocket->version->handshake($conn->WebSocket->request); } catch (\UnderflowException $e) { return; } // This needs to be refactored later on, incorporated with routing - if ('' !== ($agreedSubProtocols = $this->getSubProtocolString($from->WebSocket->request->getTokenizedHeader('Sec-WebSocket-Protocol', ',')))) { + if ('' !== ($agreedSubProtocols = $this->getSubProtocolString($conn->WebSocket->request->getTokenizedHeader('Sec-WebSocket-Protocol', ',')))) { $response->setHeader('Sec-WebSocket-Protocol', $agreedSubProtocols); } $response->setHeader('X-Powered-By', \Ratchet\VERSION); - $from->send((string)$response); + $conn->send((string)$response); if (101 != $response->getStatusCode()) { - return $from->close(); + return $conn->close(); } - $upgraded = $from->WebSocket->version->upgradeConnection($from, $this->_decorating); + $upgraded = $conn->WebSocket->version->upgradeConnection($conn, $this->_decorating); - $this->connections->attach($from, $upgraded); + $this->connections->attach($conn, $upgraded); $upgraded->WebSocket->established = true;