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];