From 67267bfd946f04be446aa8c7e9af7184942d118d Mon Sep 17 00:00:00 2001 From: Chris Boden <cboden@gmail.com> Date: Sat, 7 Jan 2012 01:20:34 -0500 Subject: [PATCH] Cleanup Using native Guzzle object in Hixie handshake instead of hack being done in App. Thanks to @mtdowling for the lead. --- lib/Ratchet/Application/WebSocket/App.php | 23 +++------- .../Guzzle/Http/Message/RequestFactory.php | 43 +++++++++++++++++++ .../Application/WebSocket/Version/Hixie76.php | 5 +-- 3 files changed, 51 insertions(+), 20 deletions(-) create mode 100644 lib/Ratchet/Application/WebSocket/Guzzle/Http/Message/RequestFactory.php diff --git a/lib/Ratchet/Application/WebSocket/App.php b/lib/Ratchet/Application/WebSocket/App.php index edda0ef..d56a6a8 100644 --- a/lib/Ratchet/Application/WebSocket/App.php +++ b/lib/Ratchet/Application/WebSocket/App.php @@ -7,7 +7,7 @@ use Ratchet\Resource\Command\Factory; use Ratchet\Resource\Command\CommandInterface; use Ratchet\Resource\Command\Action\SendMessage; use Guzzle\Http\Message\RequestInterface; -use Guzzle\Http\Message\RequestFactory; +use Ratchet\Application\WebSocket\Guzzle\Http\Message\RequestFactory; /** * The adapter to handle WebSocket requests/responses @@ -18,8 +18,6 @@ use Guzzle\Http\Message\RequestFactory; * @todo Consider chaning this class to a State Pattern. If a WS App interface is passed use different state for additional methods used */ class App implements ApplicationInterface, ConfiguratorInterface { - const CRLF = "\r\n\r\n"; - /** * Decorated application * @var Ratchet\Application\ApplicationInterface @@ -88,8 +86,7 @@ class App implements ApplicationInterface, ConfiguratorInterface { return; } - $headers = RequestFactory::fromMessage($from->WebSocket->headers); - $headers->setHeader('X-Body', $this->getBody($from->WebSocket->headers)); + $headers = RequestFactory::fromRequest($from->WebSocket->headers); $from->WebSocket->version = $this->getVersion($headers); $from->WebSocket->headers = $headers; } @@ -242,14 +239,16 @@ class App implements ApplicationInterface, ConfiguratorInterface { * @todo Abstract, some hard coding done for (stupid) Hixie protocol */ protected function isMessageComplete($message) { - $headers = (boolean)strstr($message, static::CRLF); + static $crlf = "\r\n\r\n"; + + $headers = (boolean)strstr($message, $crlf); if (!$headers) { return false; } if (strstr($message, 'Sec-WebSocket-Key2')) { - if (8 !== strlen($this->getBody($message))) { + if (8 !== strlen(substr($message, strpos($message, $crlf) + strlen($crlf)))) { return false; } } @@ -257,16 +256,6 @@ class App implements ApplicationInterface, ConfiguratorInterface { return true; } - /** - * @param string - * @return string - * @deprecated - * @todo Remove soon, this is a temp hack for Hixie - */ - protected function getBody($message) { - return substr($message, strpos($message, static::CRLF) + strlen(static::CRLF)); - } - /** * Disable a version of the WebSocket protocol *cough*Hixie76*cough* * @param string The name of the version to disable diff --git a/lib/Ratchet/Application/WebSocket/Guzzle/Http/Message/RequestFactory.php b/lib/Ratchet/Application/WebSocket/Guzzle/Http/Message/RequestFactory.php new file mode 100644 index 0000000..5184ce0 --- /dev/null +++ b/lib/Ratchet/Application/WebSocket/Guzzle/Http/Message/RequestFactory.php @@ -0,0 +1,43 @@ +<?php +namespace Ratchet\Application\WebSocket\Guzzle\Http\Message; +use Guzzle\Http\Message\RequestFactory as gReqFac; +use Guzzle\Http\Url; + +/** + * Just slighly changing the Guzzle fromMessage() method to always return an EntityEnclosingRequest instance instead of Request + */ +class RequestFactory extends gReqFac { + /** + * @param string + * @return Guzzle\Http\Message\RequestInterface + */ + public static function fromRequest($message) { + $parsed = static::parseMessage($message); + + if (!$parsed) { + return false; + } + + return self::fromRequestParts( + $parsed['method'], + $parsed['parts'], + $parsed['headers'], + $parsed['body'], + $parsed['protocol'], + $parsed['protocol_version'] + ); + } + + protected static function fromRequestParts($method, array $parts, $headers = null, $body = null, $protocol = 'HTTP', $protocolVersion = '1.1') { + return self::requestCreate($method, Url::buildUrl($parts, true), $headers, $body) + ->setProtocolVersion($protocolVersion); + } + + protected static function requestCreate($method, $url, $headers = null, $body = null) { + $c = static::$entityEnclosingRequestClass; + $request = new $c($method, $url, $headers); + $request->setBody($body); + + return $request; + } +} \ No newline at end of file diff --git a/lib/Ratchet/Application/WebSocket/Version/Hixie76.php b/lib/Ratchet/Application/WebSocket/Version/Hixie76.php index 7a04958..bea5578 100644 --- a/lib/Ratchet/Application/WebSocket/Version/Hixie76.php +++ b/lib/Ratchet/Application/WebSocket/Version/Hixie76.php @@ -22,11 +22,10 @@ class Hixie76 implements VersionInterface { /** * @param string * @return string + * @todo Unhack this mess...or wait for Hixie to die (HURRY UP APPLE) */ public function handshake(RequestInterface $request) { - $message = $request->getRawHeaders() . "\r\n\r\n" . $request->getHeader('X-Body'); - - $buffer = $message; + $buffer = $request->getRawHeaders() . "\r\n\r\n" . $request->getBody(); $resource = $host = $origin = $key1 = $key2 = $protocol = $code = $handshake = null; preg_match('#GET (.*?) HTTP#', $buffer, $match) && $resource = $match[1];