From 7b2b6897e5d4bfce1e38032a48b6deacd91d21d2 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sun, 14 Apr 2013 18:22:35 -0400
Subject: [PATCH 01/48] 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 @@
+<?php
+namespace Ratchet\Http;
+use Ratchet\MessageComponentInterface;
+use Ratchet\ConnectionInterface;
+
+// @todo This class will move to this namespace
+use Ratchet\WebSocket\HttpRequestParser;
+
+use Symfony\Component\Routing\RouteCollection;
+
+class HttpServer implements MessageComponentInterface {
+    /**
+     * Decorated component
+     * @var HttpServerInterface
+     */
+    protected $_decorating;
+
+    protected $_reqParser;
+
+    /**
+     * @var Symfony\Component\Routing\RouteCollection
+     */
+    protected $_routes;
+
+    /**
+     * @todo Change parameter from HttpServerInterface to RouteCollection
+     */
+    public function __construct(HttpServerInterface $component) {
+        $this->_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 @@
+<?php
+namespace Ratchet\Http;
+use Ratchet\MessageComponentInterface;
+use Ratchet\ConnectionInterface;
+use Guzzle\Http\Message\RequestInterface;
+
+interface HttpServerInterface extends MessageComponentInterface {
+    /**
+     * @param \Ratchet\ConnectionInterface          $conn
+     * @param \Guzzle\Http\Message\RequestInterface $headers null is default because PHP won't let me overload; don't pass null!!!
+     * @return mixed
+     */
+    public function onOpen(ConnectionInterface $conn, RequestInterface $headers = null);
+}
diff --git a/src/Ratchet/WebSocket/WsServer.php b/src/Ratchet/WebSocket/WsServer.php
index 281f16c..e766d1b 100644
--- a/src/Ratchet/WebSocket/WsServer.php
+++ b/src/Ratchet/WebSocket/WsServer.php
@@ -6,13 +6,16 @@ use Ratchet\WebSocket\Version;
 use Ratchet\WebSocket\Encoding\ToggleableValidator;
 use Guzzle\Http\Message\Response;
 
+use Guzzle\Http\Message\RequestInterface;
+use Ratchet\Http\HttpServerInterface;
+
 /**
  * The adapter to handle WebSocket requests/responses
  * This is a mediator between the Server and your application to handle real-time messaging through a web browser
  * @link http://ca.php.net/manual/en/ref.http.php
  * @link http://dev.w3.org/html5/websockets/
  */
-class WsServer implements MessageComponentInterface {
+class WsServer implements HttpServerInterface {
     /**
      * Buffers incoming HTTP requests returning a Guzzle Request when coalesced
      * @var HttpRequestParser
@@ -79,9 +82,12 @@ class WsServer implements MessageComponentInterface {
     /**
      * {@inheritdoc}
      */
-    public function onOpen(ConnectionInterface $conn) {
-        $conn->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;
 

From 423b5cc35528249d331f40f4802ca90b08bbf3e3 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sun, 14 Apr 2013 18:34:28 -0400
Subject: [PATCH 02/48] [Http] Refactor header parsing from WS to HTTP

---
 .../Guzzle/Http/Message/RequestFactory.php        |  2 +-
 .../{WebSocket => Http}/HttpRequestParser.php     |  4 ++--
 src/Ratchet/Http/HttpServer.php                   |  8 +++++---
 src/Ratchet/WebSocket/WsServer.php                | 15 +++------------
 4 files changed, 11 insertions(+), 18 deletions(-)
 rename src/Ratchet/{WebSocket => Http}/Guzzle/Http/Message/RequestFactory.php (89%)
 rename src/Ratchet/{WebSocket => Http}/HttpRequestParser.php (94%)

diff --git a/src/Ratchet/WebSocket/Guzzle/Http/Message/RequestFactory.php b/src/Ratchet/Http/Guzzle/Http/Message/RequestFactory.php
similarity index 89%
rename from src/Ratchet/WebSocket/Guzzle/Http/Message/RequestFactory.php
rename to src/Ratchet/Http/Guzzle/Http/Message/RequestFactory.php
index c1f6b45..0ebcc35 100644
--- a/src/Ratchet/WebSocket/Guzzle/Http/Message/RequestFactory.php
+++ b/src/Ratchet/Http/Guzzle/Http/Message/RequestFactory.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\WebSocket\Guzzle\Http\Message;
+namespace Ratchet\Http\Guzzle\Http\Message;
 use Guzzle\Http\Message\RequestFactory as GuzzleRequestFactory;
 use Guzzle\Http\EntityBody;
 
diff --git a/src/Ratchet/WebSocket/HttpRequestParser.php b/src/Ratchet/Http/HttpRequestParser.php
similarity index 94%
rename from src/Ratchet/WebSocket/HttpRequestParser.php
rename to src/Ratchet/Http/HttpRequestParser.php
index 0922ef7..c6296bc 100644
--- a/src/Ratchet/WebSocket/HttpRequestParser.php
+++ b/src/Ratchet/Http/HttpRequestParser.php
@@ -1,8 +1,8 @@
 <?php
-namespace Ratchet\WebSocket;
+namespace Ratchet\Http;
 use Ratchet\MessageInterface;
 use Ratchet\ConnectionInterface;
-use Ratchet\WebSocket\Guzzle\Http\Message\RequestFactory;
+use Ratchet\Http\Guzzle\Http\Message\RequestFactory;
 
 /**
  * This class receives streaming data from a client request
diff --git a/src/Ratchet/Http/HttpServer.php b/src/Ratchet/Http/HttpServer.php
index 3af5aed..ecac919 100644
--- a/src/Ratchet/Http/HttpServer.php
+++ b/src/Ratchet/Http/HttpServer.php
@@ -3,9 +3,6 @@ namespace Ratchet\Http;
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
 
-// @todo This class will move to this namespace
-use Ratchet\WebSocket\HttpRequestParser;
-
 use Symfony\Component\Routing\RouteCollection;
 
 class HttpServer implements MessageComponentInterface {
@@ -15,6 +12,11 @@ class HttpServer implements MessageComponentInterface {
      */
     protected $_decorating;
 
+    /**
+     * Buffers incoming HTTP requests returning a Guzzle Request when coalesced
+     * @var HttpRequestParser
+     * @note May not expose this in the future, may do through facade methods
+     */
     protected $_reqParser;
 
     /**
diff --git a/src/Ratchet/WebSocket/WsServer.php b/src/Ratchet/WebSocket/WsServer.php
index e766d1b..6329cf9 100644
--- a/src/Ratchet/WebSocket/WsServer.php
+++ b/src/Ratchet/WebSocket/WsServer.php
@@ -2,12 +2,11 @@
 namespace Ratchet\WebSocket;
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
+use Ratchet\Http\HttpServerInterface;
+use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\Response;
 use Ratchet\WebSocket\Version;
 use Ratchet\WebSocket\Encoding\ToggleableValidator;
-use Guzzle\Http\Message\Response;
-
-use Guzzle\Http\Message\RequestInterface;
-use Ratchet\Http\HttpServerInterface;
 
 /**
  * The adapter to handle WebSocket requests/responses
@@ -16,13 +15,6 @@ use Ratchet\Http\HttpServerInterface;
  * @link http://dev.w3.org/html5/websockets/
  */
 class WsServer implements HttpServerInterface {
-    /**
-     * Buffers incoming HTTP requests returning a Guzzle Request when coalesced
-     * @var HttpRequestParser
-     * @note May not expose this in the future, may do through facade methods
-     */
-    public $reqParser;
-
     /**
      * Manage the various WebSocket versions to support
      * @var VersionManager
@@ -65,7 +57,6 @@ class WsServer implements HttpServerInterface {
      * If you want to enable sub-protocols have your component implement WsServerInterface as well
      */
     public function __construct(MessageComponentInterface $component) {
-        $this->reqParser = new HttpRequestParser;
         $this->versioner = new VersionManager;
         $this->validator = new ToggleableValidator;
 

From 69afb3de1f26b1f80443387f12845b12fcb98cbb Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sun, 14 Apr 2013 18:42:30 -0400
Subject: [PATCH 03/48] [Http] Fixed broken unit tests

---
 .../Guzzle/Http/Message/RequestFactoryTest.php             | 4 ++--
 .../Tests/{WebSocket => Http}/HtpRequestParserTest.php     | 7 +++----
 tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php      | 5 +++--
 3 files changed, 8 insertions(+), 8 deletions(-)
 rename tests/Ratchet/Tests/{WebSocket => Http}/Guzzle/Http/Message/RequestFactoryTest.php (94%)
 rename tests/Ratchet/Tests/{WebSocket => Http}/HtpRequestParserTest.php (88%)

diff --git a/tests/Ratchet/Tests/WebSocket/Guzzle/Http/Message/RequestFactoryTest.php b/tests/Ratchet/Tests/Http/Guzzle/Http/Message/RequestFactoryTest.php
similarity index 94%
rename from tests/Ratchet/Tests/WebSocket/Guzzle/Http/Message/RequestFactoryTest.php
rename to tests/Ratchet/Tests/Http/Guzzle/Http/Message/RequestFactoryTest.php
index 01d5df0..cb67bf5 100644
--- a/tests/Ratchet/Tests/WebSocket/Guzzle/Http/Message/RequestFactoryTest.php
+++ b/tests/Ratchet/Tests/Http/Guzzle/Http/Message/RequestFactoryTest.php
@@ -1,6 +1,6 @@
 <?php
-namespace Ratchet\Tests\WebSocket\Guzzle\Http\Message;
-use Ratchet\WebSocket\Guzzle\Http\Message\RequestFactory;
+namespace Ratchet\Tests\Http\Guzzle\Http\Message;
+use Ratchet\Http\Guzzle\Http\Message\RequestFactory;
 
 /**
  * @covers Ratchet\WebSocket\Guzzle\Http\Message\RequestFactory
diff --git a/tests/Ratchet/Tests/WebSocket/HtpRequestParserTest.php b/tests/Ratchet/Tests/Http/HtpRequestParserTest.php
similarity index 88%
rename from tests/Ratchet/Tests/WebSocket/HtpRequestParserTest.php
rename to tests/Ratchet/Tests/Http/HtpRequestParserTest.php
index b3f1600..a32a6da 100644
--- a/tests/Ratchet/Tests/WebSocket/HtpRequestParserTest.php
+++ b/tests/Ratchet/Tests/Http/HtpRequestParserTest.php
@@ -1,7 +1,6 @@
 <?php
-namespace Ratchet\Tests\WebSocket;
-use Ratchet\WebSocket\HttpRequestParser;
-use Ratchet\Tests\Mock\Connection as ConnectionStub;
+namespace Ratchet\Tests\Http;
+use Ratchet\Http\HttpRequestParser;
 
 /**
  * @covers Ratchet\WebSocket\HttpRequestParser
@@ -32,7 +31,7 @@ class HttpRequestParserTest extends \PHPUnit_Framework_TestCase {
     }
 
     public function testBufferOverflowResponse() {
-        $conn = new ConnectionStub;
+        $conn = $this->getMock('\\Ratchet\\ConnectionInterface');
 
         $this->parser->maxSize = 20;
 
diff --git a/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php b/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php
index d31ce64..02d959d 100644
--- a/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php
+++ b/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php
@@ -1,6 +1,7 @@
 <?php
 namespace Ratchet\Tests\WebSocket\Version;
 use Ratchet\WebSocket\Version\Hixie76;
+use Ratchet\Http\HttpServer;
 use Ratchet\WebSocket\WsServer;
 
 /**
@@ -60,7 +61,7 @@ class Hixie76Test extends \PHPUnit_Framework_TestCase {
         $mockConn = $this->getMock('\\Ratchet\\ConnectionInterface');
         $mockApp = $this->getMock('\\Ratchet\\MessageComponentInterface');
 
-        $server = new WsServer($mockApp);
+        $server = new HttpServer(new WsServer($mockApp));
         $server->onOpen($mockConn);
         $mockApp->expects($this->exactly(0))->method('onOpen');
         $server->onMessage($mockConn, $headers);
@@ -73,7 +74,7 @@ class Hixie76Test extends \PHPUnit_Framework_TestCase {
         $mockConn = $this->getMock('\\Ratchet\\ConnectionInterface');
         $mockApp = $this->getMock('\\Ratchet\\MessageComponentInterface');
 
-        $server = new WsServer($mockApp);
+        $server = new HttpServer(new WsServer($mockApp));
         $server->onOpen($mockConn);
         $server->onMessage($mockConn, $headers);
 

From 7b5b215c44e5d9fc702850f7c7bd5d013b7d5e9b Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sun, 14 Apr 2013 19:47:25 -0400
Subject: [PATCH 04/48] Updated example to match decoupling

---
 README.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 5cd3fa9..32c96fd 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,7 @@ Need help?  Have a question?  Want to provide feedback?  Write a message on the
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
 use Ratchet\Server\IoServer;
+use Ratchet\Http\HttpServer;
 use Ratchet\WebSocket\WsServer;
 
     require __DIR__ . '/vendor/autoload.php';
@@ -76,7 +77,7 @@ class Chat implements MessageComponentInterface {
 }
 
     // Run the server application through the WebSocket protocol on port 8080
-    $server = IoServer::factory(new WsServer(new Chat), 8080);
+    $server = IoServer::factory(new HttpServer(new WsServer(new Chat)), 8080);
     $server->run();
 ```
 

From dc59a0a3c01019100b6a96ce2938eaa695609473 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Mon, 15 Apr 2013 20:48:32 -0400
Subject: [PATCH 05/48] Bump min version req to 5.3.9 to avoid Interface parse
 error

---
 .travis.yml   | 2 +-
 composer.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 6161d58..80698e0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,7 @@
 language: php
 
 php:
-  - 5.3.3
+  - 5.3.9
   - 5.3
   - 5.4
 
diff --git a/composer.json b/composer.json
index f83a0b0..364b9fe 100644
--- a/composer.json
+++ b/composer.json
@@ -25,7 +25,7 @@
         }
     }
   , "require": {
-        "php": ">=5.3.3"
+        "php": ">=5.3.9"
       , "react/socket": "0.2.*"
       , "guzzle/http": "~3.0"
       , "symfony/http-foundation": "~2.1"

From 18bc1144089cf886394f906b0f5f7c64363f6099 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Tue, 16 Apr 2013 22:37:15 -0400
Subject: [PATCH 06/48] [Http] Routing spike

---
 composer.json                   |   3 +-
 composer.lock                   | 135 +++++++++++++++++++++++---------
 src/Ratchet/Http/HttpServer.php |  53 +++++++++----
 3 files changed, 138 insertions(+), 53 deletions(-)

diff --git a/composer.json b/composer.json
index 364b9fe..a7a7953 100644
--- a/composer.json
+++ b/composer.json
@@ -28,6 +28,7 @@
         "php": ">=5.3.9"
       , "react/socket": "0.2.*"
       , "guzzle/http": "~3.0"
-      , "symfony/http-foundation": "~2.1"
+      , "symfony/http-foundation": "~2.2"
+      , "symfony/routing": "~2.2"
     }
 }
diff --git a/composer.lock b/composer.lock
index 9df5a60..882649e 100644
--- a/composer.lock
+++ b/composer.lock
@@ -1,5 +1,9 @@
 {
-    "hash": "9ccce99ef687cb79dad8a4c581f38cc5",
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
+    ],
+    "hash": "b51075c0a68acb956c32e59869790571",
     "packages": [
         {
             "name": "evenement/evenement",
@@ -42,17 +46,17 @@
         },
         {
             "name": "guzzle/common",
-            "version": "v3.3.0",
+            "version": "v3.4.1",
             "target-dir": "Guzzle/Common",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/common.git",
-                "reference": "v3.3.0"
+                "reference": "v3.4.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/common/zipball/v3.3.0",
-                "reference": "v3.3.0",
+                "url": "https://api.github.com/repos/guzzle/common/zipball/v3.4.1",
+                "reference": "v3.4.1",
                 "shasum": ""
             },
             "require": {
@@ -62,7 +66,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.0-dev"
+                    "dev-master": "3.3-dev"
                 }
             },
             "autoload": {
@@ -82,21 +86,21 @@
                 "event",
                 "exception"
             ],
-            "time": "2013-03-04 00:41:45"
+            "time": "2013-04-16 20:56:26"
         },
         {
             "name": "guzzle/http",
-            "version": "v3.3.0",
+            "version": "v3.4.1",
             "target-dir": "Guzzle/Http",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/http.git",
-                "reference": "v3.3.0"
+                "reference": "v3.4.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/http/zipball/v3.3.0",
-                "reference": "v3.3.0",
+                "url": "https://api.github.com/repos/guzzle/http/zipball/v3.4.1",
+                "reference": "v3.4.1",
                 "shasum": ""
             },
             "require": {
@@ -111,7 +115,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.0-dev"
+                    "dev-master": "3.3-dev"
                 }
             },
             "autoload": {
@@ -139,21 +143,21 @@
                 "http",
                 "http client"
             ],
-            "time": "2013-03-03 21:40:51"
+            "time": "2013-04-16 20:27:11"
         },
         {
             "name": "guzzle/parser",
-            "version": "v3.3.0",
+            "version": "v3.4.1",
             "target-dir": "Guzzle/Parser",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/parser.git",
-                "reference": "v3.3.0"
+                "reference": "v3.4.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/parser/zipball/v3.3.0",
-                "reference": "v3.3.0",
+                "url": "https://api.github.com/repos/guzzle/parser/zipball/v3.4.1",
+                "reference": "v3.4.1",
                 "shasum": ""
             },
             "require": {
@@ -162,7 +166,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.0-dev"
+                    "dev-master": "3.3-dev"
                 }
             },
             "autoload": {
@@ -183,31 +187,34 @@
                 "message",
                 "url"
             ],
-            "time": "2013-01-12 21:43:21"
+            "time": "2013-03-07 22:13:59"
         },
         {
             "name": "guzzle/stream",
-            "version": "v3.3.0",
+            "version": "v3.4.1",
             "target-dir": "Guzzle/Stream",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/stream.git",
-                "reference": "v3.3.0"
+                "reference": "v3.4.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/stream/zipball/v3.3.0",
-                "reference": "v3.3.0",
+                "url": "https://api.github.com/repos/guzzle/stream/zipball/v3.4.1",
+                "reference": "v3.4.1",
                 "shasum": ""
             },
             "require": {
                 "guzzle/common": "self.version",
                 "php": ">=5.3.2"
             },
+            "suggest": {
+                "guzzle/http": "To convert Guzzle request objects to PHP streams"
+            },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.0-dev"
+                    "dev-master": "3.3-dev"
                 }
             },
             "autoload": {
@@ -233,7 +240,7 @@
                 "component",
                 "stream"
             ],
-            "time": "2013-03-03 03:07:02"
+            "time": "2013-04-06 18:28:51"
         },
         {
             "name": "react/event-loop",
@@ -367,17 +374,17 @@
         },
         {
             "name": "symfony/event-dispatcher",
-            "version": "v2.2.0",
+            "version": "v2.2.1",
             "target-dir": "Symfony/Component/EventDispatcher",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/EventDispatcher.git",
-                "reference": "v2.2.0-RC3"
+                "reference": "v2.2.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.2.0-RC3",
-                "reference": "v2.2.0-RC3",
+                "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.2.1",
+                "reference": "v2.2.1",
                 "shasum": ""
             },
             "require": {
@@ -421,17 +428,17 @@
         },
         {
             "name": "symfony/http-foundation",
-            "version": "v2.2.0",
+            "version": "v2.2.1",
             "target-dir": "Symfony/Component/HttpFoundation",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/HttpFoundation.git",
-                "reference": "v2.2.0"
+                "reference": "v2.2.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/v2.2.0",
-                "reference": "v2.2.0",
+                "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/v2.2.1",
+                "reference": "v2.2.1",
                 "shasum": ""
             },
             "require": {
@@ -467,7 +474,65 @@
             ],
             "description": "Symfony HttpFoundation Component",
             "homepage": "http://symfony.com",
-            "time": "2013-02-26 09:42:13"
+            "time": "2013-04-06 10:15:43"
+        },
+        {
+            "name": "symfony/routing",
+            "version": "v2.2.1",
+            "target-dir": "Symfony/Component/Routing",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/Routing.git",
+                "reference": "v2.2.1"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/Routing/zipball/v2.2.1",
+                "reference": "v2.2.1",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "doctrine/common": ">=2.2,<3.0",
+                "psr/log": ">=1.0,<2.0",
+                "symfony/config": ">=2.2,<2.3-dev",
+                "symfony/yaml": ">=2.0,<3.0"
+            },
+            "suggest": {
+                "doctrine/common": "~2.2",
+                "symfony/config": "2.2.*",
+                "symfony/yaml": "2.2.*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.2-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Symfony\\Component\\Routing\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "http://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Routing Component",
+            "homepage": "http://symfony.com",
+            "time": "2013-03-23 12:03:22"
         }
     ],
     "packages-dev": [
@@ -481,7 +546,7 @@
 
     ],
     "platform": {
-        "php": ">=5.3.3"
+        "php": ">=5.3.9"
     },
     "platform-dev": [
 
diff --git a/src/Ratchet/Http/HttpServer.php b/src/Ratchet/Http/HttpServer.php
index ecac919..f1ba4dd 100644
--- a/src/Ratchet/Http/HttpServer.php
+++ b/src/Ratchet/Http/HttpServer.php
@@ -2,16 +2,15 @@
 namespace Ratchet\Http;
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
-
+use Guzzle\Http\Message\Response;
 use Symfony\Component\Routing\RouteCollection;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\Routing\RequestContext;
+use Symfony\Component\Routing\Matcher\UrlMatcher;
+use Symfony\Component\Routing\Exception\MethodNotAllowedException;
+use Symfony\Component\Routing\Exception\ResourceNotFoundException;
 
 class HttpServer implements MessageComponentInterface {
-    /**
-     * Decorated component
-     * @var HttpServerInterface
-     */
-    protected $_decorating;
-
     /**
      * Buffers incoming HTTP requests returning a Guzzle Request when coalesced
      * @var HttpRequestParser
@@ -24,14 +23,24 @@ class HttpServer implements MessageComponentInterface {
      */
     protected $_routes;
 
-    /**
-     * @todo Change parameter from HttpServerInterface to RouteCollection
-     */
-    public function __construct(HttpServerInterface $component) {
-        $this->_decorating = $component;
+    public function __construct() {
+        $this->_routes    = new RouteCollection;
         $this->_reqParser = new HttpRequestParser;
     }
 
+    /**
+     * @param string
+     * @param string
+     * @param Ratchet\Http\HttpServerInterface
+     * @param array
+     */
+    public function addRoute($name, $path, MessageComponentInterface $controller, $allowedOrigins = array()) {
+        $this->_routes->add($name, new Route($path, array(
+            '_controller' => $controller
+          , 'allowedOrigins' => $allowedOrigins
+        )));
+    }
+
     /**
      * @{inheritdoc}
      */
@@ -53,15 +62,25 @@ class HttpServer implements MessageComponentInterface {
                 return $this->close($from, 413);
             }
 
-            // check routes, return 404 or onOpen the route
+            $context = new RequestContext($request->getUrl(), $request->getMethod(), $request->getHost(), $request->getScheme(), $request->getPort());
+            $matcher = new UrlMatcher($this->_routes, $context);
 
-            $from->Http->headers = true;
-            $from->Http->request = $request;
+            try {
+                $route = $matcher->match($request->getPath());
+            } catch (MethodNotAllowedException $nae) {
+                return $this->close($from, 403);
+            } catch (ResourceNotFoundException $nfe) {
+                return $this->close($from, 404);
+            }
 
-            return $this->_decorating->onOpen($from, $request);
+            $from->Http->headers    = true;
+            $from->Http->request    = $request;
+            $from->Http->controller = $route['_controller'];
+
+            return $from->Http->controller->onOpen($from, $request);
         }
 
-        $this->_decorating->onMessage($from, $msg);
+        $from->Http->controller->onMessage($from, $msg);
     }
 
     /**

From ba76600214a06daf5a0e4daf1f95ec9e483d5ba3 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Fri, 19 Apr 2013 22:40:16 -0400
Subject: [PATCH 07/48] [Http] Fixed broken unit tests

---
 tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php b/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php
index 02d959d..05716c6 100644
--- a/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php
+++ b/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php
@@ -61,7 +61,8 @@ class Hixie76Test extends \PHPUnit_Framework_TestCase {
         $mockConn = $this->getMock('\\Ratchet\\ConnectionInterface');
         $mockApp = $this->getMock('\\Ratchet\\MessageComponentInterface');
 
-        $server = new HttpServer(new WsServer($mockApp));
+        $server = new HttpServer;
+        $server->addRoute('test', '/', new WsServer($mockApp));
         $server->onOpen($mockConn);
         $mockApp->expects($this->exactly(0))->method('onOpen');
         $server->onMessage($mockConn, $headers);
@@ -74,7 +75,8 @@ class Hixie76Test extends \PHPUnit_Framework_TestCase {
         $mockConn = $this->getMock('\\Ratchet\\ConnectionInterface');
         $mockApp = $this->getMock('\\Ratchet\\MessageComponentInterface');
 
-        $server = new HttpServer(new WsServer($mockApp));
+        $server = new HttpServer;
+        $server->addRoute('test', '/', new WsServer($mockApp));
         $server->onOpen($mockConn);
         $server->onMessage($mockConn, $headers);
 

From 67dbf46879182671448e81ab1c540627a1b9f7c8 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sat, 20 Apr 2013 16:16:47 -0400
Subject: [PATCH 08/48] [Http] Docs

---
 CHANGELOG.md | 5 +++++
 Makefile     | 1 +
 2 files changed, 6 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 13fb90f..f61291c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,11 @@ CHANGELOG
 
 ---
 
+* 0.3.0 (2013-xx-xx)
+
+ * BC: Added Routing to HTTP allowing for a single Ratchet server to handle multiple apps
+ * BC: Decoupled HTTP from WebSocket component
+
 * 0.2.5 (2013-04-01)
 
  * Fixed Hixie-76 handshake bug
diff --git a/Makefile b/Makefile
index a1b8a5b..d5e12a2 100644
--- a/Makefile
+++ b/Makefile
@@ -32,4 +32,5 @@ apidocs:
 		-s vendor/react \
 		-s vendor/guzzle \
 		-s vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Session \
+		-s vendor/symfony/http-foundation/Symfony/Component/Routing \
 		-s vendor/evenement/evenement/src/Evenement

From 43003d69f93cd6891743448722be02314f374fbd Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Fri, 26 Apr 2013 19:19:47 -0400
Subject: [PATCH 09/48] [Http] Only pass Request, don't store (twice)

---
 src/Ratchet/Http/HttpServer.php | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/Ratchet/Http/HttpServer.php b/src/Ratchet/Http/HttpServer.php
index f1ba4dd..b72fd98 100644
--- a/src/Ratchet/Http/HttpServer.php
+++ b/src/Ratchet/Http/HttpServer.php
@@ -74,7 +74,6 @@ class HttpServer implements MessageComponentInterface {
             }
 
             $from->Http->headers    = true;
-            $from->Http->request    = $request;
             $from->Http->controller = $route['_controller'];
 
             return $from->Http->controller->onOpen($from, $request);

From 4a87375f1019f6d1434155d20d45ba17d8bb9ea5 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Fri, 26 Apr 2013 20:00:11 -0400
Subject: [PATCH 10/48] [Http] HttpServerInterface

Force HttpServerInterface on route
Call controller on all events
---
 src/Ratchet/Http/HttpServer.php | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/Ratchet/Http/HttpServer.php b/src/Ratchet/Http/HttpServer.php
index b72fd98..9d306e7 100644
--- a/src/Ratchet/Http/HttpServer.php
+++ b/src/Ratchet/Http/HttpServer.php
@@ -34,9 +34,9 @@ class HttpServer implements MessageComponentInterface {
      * @param Ratchet\Http\HttpServerInterface
      * @param array
      */
-    public function addRoute($name, $path, MessageComponentInterface $controller, $allowedOrigins = array()) {
+    public function addRoute($name, $path, HttpServerInterface $controller, $allowedOrigins = array()) {
         $this->_routes->add($name, new Route($path, array(
-            '_controller' => $controller
+            '_controller'    => $controller
           , 'allowedOrigins' => $allowedOrigins
         )));
     }
@@ -87,7 +87,7 @@ class HttpServer implements MessageComponentInterface {
      */
     public function onClose(ConnectionInterface $conn) {
         if ($conn->Http->headers) {
-            $this->_decorating->onClose($conn);
+            $conn->Http->controller->onClose($conn);
         }
     }
 
@@ -96,7 +96,7 @@ class HttpServer implements MessageComponentInterface {
      */
     public function onError(ConnectionInterface $conn, \Exception $e) {
         if ($conn->Http->headers) {
-            $this->_decorating->onError($conn, $e);
+            $conn->Http->controller->onError($conn, $e);
         } else {
             $conn->close();
         }

From c24cdf379e01fe5fd06173057b772c0ee24319ce Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Fri, 26 Apr 2013 21:06:34 -0400
Subject: [PATCH 11/48] [Http] Accept RouteCollection, spike CORS protection

---
 CHANGELOG.md                                  |  1 +
 src/Ratchet/Http/HttpServer.php               | 32 +++++++++++++++----
 .../Tests/WebSocket/Version/Hixie76Test.php   |  4 ++-
 3 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f61291c..a59cc7c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ CHANGELOG
 
 * 0.3.0 (2013-xx-xx)
 
+ * BC: Requre hostname and do Origin HTTP header check against it, disabling CORS by default for security reasons
  * BC: Added Routing to HTTP allowing for a single Ratchet server to handle multiple apps
  * BC: Decoupled HTTP from WebSocket component
 
diff --git a/src/Ratchet/Http/HttpServer.php b/src/Ratchet/Http/HttpServer.php
index 9d306e7..a6d2d5e 100644
--- a/src/Ratchet/Http/HttpServer.php
+++ b/src/Ratchet/Http/HttpServer.php
@@ -19,12 +19,33 @@ class HttpServer implements MessageComponentInterface {
     protected $_reqParser;
 
     /**
-     * @var Symfony\Component\Routing\RouteCollection
+     * @var \Symfony\Component\Routing\RouteCollection A collection with \Ratchet\MessageComponentInterface controllers
      */
     protected $_routes;
 
-    public function __construct() {
-        $this->_routes    = new RouteCollection;
+    /**
+     * @param string          $host
+     * @param RouteCollection $collection
+     * @throws \UnexpectedValueException If a Route Controller does not map to a \Ratchet\MessageComponentInterface
+     */
+    public function __construct($host, RouteCollection $collection = null) {
+        if (null === $collection) {
+            $collection = new RouteCollection;
+        } else {
+            foreach ($collection as $routeName => $route) {
+                if (is_string($route['_controller']) && class_exists($route['_controller'])) {
+                    $route['_controller'] = new $route['_controller'];
+                }
+
+                if (!($route['_controller'] instanceof HttpServerInterface)) {
+                    throw new \UnexpectedValueException('All routes must implement Ratchet\MessageComponentInterface');
+                }
+            }
+        }
+
+        $collection->setHost($host);
+
+        $this->_routes    = $collection;
         $this->_reqParser = new HttpRequestParser;
     }
 
@@ -34,10 +55,9 @@ class HttpServer implements MessageComponentInterface {
      * @param Ratchet\Http\HttpServerInterface
      * @param array
      */
-    public function addRoute($name, $path, HttpServerInterface $controller, $allowedOrigins = array()) {
+    public function addRoute($name, $path, HttpServerInterface $controller) {
         $this->_routes->add($name, new Route($path, array(
-            '_controller'    => $controller
-          , 'allowedOrigins' => $allowedOrigins
+            '_controller' => $controller
         )));
     }
 
diff --git a/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php b/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php
index 05716c6..2e80307 100644
--- a/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php
+++ b/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php
@@ -44,7 +44,7 @@ class Hixie76Test extends \PHPUnit_Framework_TestCase {
         $headers  = "GET / HTTP/1.1";
         $headers .= "Upgrade: WebSocket{$this->_crlf}";
         $headers .= "Connection: Upgrade{$this->_crlf}";
-        $headers .= "Host: home.chrisboden.ca{$this->_crlf}";
+        $headers .= "Host: socketo.me{$this->_crlf}";
         $headers .= "Origin: http://fiddle.jshell.net{$this->_crlf}";
         $headers .= "Sec-WebSocket-Key1:17 Z4< F94 N3  7P41  7{$this->_crlf}";
         $headers .= "Sec-WebSocket-Key2:1 23C3:,2% 1-29  4 f0{$this->_crlf}";
@@ -54,6 +54,7 @@ class Hixie76Test extends \PHPUnit_Framework_TestCase {
         return $headers;
     }
 
+/* @todo Re-enable and fix these tests later - bad functional tests atm, break into units
     public function testNoUpgradeBeforeBody() {
         $headers = $this->headerProvider();
         $body    = base64_decode($this->_body);
@@ -83,4 +84,5 @@ class Hixie76Test extends \PHPUnit_Framework_TestCase {
         $mockApp->expects($this->once())->method('onOpen');
         $server->onMessage($mockConn, $body . $this->_crlf . $this->_crlf);
     }
+*/
 }
\ No newline at end of file

From 4df71c3a359af3bf756834dae23f7626337872f6 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Fri, 26 Apr 2013 23:01:28 -0400
Subject: [PATCH 12/48] [Http] ROUTING BABY

Decoupled routing from HTTP
Added Router implement HttpServerInterface
Fully functional Symfony routes in application!
As a result, this drastically decreased backwards compatibility breaks while introducing new functionality
---
 CHANGELOG.md                             |  4 +-
 README.md                                | 13 +++-
 src/Ratchet/Http/HttpServer.php          | 75 +++++-------------------
 src/Ratchet/Http/HttpServerInterface.php |  5 +-
 src/Ratchet/Http/Router.php              | 61 +++++++++++++++++++
 src/Ratchet/WebSocket/WsServer.php       |  4 +-
 6 files changed, 95 insertions(+), 67 deletions(-)
 create mode 100644 src/Ratchet/Http/Router.php

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a59cc7c..e0771e2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,8 +10,8 @@ CHANGELOG
 
 * 0.3.0 (2013-xx-xx)
 
- * BC: Requre hostname and do Origin HTTP header check against it, disabling CORS by default for security reasons
- * BC: Added Routing to HTTP allowing for a single Ratchet server to handle multiple apps
+ * BC: Require hostname and do Origin HTTP header check against it by default, helping prevent CSRF attacks
+ * Added HTTP Router component to allowing for a single Ratchet server to handle multiple apps
  * BC: Decoupled HTTP from WebSocket component
 
 * 0.2.5 (2013-04-01)
diff --git a/README.md b/README.md
index 32c96fd..e089404 100644
--- a/README.md
+++ b/README.md
@@ -38,9 +38,15 @@ Need help?  Have a question?  Want to provide feedback?  Write a message on the
 <?php
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
+
 use Ratchet\Server\IoServer;
 use Ratchet\Http\HttpServer;
+use Ratchet\Http\Router;
 use Ratchet\WebSocket\WsServer;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\Routing\Matcher\UrlMatcher;
+use Symfony\Component\Routing\RouteCollection;
+use Symfony\Component\Routing\RequestContext;
 
     require __DIR__ . '/vendor/autoload.php';
 
@@ -77,7 +83,12 @@ class Chat implements MessageComponentInterface {
 }
 
     // Run the server application through the WebSocket protocol on port 8080
-    $server = IoServer::factory(new HttpServer(new WsServer(new Chat)), 8080);
+    // This will be made easier soon, routing currently in development
+    $routes->add('chatRoute', new Route('/chat', array(
+        '_controller' => new WsServer(new Chat)
+    )));
+
+    $server = IoServer::factory(new HttpServer(new Router(new UrlMatcher($routes, new RequestContext))), 8080);
     $server->run();
 ```
 
diff --git a/src/Ratchet/Http/HttpServer.php b/src/Ratchet/Http/HttpServer.php
index a6d2d5e..867d008 100644
--- a/src/Ratchet/Http/HttpServer.php
+++ b/src/Ratchet/Http/HttpServer.php
@@ -19,61 +19,30 @@ class HttpServer implements MessageComponentInterface {
     protected $_reqParser;
 
     /**
-     * @var \Symfony\Component\Routing\RouteCollection A collection with \Ratchet\MessageComponentInterface controllers
+     * @var \Ratchet\Http\HttpServerInterface
      */
-    protected $_routes;
+    protected $_httpServer;
 
     /**
-     * @param string          $host
-     * @param RouteCollection $collection
-     * @throws \UnexpectedValueException If a Route Controller does not map to a \Ratchet\MessageComponentInterface
+     * @param HttpServerInterface
      */
-    public function __construct($host, RouteCollection $collection = null) {
-        if (null === $collection) {
-            $collection = new RouteCollection;
-        } else {
-            foreach ($collection as $routeName => $route) {
-                if (is_string($route['_controller']) && class_exists($route['_controller'])) {
-                    $route['_controller'] = new $route['_controller'];
-                }
-
-                if (!($route['_controller'] instanceof HttpServerInterface)) {
-                    throw new \UnexpectedValueException('All routes must implement Ratchet\MessageComponentInterface');
-                }
-            }
-        }
-
-        $collection->setHost($host);
-
-        $this->_routes    = $collection;
-        $this->_reqParser = new HttpRequestParser;
-    }
-
-    /**
-     * @param string
-     * @param string
-     * @param Ratchet\Http\HttpServerInterface
-     * @param array
-     */
-    public function addRoute($name, $path, HttpServerInterface $controller) {
-        $this->_routes->add($name, new Route($path, array(
-            '_controller' => $controller
-        )));
+    public function __construct(HttpServerInterface $server) {
+        $this->_httpServer = $server;
+        $this->_reqParser  = new HttpRequestParser;
     }
 
     /**
      * @{inheritdoc}
      */
     public function onOpen(ConnectionInterface $conn) {
-        $conn->Http = new \StdClass;
-        $conn->Http->headers = false;
+        $conn->httpHeadersReceived = false;
     }
 
     /**
      * @{inheritdoc}
      */
     public function onMessage(ConnectionInterface $from, $msg) {
-        if (true !== $from->Http->headers) {
+        if (true !== $from->httpHeadersReceived) {
             try {
                 if (null === ($request = $this->_reqParser->onMessage($from, $msg))) {
                     return;
@@ -82,32 +51,20 @@ class HttpServer implements MessageComponentInterface {
                 return $this->close($from, 413);
             }
 
-            $context = new RequestContext($request->getUrl(), $request->getMethod(), $request->getHost(), $request->getScheme(), $request->getPort());
-            $matcher = new UrlMatcher($this->_routes, $context);
+            $from->httpHeadersReceived = true;
 
-            try {
-                $route = $matcher->match($request->getPath());
-            } catch (MethodNotAllowedException $nae) {
-                return $this->close($from, 403);
-            } catch (ResourceNotFoundException $nfe) {
-                return $this->close($from, 404);
-            }
-
-            $from->Http->headers    = true;
-            $from->Http->controller = $route['_controller'];
-
-            return $from->Http->controller->onOpen($from, $request);
+            return $this->_httpServer->onOpen($from, $request);
         }
 
-        $from->Http->controller->onMessage($from, $msg);
+        $this->_httpServer->onMessage($from, $msg);
     }
 
     /**
      * @{inheritdoc}
      */
     public function onClose(ConnectionInterface $conn) {
-        if ($conn->Http->headers) {
-            $conn->Http->controller->onClose($conn);
+        if ($conn->httpHeadersReceived) {
+            $this->_httpServer->onClose($conn);
         }
     }
 
@@ -115,10 +72,10 @@ class HttpServer implements MessageComponentInterface {
      * @{inheritdoc}
      */
     public function onError(ConnectionInterface $conn, \Exception $e) {
-        if ($conn->Http->headers) {
-            $conn->Http->controller->onError($conn, $e);
+        if ($conn->httpHeadersReceived) {
+            $this->_httpServer->onError($conn, $e);
         } else {
-            $conn->close();
+            $this->close($conn, 500);
         }
     }
 
diff --git a/src/Ratchet/Http/HttpServerInterface.php b/src/Ratchet/Http/HttpServerInterface.php
index 2f62238..0730680 100644
--- a/src/Ratchet/Http/HttpServerInterface.php
+++ b/src/Ratchet/Http/HttpServerInterface.php
@@ -7,8 +7,7 @@ use Guzzle\Http\Message\RequestInterface;
 interface HttpServerInterface extends MessageComponentInterface {
     /**
      * @param \Ratchet\ConnectionInterface          $conn
-     * @param \Guzzle\Http\Message\RequestInterface $headers null is default because PHP won't let me overload; don't pass null!!!
-     * @return mixed
+     * @param \Guzzle\Http\Message\RequestInterface $request null is default because PHP won't let me overload; don't pass null!!!
      */
-    public function onOpen(ConnectionInterface $conn, RequestInterface $headers = null);
+    public function onOpen(ConnectionInterface $conn, RequestInterface $request = null);
 }
diff --git a/src/Ratchet/Http/Router.php b/src/Ratchet/Http/Router.php
new file mode 100644
index 0000000..9946d7e
--- /dev/null
+++ b/src/Ratchet/Http/Router.php
@@ -0,0 +1,61 @@
+<?php
+namespace Ratchet\Http;
+use Ratchet\ConnectionInterface;
+use Guzzle\Http\Message\RequestInterface;
+use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
+use Symfony\Component\Routing\Exception\MethodNotAllowedException;
+use Symfony\Component\Routing\Exception\ResourceNotFoundException;
+
+class Router implements HttpServerInterface {
+    /**
+     * @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface
+     */
+    protected $_matcher;
+
+    public function __construct(UrlMatcherInterface $matcher) {
+        $this->_matcher = $matcher;
+    }
+
+    public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) {
+        try {
+            $route = $this->_matcher->match($request->getPath());
+        } catch (MethodNotAllowedException $nae) {
+            return $this->close($from, 403);
+        } catch (ResourceNotFoundException $nfe) {
+            return $this->close($from, 404);
+        }
+
+        if (is_string($route['_controller']) && class_exists($route['_controller'])) {
+            $route['_controller'] = new $route['_controller'];
+        }
+
+        if (!($route['_controller'] instanceof HttpServerInterface)) {
+            throw new \UnexpectedValueException('All routes must implement Ratchet\HttpServerInterface');
+        }
+
+        $conn->controller = $route['_controller'];
+
+        $conn->controller->onOpen($conn, $request);
+    }
+
+    /**
+     * @{inheritdoc}
+     */
+    function onMessage(ConnectionInterface $from, $msg) {
+        $from->controller->onMessage($from, $msg);
+    }
+
+    /**
+     * @{inheritdoc}
+     */
+    function onClose(ConnectionInterface $conn) {
+        $conn->controller->onClose($conn);
+    }
+
+    /**
+     * @{inheritdoc}
+     */
+    function onError(ConnectionInterface $conn, \Exception $e) {
+        $conn->controller->onError($conn, $e);
+    }
+}
\ No newline at end of file
diff --git a/src/Ratchet/WebSocket/WsServer.php b/src/Ratchet/WebSocket/WsServer.php
index 6329cf9..77e3fe1 100644
--- a/src/Ratchet/WebSocket/WsServer.php
+++ b/src/Ratchet/WebSocket/WsServer.php
@@ -73,9 +73,9 @@ class WsServer implements HttpServerInterface {
     /**
      * {@inheritdoc}
      */
-    public function onOpen(ConnectionInterface $conn, RequestInterface $headers = null) {
+    public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) {
         $conn->WebSocket              = new \StdClass;
-        $conn->WebSocket->request     = $headers;
+        $conn->WebSocket->request     = $request;
         $conn->WebSocket->established = false;
 
         $this->attemptUpgrade($conn);

From 26a760709f24c11e66658e0ef7dea3176f132e13 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sat, 27 Apr 2013 00:05:10 -0400
Subject: [PATCH 13/48] [Http] Facade class for routing

Not sure if it'll stick or not, but easier way to route for now
Refs #15
---
 README.md                             | 19 +++-----
 src/Ratchet/Http/RoutedHttpServer.php | 65 +++++++++++++++++++++++++++
 2 files changed, 71 insertions(+), 13 deletions(-)
 create mode 100644 src/Ratchet/Http/RoutedHttpServer.php

diff --git a/README.md b/README.md
index e089404..3f78953 100644
--- a/README.md
+++ b/README.md
@@ -38,15 +38,9 @@ Need help?  Have a question?  Want to provide feedback?  Write a message on the
 <?php
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
-
+use Ratchet\Http\RoutedHttpServer;
 use Ratchet\Server\IoServer;
-use Ratchet\Http\HttpServer;
-use Ratchet\Http\Router;
-use Ratchet\WebSocket\WsServer;
-use Symfony\Component\Routing\Route;
-use Symfony\Component\Routing\Matcher\UrlMatcher;
-use Symfony\Component\Routing\RouteCollection;
-use Symfony\Component\Routing\RequestContext;
+use Ratchet\Tests\AbFuzzyServer;
 
     require __DIR__ . '/vendor/autoload.php';
 
@@ -83,12 +77,11 @@ class Chat implements MessageComponentInterface {
 }
 
     // Run the server application through the WebSocket protocol on port 8080
-    // This will be made easier soon, routing currently in development
-    $routes->add('chatRoute', new Route('/chat', array(
-        '_controller' => new WsServer(new Chat)
-    )));
+    $router = new RoutedHttpServer;
+    $router->addRoute('/echo', new AbFuzzyServer);
+    $router->addRoute('/chat', new Chat);
 
-    $server = IoServer::factory(new HttpServer(new Router(new UrlMatcher($routes, new RequestContext))), 8080);
+    $server = IoServer::factory($router, 8000);
     $server->run();
 ```
 
diff --git a/src/Ratchet/Http/RoutedHttpServer.php b/src/Ratchet/Http/RoutedHttpServer.php
new file mode 100644
index 0000000..728424c
--- /dev/null
+++ b/src/Ratchet/Http/RoutedHttpServer.php
@@ -0,0 +1,65 @@
+<?php
+namespace Ratchet\Http;
+use Ratchet\MessageComponentInterface;
+use Ratchet\ConnectionInterface;
+use Ratchet\WebSocket\WsServer;
+use Symfony\Component\Routing\RouteCollection;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\Routing\RequestContext;
+use Symfony\Component\Routing\Matcher\UrlMatcher;
+
+/**
+ */
+class RoutedHttpServer implements MessageComponentInterface {
+    protected $_routes;
+    protected $_server;
+
+    public function __construct(RouteCollection $routes = null) {
+        if (null == $routes) {
+            $routes = new RouteCollection;
+        }
+
+        $this->_routes = $routes;
+        $this->_server = new HttpServer(new Router(new UrlMatcher($routes, new RequestContext)));
+    }
+
+    public function addRoute($path, MessageComponentInterface $controller) {
+        $this->_routes->add(uniqid(), new Route($path, array(
+            '_controller' => new WsServer($controller)
+        )));
+    }
+
+    public function addHttpRoute($path, HttpServerInterface $controller) {
+        $this->_routes->add(uniqid(), new Route($path, array(
+            '_controller' => $controller
+        )));
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    function onOpen(ConnectionInterface $conn) {
+        $this->_server->onOpen($conn);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    function onMessage(ConnectionInterface $from, $msg) {
+        $this->_server->onMessage($from, $msg);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    function onClose(ConnectionInterface $conn) {
+        $this->_server->onClose($conn);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    function onError(ConnectionInterface $conn, \Exception $e) {
+        $this->_server->onError($conn, $e);
+    }
+}
\ No newline at end of file

From 9d389b14c8b2f444038b1339146a7d9a21a3e738 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sat, 27 Apr 2013 00:11:34 -0400
Subject: [PATCH 14/48] Don't test old version of PHP 5

---
 .travis.yml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 80698e0..5625a26 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,6 @@
 language: php
 
 php:
-  - 5.3.9
   - 5.3
   - 5.4
 

From 5c41b2fbe126c5b5eb70b0171c078f0fc828f193 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sat, 27 Apr 2013 10:27:45 -0400
Subject: [PATCH 15/48] [Http][Tests] Refactored unit tests, added new for HTTP

---
 src/Ratchet/Session/SessionProvider.php       |  2 +-
 src/Ratchet/WebSocket/WsServer.php            |  1 -
 .../Tests/AbstractConnectionDecoratorTest.php |  3 +-
 .../AbstractMessageComponentTestCase.php      | 41 ++++++++++++
 tests/Ratchet/Tests/Http/HttpServerTest.php   | 33 ++++++++++
 .../Tests/Mock/MemorySessionHandler.php       | 39 -----------
 tests/Ratchet/Tests/Mock/NullComponent.php    | 28 ++++++++
 .../Tests/Session/SessionComponentTest.php    | 64 ++++++-------------
 .../Ratchet/Tests/Wamp/ServerProtocolTest.php |  2 +-
 tests/Ratchet/Tests/Wamp/WampServerTest.php   | 41 ++++--------
 .../Tests/WebSocket/Version/Hixie76Test.php   | 17 ++---
 11 files changed, 143 insertions(+), 128 deletions(-)
 create mode 100644 tests/Ratchet/Tests/AbstractMessageComponentTestCase.php
 create mode 100644 tests/Ratchet/Tests/Http/HttpServerTest.php
 delete mode 100644 tests/Ratchet/Tests/Mock/MemorySessionHandler.php
 create mode 100644 tests/Ratchet/Tests/Mock/NullComponent.php

diff --git a/src/Ratchet/Session/SessionProvider.php b/src/Ratchet/Session/SessionProvider.php
index 7203dda..b2c549b 100644
--- a/src/Ratchet/Session/SessionProvider.php
+++ b/src/Ratchet/Session/SessionProvider.php
@@ -71,7 +71,7 @@ class SessionProvider implements MessageComponentInterface, WsServerInterface {
      * {@inheritdoc}
      */
     function onOpen(ConnectionInterface $conn) {
-        if (null === ($id = $conn->WebSocket->request->getCookie(ini_get('session.name')))) {
+        if (!isset($conn->WebSocket) || null === ($id = $conn->WebSocket->request->getCookie(ini_get('session.name')))) {
             $saveHandler = $this->_null;
             $id = '';
         } else {
diff --git a/src/Ratchet/WebSocket/WsServer.php b/src/Ratchet/WebSocket/WsServer.php
index 77e3fe1..5245019 100644
--- a/src/Ratchet/WebSocket/WsServer.php
+++ b/src/Ratchet/WebSocket/WsServer.php
@@ -110,7 +110,6 @@ class WsServer implements HttpServerInterface {
             return;
         }
 
-        // This needs to be refactored later on, incorporated with routing
         if ('' !== ($agreedSubProtocols = $this->getSubProtocolString($conn->WebSocket->request->getTokenizedHeader('Sec-WebSocket-Protocol', ',')))) {
             $response->setHeader('Sec-WebSocket-Protocol', $agreedSubProtocols);
         }
diff --git a/tests/Ratchet/Tests/AbstractConnectionDecoratorTest.php b/tests/Ratchet/Tests/AbstractConnectionDecoratorTest.php
index 707460c..f196c79 100644
--- a/tests/Ratchet/Tests/AbstractConnectionDecoratorTest.php
+++ b/tests/Ratchet/Tests/AbstractConnectionDecoratorTest.php
@@ -1,7 +1,6 @@
 <?php
 namespace Ratchet\Tests;
 use Ratchet\Tests\Mock\ConnectionDecorator;
-use Ratchet\Tests\Mock\Connection;
 
 /**
  * @covers Ratchet\AbstractConnectionDecorator
@@ -13,7 +12,7 @@ class AbstractConnectionDecoratorTest extends \PHPUnit_Framework_TestCase {
     protected $l2;
 
     public function setUp() {
-        $this->mock = new Connection;
+        $this->mock = $this->getMock('\Ratchet\ConnectionInterface');
         $this->l1   = new ConnectionDecorator($this->mock);
         $this->l2   = new ConnectionDecorator($this->l1);
     }
diff --git a/tests/Ratchet/Tests/AbstractMessageComponentTestCase.php b/tests/Ratchet/Tests/AbstractMessageComponentTestCase.php
new file mode 100644
index 0000000..a9223af
--- /dev/null
+++ b/tests/Ratchet/Tests/AbstractMessageComponentTestCase.php
@@ -0,0 +1,41 @@
+<?php
+namespace Ratchet\Tests;
+
+abstract class AbstractMessageComponentTestCase extends \PHPUnit_Framework_TestCase {
+    protected $_app;
+    protected $_serv;
+    protected $_conn;
+
+    abstract public function getConnectionClassString();
+    abstract public function getDecoratorClassString();
+    abstract public function getComponentClassString();
+
+    public function setUp() {
+        $this->_app  = $this->getMock($this->getComponentClassString());
+        $decorator   = $this->getDecoratorClassString();
+        $this->_serv = new $decorator($this->_app);
+        $this->_conn = $this->getMock('\Ratchet\ConnectionInterface');
+
+        $this->_serv->onOpen($this->_conn);
+    }
+
+    public function isExpectedConnection() {
+        return new \PHPUnit_Framework_Constraint_IsInstanceOf($this->getConnectionClassString());
+    }
+
+    public function testOpen() {
+        $this->_app->expects($this->once())->method('onOpen')->with($this->isExpectedConnection());
+        $this->_serv->onOpen($this->getMock('\Ratchet\ConnectionInterface'));
+    }
+
+    public function testOnClose() {
+        $this->_app->expects($this->once())->method('onClose')->with($this->isExpectedConnection());
+        $this->_serv->onClose($this->_conn);
+    }
+
+    public function testOnError() {
+        $e = new \Exception('Whoops!');
+        $this->_app->expects($this->once())->method('onError')->with($this->isExpectedConnection(), $e);
+        $this->_serv->onError($this->_conn, $e);
+    }
+}
\ No newline at end of file
diff --git a/tests/Ratchet/Tests/Http/HttpServerTest.php b/tests/Ratchet/Tests/Http/HttpServerTest.php
new file mode 100644
index 0000000..c7fef74
--- /dev/null
+++ b/tests/Ratchet/Tests/Http/HttpServerTest.php
@@ -0,0 +1,33 @@
+<?php
+namespace Ratchet\Tests\Http;
+use Ratchet\Tests\AbstractMessageComponentTestCase;
+
+/**
+ * @covers Ratchet\Http\HttpServer
+ */
+class HttpServerTest extends AbstractMessageComponentTestCase {
+    public function setUp() {
+        parent::setUp();
+        $this->_conn->httpHeadersReceived = true;
+    }
+
+    public function getConnectionClassString() {
+        return '\Ratchet\ConnectionInterface';
+    }
+
+    public function getDecoratorClassString() {
+        return '\Ratchet\Http\HttpServer';
+    }
+
+    public function getComponentClassString() {
+        return '\Ratchet\Http\HttpServerInterface';
+    }
+
+    public function testOpen() {
+        $headers = "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n";
+
+        $this->_conn->httpHeadersReceived = false;
+        $this->_app->expects($this->once())->method('onOpen')->with($this->isExpectedConnection());
+        $this->_serv->onMessage($this->_conn, $headers);
+    }
+}
\ No newline at end of file
diff --git a/tests/Ratchet/Tests/Mock/MemorySessionHandler.php b/tests/Ratchet/Tests/Mock/MemorySessionHandler.php
deleted file mode 100644
index 87e9953..0000000
--- a/tests/Ratchet/Tests/Mock/MemorySessionHandler.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-namespace Ratchet\Tests\Mock;
-
-class MemorySessionHandler implements \SessionHandlerInterface {
-    protected $_sessions = array();
-
-    public function close() {
-    }
-
-    public function destroy($session_id) {
-        if (isset($this->_sessions[$session_id])) {
-            unset($this->_sessions[$session_id]);
-        }
-
-        return true;
-    }
-
-    public function gc($maxlifetime) {
-        return true;
-    }
-
-    public function open($save_path, $session_id) {
-        if (!isset($this->_sessions[$session_id])) {
-            $this->_sessions[$session_id] = '';
-        }
-
-        return true;
-    }
-
-    public function read($session_id) {
-        return $this->_sessions[$session_id];
-    }
-
-    public function write($session_id, $session_data) {
-        $this->_sessions[$session_id] = $session_data;
-
-        return true;
-    }
-}
\ No newline at end of file
diff --git a/tests/Ratchet/Tests/Mock/NullComponent.php b/tests/Ratchet/Tests/Mock/NullComponent.php
new file mode 100644
index 0000000..73a44a1
--- /dev/null
+++ b/tests/Ratchet/Tests/Mock/NullComponent.php
@@ -0,0 +1,28 @@
+<?php
+namespace Ratchet\Tests\Mock;
+use Ratchet\ConnectionInterface;
+use Ratchet\MessageComponentInterface;
+use Ratchet\WebSocket\WsServerInterface;
+use Ratchet\Wamp\WampServerInterface;
+
+class NullComponent implements MessageComponentInterface, WsServerInterface, WampServerInterface {
+    public function onOpen(ConnectionInterface $conn) {}
+
+    public function onMessage(ConnectionInterface $conn, $msg) {}
+
+    public function onClose(ConnectionInterface $conn) {}
+
+    public function onError(ConnectionInterface $conn, \Exception $e) {}
+
+    public function onCall(ConnectionInterface $conn, $id, $topic, array $params) {}
+
+    public function onSubscribe(ConnectionInterface $conn, $topic) {}
+
+    public function onUnSubscribe(ConnectionInterface $conn, $topic) {}
+
+    public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude = array(), array $eligible = array()) {}
+
+    public function getSubProtocols() {
+        return array();
+    }
+}
\ No newline at end of file
diff --git a/tests/Ratchet/Tests/Session/SessionComponentTest.php b/tests/Ratchet/Tests/Session/SessionComponentTest.php
index ed75191..4b4b41d 100644
--- a/tests/Ratchet/Tests/Session/SessionComponentTest.php
+++ b/tests/Ratchet/Tests/Session/SessionComponentTest.php
@@ -1,5 +1,6 @@
 <?php
 namespace Ratchet\Tests\Session;
+use Ratchet\Tests\AbstractMessageComponentTestCase;
 use Ratchet\Session\SessionProvider;
 use Ratchet\Tests\Mock\MemorySessionHandler;
 use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
@@ -11,11 +12,26 @@ use Guzzle\Http\Message\Request;
  * @covers Ratchet\Session\Storage\VirtualSessionStorage
  * @covers Ratchet\Session\Storage\Proxy\VirtualProxy
  */
-class SessionProviderTest extends \PHPUnit_Framework_TestCase {
+class SessionProviderTest extends AbstractMessageComponentTestCase {
     public function setUp() {
-        if (!class_exists('Symfony\\Component\\HttpFoundation\\Session\\Session')) {
+        if (!class_exists('Symfony\Component\HttpFoundation\Session\Session')) {
             return $this->markTestSkipped('Dependency of Symfony HttpFoundation failed');
         }
+
+        parent::setUp();
+        $this->_serv = new SessionProvider($this->_app, new NullSessionHandler);
+    }
+
+    public function getConnectionClassString() {
+        return '\Ratchet\ConnectionInterface';
+    }
+
+    public function getDecoratorClassString() {
+        return '\Ratchet\Tests\Mock\NullComponent';
+    }
+
+    public function getComponentClassString() {
+        return '\Ratchet\MessageComponentInterface';
     }
 
     public function classCaseProvider() {
@@ -33,7 +49,7 @@ class SessionProviderTest extends \PHPUnit_Framework_TestCase {
         $method = $ref->getMethod('toClassCase');
         $method->setAccessible(true);
 
-        $component = new SessionProvider($this->getMock('Ratchet\\MessageComponentInterface'), new MemorySessionHandler);
+        $component = new SessionProvider($this->getMock('Ratchet\\MessageComponentInterface'), $this->getMock('\SessionHandlerInterface'));
         $this->assertEquals($out, $method->invokeArgs($component, array($in)));
     }
 
@@ -84,48 +100,6 @@ class SessionProviderTest extends \PHPUnit_Framework_TestCase {
         return $conn;
     }
 
-    public function testOnOpenBubbles() {
-        $conn = $this->newConn();
-        $mock = $this->getMock('Ratchet\\MessageComponentInterface');
-        $comp = new SessionProvider($mock, new NullSessionHandler);
-
-        $mock->expects($this->once())->method('onOpen')->with($conn);
-        $comp->onOpen($conn);
-    }
-
-    protected function getOpenConn() {
-        $conn = $this->newConn();
-        $mock = $this->getMock('Ratchet\\MessageComponentInterface');
-        $prov = new SessionProvider($mock, new NullSessionHandler);
-
-        $prov->onOpen($conn);
-
-        return array($conn, $mock, $prov);
-    }
-
-    public function testOnMessageBubbles() {
-        list($conn, $mock, $prov) = $this->getOpenConn();
-        $msg = 'No sessions here';
-
-        $mock->expects($this->once())->method('onMessage')->with($conn, $msg);
-        $prov->onMessage($conn, $msg);
-    }
-
-    public function testOnCloseBubbles() {
-        list($conn, $mock, $prov) = $this->getOpenConn();
-
-        $mock->expects($this->once())->method('onClose')->with($conn);
-        $prov->onClose($conn);
-    }
-
-    public function testOnErrorBubbles() {
-        list($conn, $mock, $prov) = $this->getOpenConn();
-        $e = new \Exception('I made a boo boo');
-
-        $mock->expects($this->once())->method('onError')->with($conn, $e);
-        $prov->onError($conn, $e);
-    }
-
     public function testGetSubProtocolsReturnsArray() {
         $mock = $this->getMock('Ratchet\\MessageComponentInterface');
         $comp = new SessionProvider($mock, new NullSessionHandler);
diff --git a/tests/Ratchet/Tests/Wamp/ServerProtocolTest.php b/tests/Ratchet/Tests/Wamp/ServerProtocolTest.php
index cf5d803..4217ea3 100644
--- a/tests/Ratchet/Tests/Wamp/ServerProtocolTest.php
+++ b/tests/Ratchet/Tests/Wamp/ServerProtocolTest.php
@@ -38,7 +38,7 @@ class ServerProtocolTest extends \PHPUnit_Framework_TestCase {
      * @dataProvider invalidMessageProvider
      */
     public function testInvalidMessages($type) {
-        $this->setExpectedException('\\Ratchet\\Wamp\\Exception');
+        $this->setExpectedException('\Ratchet\Wamp\Exception');
 
         $conn = $this->newConn();
         $this->_comp->onOpen($conn);
diff --git a/tests/Ratchet/Tests/Wamp/WampServerTest.php b/tests/Ratchet/Tests/Wamp/WampServerTest.php
index 6a92d57..e83dc28 100644
--- a/tests/Ratchet/Tests/Wamp/WampServerTest.php
+++ b/tests/Ratchet/Tests/Wamp/WampServerTest.php
@@ -1,59 +1,44 @@
 <?php
 namespace Ratchet\Tests\Wamp;
 use Ratchet\Wamp\WampServer;
+use Ratchet\Tests\AbstractMessageComponentTestCase;
 
 /**
  * @covers Ratchet\Wamp\WampServer
  */
-class WampServerTest extends \PHPUnit_Framework_TestCase {
+class WampServerTest extends AbstractMessageComponentTestCase {
     private $serv;
     private $mock;
     private $conn;
 
-    public function setUp() {
-        $this->mock = $this->getMock('\\Ratchet\\Wamp\\WampServerInterface');
-        $this->serv = new WampServer($this->mock);
-        $this->conn = $this->getMock('\\Ratchet\\ConnectionInterface');
-
-        $this->serv->onOpen($this->conn);
+    public function getConnectionClassString() {
+        return '\Ratchet\Wamp\WampConnection';
     }
 
-    public function isWampConn() {
-        return new \PHPUnit_Framework_Constraint_IsInstanceOf('\\Ratchet\\Wamp\\WampConnection');
+    public function getDecoratorClassString() {
+        return 'Ratchet\Wamp\WampServer';
     }
 
-    public function testOpen() {
-        $this->mock->expects($this->once())->method('onOpen')->with($this->isWampConn());
-        $this->serv->onOpen($this->getMock('\\Ratchet\\ConnectionInterface'));
-    }
-
-    public function testOnClose() {
-        $this->mock->expects($this->once())->method('onClose')->with($this->isWampConn());
-        $this->serv->onClose($this->conn);
-    }
-
-    public function testOnError() {
-        $e = new \Exception('hurr hurr');
-        $this->mock->expects($this->once())->method('onError')->with($this->isWampConn(), $e);
-        $this->serv->onError($this->conn, $e);
+    public function getComponentClassString() {
+        return '\Ratchet\Wamp\WampServerInterface';
     }
 
     public function testOnMessageToEvent() {
         $published = 'Client published this message';
 
-        $this->mock->expects($this->once())->method('onPublish')->with(
-            $this->isWampConn()
-          , new \PHPUnit_Framework_Constraint_IsInstanceOf('\\Ratchet\\Wamp\\Topic')
+        $this->_app->expects($this->once())->method('onPublish')->with(
+            $this->isExpectedConnection()
+          , new \PHPUnit_Framework_Constraint_IsInstanceOf('\Ratchet\Wamp\Topic')
           , $published
           , array()
           , array()
         );
 
-        $this->serv->onMessage($this->conn, json_encode(array(7, 'topic', $published)));
+        $this->_serv->onMessage($this->_conn, json_encode(array(7, 'topic', $published)));
     }
 
     public function testGetSubProtocols() {
         // todo: could expand on this
-        $this->assertInternalType('array', $this->serv->getSubProtocols());
+        $this->assertInternalType('array', $this->_serv->getSubProtocols());
     }
 }
\ No newline at end of file
diff --git a/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php b/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php
index 2e80307..3ac1f4a 100644
--- a/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php
+++ b/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php
@@ -54,16 +54,13 @@ class Hixie76Test extends \PHPUnit_Framework_TestCase {
         return $headers;
     }
 
-/* @todo Re-enable and fix these tests later - bad functional tests atm, break into units
     public function testNoUpgradeBeforeBody() {
         $headers = $this->headerProvider();
-        $body    = base64_decode($this->_body);
 
-        $mockConn = $this->getMock('\\Ratchet\\ConnectionInterface');
-        $mockApp = $this->getMock('\\Ratchet\\MessageComponentInterface');
+        $mockConn = $this->getMock('\Ratchet\ConnectionInterface');
+        $mockApp  = $this->getMock('\Ratchet\MessageComponentInterface');
 
-        $server = new HttpServer;
-        $server->addRoute('test', '/', new WsServer($mockApp));
+        $server = new HttpServer(new WsServer($mockApp));
         $server->onOpen($mockConn);
         $mockApp->expects($this->exactly(0))->method('onOpen');
         $server->onMessage($mockConn, $headers);
@@ -73,16 +70,14 @@ class Hixie76Test extends \PHPUnit_Framework_TestCase {
         $headers = $this->headerProvider();
         $body    = base64_decode($this->_body);
 
-        $mockConn = $this->getMock('\\Ratchet\\ConnectionInterface');
-        $mockApp = $this->getMock('\\Ratchet\\MessageComponentInterface');
+        $mockConn = $this->getMock('\Ratchet\ConnectionInterface');
+        $mockApp  = $this->getMock('\Ratchet\MessageComponentInterface');
 
-        $server = new HttpServer;
-        $server->addRoute('test', '/', new WsServer($mockApp));
+        $server = new HttpServer(new WsServer($mockApp));
         $server->onOpen($mockConn);
         $server->onMessage($mockConn, $headers);
 
         $mockApp->expects($this->once())->method('onOpen');
         $server->onMessage($mockConn, $body . $this->_crlf . $this->_crlf);
     }
-*/
 }
\ No newline at end of file

From 38df97676833303faf56a22026b119132dadb9b5 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sat, 27 Apr 2013 11:22:56 -0400
Subject: [PATCH 16/48] [Http] Fixed tests, upgraded React

---
 composer.json                                 |  2 +-
 composer.lock                                 | 52 +++++++++----------
 .../bin/fuzzingserver-libev.php               |  2 +-
 .../bin/fuzzingserver-libevent.php            |  2 +-
 .../bin/fuzzingserver-libuv.php               |  2 +-
 .../bin/fuzzingserver-noutf8.php              |  5 +-
 .../bin/fuzzingserver-stream.php              |  2 +-
 .../Http/Message/RequestFactoryTest.php       |  2 +-
 .../Tests/Http/HtpRequestParserTest.php       |  2 +-
 9 files changed, 36 insertions(+), 35 deletions(-)

diff --git a/composer.json b/composer.json
index a7a7953..89eec01 100644
--- a/composer.json
+++ b/composer.json
@@ -26,7 +26,7 @@
     }
   , "require": {
         "php": ">=5.3.9"
-      , "react/socket": "0.2.*"
+      , "react/socket": "~0.2"
       , "guzzle/http": "~3.0"
       , "symfony/http-foundation": "~2.2"
       , "symfony/routing": "~2.2"
diff --git a/composer.lock b/composer.lock
index 882649e..f7408e1 100644
--- a/composer.lock
+++ b/composer.lock
@@ -3,7 +3,7 @@
         "This file locks the dependencies of your project to a known state",
         "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
     ],
-    "hash": "b51075c0a68acb956c32e59869790571",
+    "hash": "6006ea344879ef78bf1a490e630a74fc",
     "packages": [
         {
             "name": "evenement/evenement",
@@ -244,17 +244,17 @@
         },
         {
             "name": "react/event-loop",
-            "version": "v0.2.7",
+            "version": "v0.3.1",
             "target-dir": "React/EventLoop",
             "source": {
                 "type": "git",
-                "url": "https://github.com/reactphp/event-loop",
-                "reference": "v0.2.7"
+                "url": "https://github.com/reactphp/event-loop.git",
+                "reference": "v0.3.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://github.com/reactphp/event-loop/archive/v0.2.7.zip",
-                "reference": "v0.2.7",
+                "url": "https://api.github.com/repos/reactphp/event-loop/zipball/v0.3.1",
+                "reference": "v0.3.1",
                 "shasum": ""
             },
             "require": {
@@ -267,7 +267,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "0.2-dev"
+                    "dev-master": "0.3-dev"
                 }
             },
             "autoload": {
@@ -283,33 +283,33 @@
             "keywords": [
                 "event-loop"
             ],
-            "time": "2013-01-05 11:41:26"
+            "time": "2013-01-14 23:11:47"
         },
         {
             "name": "react/socket",
-            "version": "v0.2.7",
+            "version": "v0.3.1",
             "target-dir": "React/Socket",
             "source": {
                 "type": "git",
-                "url": "https://github.com/reactphp/socket",
-                "reference": "v0.2.7"
+                "url": "https://github.com/reactphp/socket.git",
+                "reference": "v0.3.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://github.com/reactphp/socket/archive/v0.2.7.zip",
-                "reference": "v0.2.7",
+                "url": "https://api.github.com/repos/reactphp/socket/zipball/v0.3.1",
+                "reference": "v0.3.1",
                 "shasum": ""
             },
             "require": {
                 "evenement/evenement": "1.0.*",
                 "php": ">=5.3.3",
-                "react/event-loop": "0.2.*",
-                "react/stream": "0.2.*"
+                "react/event-loop": "0.3.*",
+                "react/stream": "0.3.*"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "0.2-dev"
+                    "dev-master": "0.3-dev"
                 }
             },
             "autoload": {
@@ -325,21 +325,21 @@
             "keywords": [
                 "Socket"
             ],
-            "time": "2012-12-14 00:58:14"
+            "time": "2013-04-20 14:53:10"
         },
         {
             "name": "react/stream",
-            "version": "v0.2.7",
+            "version": "v0.3.1",
             "target-dir": "React/Stream",
             "source": {
                 "type": "git",
-                "url": "https://github.com/reactphp/stream",
-                "reference": "v0.2.7"
+                "url": "https://github.com/reactphp/stream.git",
+                "reference": "v0.3.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://github.com/reactphp/stream/archive/v0.2.7.zip",
-                "reference": "v0.2.7",
+                "url": "https://api.github.com/repos/reactphp/stream/zipball/v0.3.1",
+                "reference": "v0.3.1",
                 "shasum": ""
             },
             "require": {
@@ -347,13 +347,13 @@
                 "php": ">=5.3.3"
             },
             "suggest": {
-                "react/event-loop": "0.2.*",
-                "react/promise": "1.0.*"
+                "react/event-loop": "0.3.*",
+                "react/promise": "~1.0"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "0.2-dev"
+                    "dev-master": "0.3-dev"
                 }
             },
             "autoload": {
@@ -370,7 +370,7 @@
                 "pipe",
                 "stream"
             ],
-            "time": "2012-12-14 00:58:14"
+            "time": "2013-04-21 13:25:49"
         },
         {
             "name": "symfony/event-dispatcher",
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-libev.php b/tests/AutobahnTestSuite/bin/fuzzingserver-libev.php
index ccd0613..fb6d03f 100644
--- a/tests/AutobahnTestSuite/bin/fuzzingserver-libev.php
+++ b/tests/AutobahnTestSuite/bin/fuzzingserver-libev.php
@@ -4,7 +4,7 @@
 
     $loop = new React\EventLoop\LibEvLoop;
     $sock = new React\Socket\Server($loop);
-    $app  = new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer);
+    $app  = new Ratchet\Http\HttpServer(new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer));
 
     $port = $argc > 1 ? $argv[1] : 8000;
     $sock->listen($port, '0.0.0.0');
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-libevent.php b/tests/AutobahnTestSuite/bin/fuzzingserver-libevent.php
index 166bd45..ea1fbad 100644
--- a/tests/AutobahnTestSuite/bin/fuzzingserver-libevent.php
+++ b/tests/AutobahnTestSuite/bin/fuzzingserver-libevent.php
@@ -4,7 +4,7 @@
 
     $loop = new React\EventLoop\LibEventLoop;
     $sock = new React\Socket\Server($loop);
-    $app  = new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer);
+    $app  = new Ratchet\Http\HttpServer(new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer));
 
     $port = $argc > 1 ? $argv[1] : 8000;
     $sock->listen($port, '0.0.0.0');
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-libuv.php b/tests/AutobahnTestSuite/bin/fuzzingserver-libuv.php
index ccd0613..fb6d03f 100644
--- a/tests/AutobahnTestSuite/bin/fuzzingserver-libuv.php
+++ b/tests/AutobahnTestSuite/bin/fuzzingserver-libuv.php
@@ -4,7 +4,7 @@
 
     $loop = new React\EventLoop\LibEvLoop;
     $sock = new React\Socket\Server($loop);
-    $app  = new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer);
+    $app  = new Ratchet\Http\HttpServer(new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer));
 
     $port = $argc > 1 ? $argv[1] : 8000;
     $sock->listen($port, '0.0.0.0');
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php b/tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php
index 589cdd9..f63893a 100644
--- a/tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php
+++ b/tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php
@@ -4,8 +4,9 @@
 
     $loop = new React\EventLoop\StreamSelectLoop;
     $sock = new React\Socket\Server($loop);
-    $app  = new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer);
-    $app->setEncodingChecks(false);
+    $web  = new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer)
+    $app  = new Ratchet\Http\HttpServer($web);
+    $web->setEncodingChecks(false);
 
     $port = $argc > 1 ? $argv[1] : 8000;
     $sock->listen($port, '0.0.0.0');
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-stream.php b/tests/AutobahnTestSuite/bin/fuzzingserver-stream.php
index 4e3e797..98b4448 100644
--- a/tests/AutobahnTestSuite/bin/fuzzingserver-stream.php
+++ b/tests/AutobahnTestSuite/bin/fuzzingserver-stream.php
@@ -4,7 +4,7 @@
 
     $loop = new React\EventLoop\StreamSelectLoop;
     $sock = new React\Socket\Server($loop);
-    $app  = new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer);
+    $app  = new Ratchet\Http\HttpServer(new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer));
 
     $port = $argc > 1 ? $argv[1] : 8000;
     $sock->listen($port, '0.0.0.0');
diff --git a/tests/Ratchet/Tests/Http/Guzzle/Http/Message/RequestFactoryTest.php b/tests/Ratchet/Tests/Http/Guzzle/Http/Message/RequestFactoryTest.php
index cb67bf5..9709745 100644
--- a/tests/Ratchet/Tests/Http/Guzzle/Http/Message/RequestFactoryTest.php
+++ b/tests/Ratchet/Tests/Http/Guzzle/Http/Message/RequestFactoryTest.php
@@ -3,7 +3,7 @@ namespace Ratchet\Tests\Http\Guzzle\Http\Message;
 use Ratchet\Http\Guzzle\Http\Message\RequestFactory;
 
 /**
- * @covers Ratchet\WebSocket\Guzzle\Http\Message\RequestFactory
+ * @covers Ratchet\Http\Guzzle\Http\Message\RequestFactory
  */
 class RequestFactoryTest extends \PHPUnit_Framework_TestCase {
     protected $factory;
diff --git a/tests/Ratchet/Tests/Http/HtpRequestParserTest.php b/tests/Ratchet/Tests/Http/HtpRequestParserTest.php
index a32a6da..4de396c 100644
--- a/tests/Ratchet/Tests/Http/HtpRequestParserTest.php
+++ b/tests/Ratchet/Tests/Http/HtpRequestParserTest.php
@@ -3,7 +3,7 @@ namespace Ratchet\Tests\Http;
 use Ratchet\Http\HttpRequestParser;
 
 /**
- * @covers Ratchet\WebSocket\HttpRequestParser
+ * @covers Ratchet\Http\HttpRequestParser
  */
 class HttpRequestParserTest extends \PHPUnit_Framework_TestCase {
     protected $parser;

From 1ea0bd32559a3dd3084172a6616daee7a3a64bb9 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sat, 27 Apr 2013 16:51:24 -0400
Subject: [PATCH 17/48] [Http] Cleanup and parse error fix

---
 src/Ratchet/Http/HttpServer.php                   | 15 ++++++---------
 .../bin/fuzzingserver-noutf8.php                  |  2 +-
 2 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/src/Ratchet/Http/HttpServer.php b/src/Ratchet/Http/HttpServer.php
index 867d008..d4e8967 100644
--- a/src/Ratchet/Http/HttpServer.php
+++ b/src/Ratchet/Http/HttpServer.php
@@ -3,13 +3,10 @@ namespace Ratchet\Http;
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
 use Guzzle\Http\Message\Response;
-use Symfony\Component\Routing\RouteCollection;
-use Symfony\Component\Routing\Route;
-use Symfony\Component\Routing\RequestContext;
-use Symfony\Component\Routing\Matcher\UrlMatcher;
-use Symfony\Component\Routing\Exception\MethodNotAllowedException;
-use Symfony\Component\Routing\Exception\ResourceNotFoundException;
 
+/**
+ * @todo Detect HTTP proxy header IP, re-map remoteAddress
+ */
 class HttpServer implements MessageComponentInterface {
     /**
      * Buffers incoming HTTP requests returning a Guzzle Request when coalesced
@@ -26,8 +23,8 @@ class HttpServer implements MessageComponentInterface {
     /**
      * @param HttpServerInterface
      */
-    public function __construct(HttpServerInterface $server) {
-        $this->_httpServer = $server;
+    public function __construct(HttpServerInterface $component) {
+        $this->_httpServer = $component;
         $this->_reqParser  = new HttpRequestParser;
     }
 
@@ -83,7 +80,7 @@ class HttpServer implements MessageComponentInterface {
      * Close a connection with an HTTP response
      * @param \Ratchet\ConnectionInterface $conn
      * @param int                          $code HTTP status code
-     * @return void
+     * @return null
      */
     protected function close(ConnectionInterface $conn, $code = 400) {
         $response = new Response($code, array(
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php b/tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php
index f63893a..b20b3a1 100644
--- a/tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php
+++ b/tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php
@@ -4,7 +4,7 @@
 
     $loop = new React\EventLoop\StreamSelectLoop;
     $sock = new React\Socket\Server($loop);
-    $web  = new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer)
+    $web  = new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer);
     $app  = new Ratchet\Http\HttpServer($web);
     $web->setEncodingChecks(false);
 

From 8df459548fd7e46d9cef3e02cd15675072743d9f Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sun, 28 Apr 2013 09:55:43 -0400
Subject: [PATCH 18/48] [WebSocket][Http] Bug fix WS require nullifying, more
 strict on Request parameter

---
 src/Ratchet/Http/HttpServerInterface.php |  1 +
 src/Ratchet/Http/Router.php              | 14 +++++++++----
 src/Ratchet/WebSocket/WsServer.php       | 25 ++++++++++++------------
 3 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/src/Ratchet/Http/HttpServerInterface.php b/src/Ratchet/Http/HttpServerInterface.php
index 0730680..79b7d55 100644
--- a/src/Ratchet/Http/HttpServerInterface.php
+++ b/src/Ratchet/Http/HttpServerInterface.php
@@ -8,6 +8,7 @@ interface HttpServerInterface extends MessageComponentInterface {
     /**
      * @param \Ratchet\ConnectionInterface          $conn
      * @param \Guzzle\Http\Message\RequestInterface $request null is default because PHP won't let me overload; don't pass null!!!
+     * @throws \UnexpectedValueException if a RequestInterface is not passed
      */
     public function onOpen(ConnectionInterface $conn, RequestInterface $request = null);
 }
diff --git a/src/Ratchet/Http/Router.php b/src/Ratchet/Http/Router.php
index 9946d7e..e1c1f6d 100644
--- a/src/Ratchet/Http/Router.php
+++ b/src/Ratchet/Http/Router.php
@@ -16,7 +16,14 @@ class Router implements HttpServerInterface {
         $this->_matcher = $matcher;
     }
 
+    /**
+     * {@inheritdoc}
+     */
     public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) {
+        if (null === $request) {
+            throw new \UnexpectedValueException('$request can not be null');
+        }
+
         try {
             $route = $this->_matcher->match($request->getPath());
         } catch (MethodNotAllowedException $nae) {
@@ -34,26 +41,25 @@ class Router implements HttpServerInterface {
         }
 
         $conn->controller = $route['_controller'];
-
         $conn->controller->onOpen($conn, $request);
     }
 
     /**
-     * @{inheritdoc}
+     * {@inheritdoc}
      */
     function onMessage(ConnectionInterface $from, $msg) {
         $from->controller->onMessage($from, $msg);
     }
 
     /**
-     * @{inheritdoc}
+     * {@inheritdoc}
      */
     function onClose(ConnectionInterface $conn) {
         $conn->controller->onClose($conn);
     }
 
     /**
-     * @{inheritdoc}
+     * {@inheritdoc}
      */
     function onError(ConnectionInterface $conn, \Exception $e) {
         $conn->controller->onError($conn, $e);
diff --git a/src/Ratchet/WebSocket/WsServer.php b/src/Ratchet/WebSocket/WsServer.php
index 5245019..24ea580 100644
--- a/src/Ratchet/WebSocket/WsServer.php
+++ b/src/Ratchet/WebSocket/WsServer.php
@@ -26,7 +26,7 @@ class WsServer implements HttpServerInterface {
      * Decorated component
      * @var \Ratchet\MessageComponentInterface
      */
-    protected $_decorating;
+    public $component;
 
     /**
      * @var \SplObjectStorage
@@ -34,9 +34,7 @@ class WsServer implements HttpServerInterface {
     protected $connections;
 
     /**
-     * For now, array_push accepted subprotocols to this array
-     * @deprecated
-     * @temporary
+     * Holder of accepted protocols, implement through WampServerInterface
      */
     protected $acceptedSubProtocols = array();
 
@@ -66,7 +64,7 @@ class WsServer implements HttpServerInterface {
             ->enableVersion(new Version\Hixie76)
         ;
 
-        $this->_decorating = $component;
+        $this->component   = $component;
         $this->connections = new \SplObjectStorage;
     }
 
@@ -74,6 +72,10 @@ class WsServer implements HttpServerInterface {
      * {@inheritdoc}
      */
     public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) {
+        if (null === $request) {
+            throw new \UnexpectedValueException('$request can not be null');
+        }
+
         $conn->WebSocket              = new \StdClass;
         $conn->WebSocket->request     = $request;
         $conn->WebSocket->established = false;
@@ -100,7 +102,6 @@ class WsServer implements HttpServerInterface {
                 return $this->close($conn);
             }
 
-            $conn->WebSocket->request = $conn->WebSocket->request;
             $conn->WebSocket->version = $this->versioner->getVersion($conn->WebSocket->request);
         }
 
@@ -121,13 +122,13 @@ class WsServer implements HttpServerInterface {
             return $conn->close();
         }
 
-        $upgraded = $conn->WebSocket->version->upgradeConnection($conn, $this->_decorating);
+        $upgraded = $conn->WebSocket->version->upgradeConnection($conn, $this->component);
 
         $this->connections->attach($conn, $upgraded);
 
         $upgraded->WebSocket->established = true;
 
-        return $this->_decorating->onOpen($upgraded);
+        return $this->component->onOpen($upgraded);
     }
 
     /**
@@ -138,7 +139,7 @@ class WsServer implements HttpServerInterface {
             $decor = $this->connections[$conn];
             $this->connections->detach($conn);
 
-            $this->_decorating->onClose($decor);
+            $this->component->onClose($decor);
         }
     }
 
@@ -147,7 +148,7 @@ class WsServer implements HttpServerInterface {
      */
     public function onError(ConnectionInterface $conn, \Exception $e) {
         if ($conn->WebSocket->established) {
-            $this->_decorating->onError($this->connections[$conn], $e);
+            $this->component->onError($this->connections[$conn], $e);
         } else {
             $conn->close();
         }
@@ -181,8 +182,8 @@ class WsServer implements HttpServerInterface {
      */
     public function isSubProtocolSupported($name) {
         if (!$this->isSpGenerated) {
-            if ($this->_decorating instanceof WsServerInterface) {
-                $this->acceptedSubProtocols = array_flip($this->_decorating->getSubProtocols());
+            if ($this->component instanceof WsServerInterface) {
+                $this->acceptedSubProtocols = array_flip($this->component->getSubProtocols());
             }
 
             $this->isSpGenerated = true;

From 344818d0f56d1c22d5accf6385cb70d656041b51 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sun, 28 Apr 2013 15:25:16 -0400
Subject: [PATCH 19/48] [Tests] Bring up unit testing coverage

Coverage on Http and Session
Set version to 0.3-beta
Cleaned up a couple API doc things
Removed Origin code from RFC, will be moved to Http
---
 src/Ratchet/ConnectionInterface.php           |  2 +-
 src/Ratchet/Http/HttpServer.php               |  8 ++---
 src/Ratchet/Session/SessionProvider.php       |  2 +-
 .../Version/RFC6455/HandshakeVerifier.php     | 16 ----------
 src/Ratchet/WebSocket/WsServer.php            |  1 -
 ...rserTest.php => HttpRequestParserTest.php} |  9 +++++-
 tests/Ratchet/Tests/Http/HttpServerTest.php   | 31 +++++++++++++++++++
 .../Tests/Session/SessionComponentTest.php    | 20 ++++++++++--
 8 files changed, 63 insertions(+), 26 deletions(-)
 rename tests/Ratchet/Tests/Http/{HtpRequestParserTest.php => HttpRequestParserTest.php} (78%)

diff --git a/src/Ratchet/ConnectionInterface.php b/src/Ratchet/ConnectionInterface.php
index cc4d74b..088823d 100644
--- a/src/Ratchet/ConnectionInterface.php
+++ b/src/Ratchet/ConnectionInterface.php
@@ -5,7 +5,7 @@ namespace Ratchet;
  * The version of Ratchet being used
  * @var string
  */
-const VERSION = 'Ratchet/0.2.5';
+const VERSION = 'Ratchet/0.3-beta';
 
 /**
  * A proxy object representing a connection to the application
diff --git a/src/Ratchet/Http/HttpServer.php b/src/Ratchet/Http/HttpServer.php
index d4e8967..5788807 100644
--- a/src/Ratchet/Http/HttpServer.php
+++ b/src/Ratchet/Http/HttpServer.php
@@ -29,14 +29,14 @@ class HttpServer implements MessageComponentInterface {
     }
 
     /**
-     * @{inheritdoc}
+     * {@inheritdoc}
      */
     public function onOpen(ConnectionInterface $conn) {
         $conn->httpHeadersReceived = false;
     }
 
     /**
-     * @{inheritdoc}
+     * {@inheritdoc}
      */
     public function onMessage(ConnectionInterface $from, $msg) {
         if (true !== $from->httpHeadersReceived) {
@@ -57,7 +57,7 @@ class HttpServer implements MessageComponentInterface {
     }
 
     /**
-     * @{inheritdoc}
+     * {@inheritdoc}
      */
     public function onClose(ConnectionInterface $conn) {
         if ($conn->httpHeadersReceived) {
@@ -66,7 +66,7 @@ class HttpServer implements MessageComponentInterface {
     }
 
     /**
-     * @{inheritdoc}
+     * {@inheritdoc}
      */
     public function onError(ConnectionInterface $conn, \Exception $e) {
         if ($conn->httpHeadersReceived) {
diff --git a/src/Ratchet/Session/SessionProvider.php b/src/Ratchet/Session/SessionProvider.php
index b2c549b..9cd4dd3 100644
--- a/src/Ratchet/Session/SessionProvider.php
+++ b/src/Ratchet/Session/SessionProvider.php
@@ -42,7 +42,7 @@ class SessionProvider implements MessageComponentInterface, WsServerInterface {
      * @param \SessionHandlerInterface                    $handler
      * @param array                                       $options
      * @param \Ratchet\Session\Serialize\HandlerInterface $serializer
-     * @throws \RuntimeExcpetion
+     * @throws \RuntimeException
      */
     public function __construct(MessageComponentInterface $app, \SessionHandlerInterface $handler, array $options = array(), HandlerInterface $serializer = null) {
         $this->_app     = $app;
diff --git a/src/Ratchet/WebSocket/Version/RFC6455/HandshakeVerifier.php b/src/Ratchet/WebSocket/Version/RFC6455/HandshakeVerifier.php
index 7fbf452..ea17d08 100644
--- a/src/Ratchet/WebSocket/Version/RFC6455/HandshakeVerifier.php
+++ b/src/Ratchet/WebSocket/Version/RFC6455/HandshakeVerifier.php
@@ -113,22 +113,6 @@ class HandshakeVerifier {
         return (16 === strlen(base64_decode((string)$val)));
     }
 
-    /**
-     * Verify Origin matches RFC6454 IF it is set
-     * Origin is an optional field
-     * @param string|null
-     * @return bool
-     * @todo Implement verification functionality - see section 4.2.1.7
-     */
-    public function verifyOrigin($val) {
-        if (null === $val) {
-            return true;
-        }
-
-        // logic here
-        return true;
-    }
-
     /**
      * Verify the version passed matches this RFC
      * @param string|int MUST equal 13|"13"
diff --git a/src/Ratchet/WebSocket/WsServer.php b/src/Ratchet/WebSocket/WsServer.php
index 24ea580..0373a14 100644
--- a/src/Ratchet/WebSocket/WsServer.php
+++ b/src/Ratchet/WebSocket/WsServer.php
@@ -216,7 +216,6 @@ class WsServer implements HttpServerInterface {
      * 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(
diff --git a/tests/Ratchet/Tests/Http/HtpRequestParserTest.php b/tests/Ratchet/Tests/Http/HttpRequestParserTest.php
similarity index 78%
rename from tests/Ratchet/Tests/Http/HtpRequestParserTest.php
rename to tests/Ratchet/Tests/Http/HttpRequestParserTest.php
index 4de396c..3a540ec 100644
--- a/tests/Ratchet/Tests/Http/HtpRequestParserTest.php
+++ b/tests/Ratchet/Tests/Http/HttpRequestParserTest.php
@@ -31,7 +31,7 @@ class HttpRequestParserTest extends \PHPUnit_Framework_TestCase {
     }
 
     public function testBufferOverflowResponse() {
-        $conn = $this->getMock('\\Ratchet\\ConnectionInterface');
+        $conn = $this->getMock('\Ratchet\ConnectionInterface');
 
         $this->parser->maxSize = 20;
 
@@ -41,4 +41,11 @@ class HttpRequestParserTest extends \PHPUnit_Framework_TestCase {
 
         $this->parser->onMessage($conn, "Header-Is: Too Big");
     }
+
+    public function testReturnTypeIsRequest() {
+        $conn = $this->getMock('\Ratchet\ConnectionInterface');
+        $return = $this->parser->onMessage($conn, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n");
+
+        $this->assertInstanceOf('\Guzzle\Http\Message\RequestInterface', $return);
+    }
 }
\ No newline at end of file
diff --git a/tests/Ratchet/Tests/Http/HttpServerTest.php b/tests/Ratchet/Tests/Http/HttpServerTest.php
index c7fef74..203172a 100644
--- a/tests/Ratchet/Tests/Http/HttpServerTest.php
+++ b/tests/Ratchet/Tests/Http/HttpServerTest.php
@@ -30,4 +30,35 @@ class HttpServerTest extends AbstractMessageComponentTestCase {
         $this->_app->expects($this->once())->method('onOpen')->with($this->isExpectedConnection());
         $this->_serv->onMessage($this->_conn, $headers);
     }
+
+    public function testOnMessageAfterHeaders() {
+        $headers = "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n";
+        $this->_conn->httpHeadersReceived = false;
+        $this->_serv->onMessage($this->_conn, $headers);
+
+        $message = "Hello World!";
+        $this->_app->expects($this->once())->method('onMessage')->with($this->isExpectedConnection(), $message);
+        $this->_serv->onMessage($this->_conn, $message);
+    }
+
+    public function testBufferOverflow() {
+        $this->_conn->expects($this->once())->method('close');
+        $this->_conn->httpHeadersReceived = false;
+
+        $this->_serv->onMessage($this->_conn, str_repeat('a', 5000));
+    }
+
+    public function testCloseIfNotEstablished() {
+        $this->_conn->httpHeadersReceived = false;
+        $this->_conn->expects($this->once())->method('close');
+        $this->_serv->onError($this->_conn, new \Exception('Whoops!'));
+    }
+
+    public function testBufferHeaders() {
+        $this->_conn->httpHeadersReceived = false;
+        $this->_app->expects($this->never())->method('onOpen');
+        $this->_app->expects($this->never())->method('onMessage');
+
+        $this->_serv->onMessage($this->_conn, "GET / HTTP/1.1");
+    }
 }
\ No newline at end of file
diff --git a/tests/Ratchet/Tests/Session/SessionComponentTest.php b/tests/Ratchet/Tests/Session/SessionComponentTest.php
index 4b4b41d..290e7dd 100644
--- a/tests/Ratchet/Tests/Session/SessionComponentTest.php
+++ b/tests/Ratchet/Tests/Session/SessionComponentTest.php
@@ -22,6 +22,10 @@ class SessionProviderTest extends AbstractMessageComponentTestCase {
         $this->_serv = new SessionProvider($this->_app, new NullSessionHandler);
     }
 
+    public function tearDown() {
+        ini_set('session.serialize_handler', 'php');
+    }
+
     public function getConnectionClassString() {
         return '\Ratchet\ConnectionInterface';
     }
@@ -89,9 +93,9 @@ class SessionProviderTest extends AbstractMessageComponentTestCase {
     }
 
     protected function newConn() {
-        $conn = $this->getMock('Ratchet\\ConnectionInterface');
+        $conn = $this->getMock('Ratchet\ConnectionInterface');
 
-        $headers = $this->getMock('Guzzle\\Http\\Message\\Request', array('getCookie'), array('POST', '/', array()));
+        $headers = $this->getMock('Guzzle\Http\Message\Request', array('getCookie'), array('POST', '/', array()));
         $headers->expects($this->once())->method('getCookie', array(ini_get('session.name')))->will($this->returnValue(null));
 
         $conn->WebSocket          = new \StdClass;
@@ -100,6 +104,12 @@ class SessionProviderTest extends AbstractMessageComponentTestCase {
         return $conn;
     }
 
+    public function testOnMessageDecorator() {
+        $message = "Database calls are usually blocking  :(";
+        $this->_app->expects($this->once())->method('onMessage')->with($this->isExpectedConnection(), $message);
+        $this->_serv->onMessage($this->_conn, $message);
+    }
+
     public function testGetSubProtocolsReturnsArray() {
         $mock = $this->getMock('Ratchet\\MessageComponentInterface');
         $comp = new SessionProvider($mock, new NullSessionHandler);
@@ -114,4 +124,10 @@ class SessionProviderTest extends AbstractMessageComponentTestCase {
 
         $this->assertGreaterThanOrEqual(2, count($comp->getSubProtocols()));
     }
+
+    public function testRejectInvalidSeralizers() {
+        ini_set('session.serialize_handler', 'wddx');
+        $this->setExpectedException('\RuntimeException');
+        new SessionProvider($this->getMock('\Ratchet\MessageComponentInterface'), $this->getMock('\SessionHandlerInterface'));
+    }
 }
\ No newline at end of file

From 4c1073883a3465c438f7e5b225cb203972122685 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sun, 28 Apr 2013 15:58:22 -0400
Subject: [PATCH 20/48] [Tests] Skip serializer if not available (TravisCI)

---
 tests/Ratchet/Tests/Session/SessionComponentTest.php | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tests/Ratchet/Tests/Session/SessionComponentTest.php b/tests/Ratchet/Tests/Session/SessionComponentTest.php
index 290e7dd..b97d273 100644
--- a/tests/Ratchet/Tests/Session/SessionComponentTest.php
+++ b/tests/Ratchet/Tests/Session/SessionComponentTest.php
@@ -126,6 +126,10 @@ class SessionProviderTest extends AbstractMessageComponentTestCase {
     }
 
     public function testRejectInvalidSeralizers() {
+        if (!function_exists('wddx_serialize_value')) {
+            $this->markTestSkipped();
+        }
+
         ini_set('session.serialize_handler', 'wddx');
         $this->setExpectedException('\RuntimeException');
         new SessionProvider($this->getMock('\Ratchet\MessageComponentInterface'), $this->getMock('\SessionHandlerInterface'));

From ec9bef4ee1419e656715488a177e7779c5b9743f Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Tue, 30 Apr 2013 21:09:49 -0400
Subject: [PATCH 21/48] [Http] Router tests

---
 tests/Ratchet/Tests/Http/RouterTest.php | 84 +++++++++++++++++++++++++
 1 file changed, 84 insertions(+)
 create mode 100644 tests/Ratchet/Tests/Http/RouterTest.php

diff --git a/tests/Ratchet/Tests/Http/RouterTest.php b/tests/Ratchet/Tests/Http/RouterTest.php
new file mode 100644
index 0000000..cc3309b
--- /dev/null
+++ b/tests/Ratchet/Tests/Http/RouterTest.php
@@ -0,0 +1,84 @@
+<?php
+namespace Ratchet\Tests\Http;
+use Ratchet\Http\Router;
+use Symfony\Component\Routing\Exception\ResourceNotFoundException;
+
+/**
+ * @covers Ratchet\Http\Router
+ */
+class RouterTest extends \PHPUnit_Framework_TestCase {
+    protected $_router;
+    protected $_matcher;
+    protected $_conn;
+    protected $_req;
+
+    public function setUp() {
+        $this->_conn    = $this->getMock('\Ratchet\ConnectionInterface');
+        $this->_req     = $this->getMock('\Guzzle\Http\Message\RequestInterface');
+        $this->_matcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface');
+        $this->_router  = new Router($this->_matcher);
+
+        $this->_req->expects($this->any())->method('getPath')->will($this->returnValue('/whatever'));
+    }
+
+    public function testFourOhFour() {
+        $this->_conn->expects($this->once())->method('close');
+
+        $nope = new ResourceNotFoundException;
+        $this->_matcher->expects($this->any())->method('match')->will($this->throwException($nope));
+
+        $this->_router->onOpen($this->_conn, $this->_req);
+    }
+
+    public function testNullRequest() {
+        $this->setExpectedException('\UnexpectedValueException');
+        $this->_router->onOpen($this->_conn);
+    }
+
+    public function testControllerIsMessageComponentInterface() {
+        $this->setExpectedException('\UnexpectedValueException');
+        $this->_matcher->expects($this->any())->method('match')->will($this->returnValue(array('_controller' => new \StdClass)));
+        $this->_router->onOpen($this->_conn, $this->_req);
+    }
+
+    public function testControllerOnOpen() {
+        $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock();
+        $this->_matcher->expects($this->any())->method('match')->will($this->returnValue(array('_controller' => $controller)));
+        $this->_router->onOpen($this->_conn, $this->_req);
+
+        $expectedConn = new \PHPUnit_Framework_Constraint_IsInstanceOf('\Ratchet\ConnectionInterface');
+        $controller->expects($this->once())->method('onOpen')->with($expectedConn, $this->_req);
+
+        $this->_matcher->expects($this->any())->method('match')->will($this->returnValue(array('_controller' => $controller)));
+        $this->_router->onOpen($this->_conn, $this->_req);
+    }
+
+    public function testControllerOnMessageBubbles() {
+        $message = "The greatest trick the Devil ever pulled was convincing the world he didn't exist";
+        $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock();
+        $controller->expects($this->once())->method('onMessage')->with($this->_conn, $message);
+
+        $this->_conn->controller = $controller;
+
+        $this->_router->onMessage($this->_conn, $message);
+    }
+
+    public function testControllerOnCloseBubbles() {
+        $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock();
+        $controller->expects($this->once())->method('onClose')->with($this->_conn);
+
+        $this->_conn->controller = $controller;
+
+        $this->_router->onClose($this->_conn);
+    }
+
+    public function testControllerOnErrorBubbles() {
+        $e= new \Exception('One cannot be betrayed if one has no exceptions');
+        $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock();
+        $controller->expects($this->once())->method('onError')->with($this->_conn, $e);
+
+        $this->_conn->controller = $controller;
+
+        $this->_router->onError($this->_conn, $e);
+    }
+}

From 1622caadada49c42a1f0a1cf4b83afff130934a8 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Tue, 30 Apr 2013 21:24:39 -0400
Subject: [PATCH 22/48] [Http][Router] Fixed bugs found from unit tests

---
 src/Ratchet/Http/Router.php | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/src/Ratchet/Http/Router.php b/src/Ratchet/Http/Router.php
index e1c1f6d..08e0c1a 100644
--- a/src/Ratchet/Http/Router.php
+++ b/src/Ratchet/Http/Router.php
@@ -2,6 +2,7 @@
 namespace Ratchet\Http;
 use Ratchet\ConnectionInterface;
 use Guzzle\Http\Message\RequestInterface;
+use Guzzle\Http\Message\Response;
 use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
 use Symfony\Component\Routing\Exception\MethodNotAllowedException;
 use Symfony\Component\Routing\Exception\ResourceNotFoundException;
@@ -18,6 +19,7 @@ class Router implements HttpServerInterface {
 
     /**
      * {@inheritdoc}
+     * @throws \UnexpectedValueException If a controller is not \Ratchet\Http\HttpServerInterface
      */
     public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) {
         if (null === $request) {
@@ -27,9 +29,9 @@ class Router implements HttpServerInterface {
         try {
             $route = $this->_matcher->match($request->getPath());
         } catch (MethodNotAllowedException $nae) {
-            return $this->close($from, 403);
+            return $this->close($conn, 403);
         } catch (ResourceNotFoundException $nfe) {
-            return $this->close($from, 404);
+            return $this->close($conn, 404);
         }
 
         if (is_string($route['_controller']) && class_exists($route['_controller'])) {
@@ -37,7 +39,7 @@ class Router implements HttpServerInterface {
         }
 
         if (!($route['_controller'] instanceof HttpServerInterface)) {
-            throw new \UnexpectedValueException('All routes must implement Ratchet\HttpServerInterface');
+            throw new \UnexpectedValueException('All routes must implement Ratchet\Http\HttpServerInterface');
         }
 
         $conn->controller = $route['_controller'];
@@ -64,4 +66,19 @@ class Router implements HttpServerInterface {
     function onError(ConnectionInterface $conn, \Exception $e) {
         $conn->controller->onError($conn, $e);
     }
+
+    /**
+     * Close a connection with an HTTP response
+     * @param \Ratchet\ConnectionInterface $conn
+     * @param int                          $code HTTP status code
+     * @return null
+     */
+    protected function close(ConnectionInterface $conn, $code = 400) {
+        $response = new Response($code, array(
+            'X-Powered-By' => \Ratchet\VERSION
+        ));
+
+        $conn->send((string)$response);
+        $conn->close();
+    }
 }
\ No newline at end of file

From 8c05486740ddab2af54221bf7fdc9998cc62609c Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Tue, 30 Apr 2013 21:30:16 -0400
Subject: [PATCH 23/48] [Server] Full coverage on flash

---
 .../Tests/Server/FlashPolicyComponentTest.php        | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/tests/Ratchet/Tests/Server/FlashPolicyComponentTest.php b/tests/Ratchet/Tests/Server/FlashPolicyComponentTest.php
index 15fb45d..60088b4 100644
--- a/tests/Ratchet/Tests/Server/FlashPolicyComponentTest.php
+++ b/tests/Ratchet/Tests/Server/FlashPolicyComponentTest.php
@@ -137,4 +137,16 @@ class FlashPolicyTest extends \PHPUnit_Framework_TestCase {
 
         $this->_policy->onMessage($conn, ' ');
     }
+
+    public function testOnOpenExists() {
+        $this->assertTrue(method_exists($this->_policy, 'onOpen'));
+        $conn = $this->getMock('\Ratchet\ConnectionInterface');
+        $this->_policy->onOpen($conn);
+    }
+
+    public function testOnCloseExists() {
+        $this->assertTrue(method_exists($this->_policy, 'onClose'));
+        $conn = $this->getMock('\Ratchet\ConnectionInterface');
+        $this->_policy->onClose($conn);
+    }
 }
\ No newline at end of file

From cd0efed085d386bc6f20488780bc065719111b98 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Wed, 1 May 2013 19:42:15 -0400
Subject: [PATCH 24/48] Set $conn->remoteAddress if proxy forwarded

Refs #89
---
 src/Ratchet/Http/HttpServer.php           | 4 ++++
 src/Ratchet/WebSocket/Version/HyBi10.php  | 3 ++-
 src/Ratchet/WebSocket/Version/RFC6455.php | 4 ++--
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/Ratchet/Http/HttpServer.php b/src/Ratchet/Http/HttpServer.php
index 5788807..4568067 100644
--- a/src/Ratchet/Http/HttpServer.php
+++ b/src/Ratchet/Http/HttpServer.php
@@ -50,6 +50,10 @@ class HttpServer implements MessageComponentInterface {
 
             $from->httpHeadersReceived = true;
 
+            if ($request->hasHeader('X-Forwarded-For')) {
+                $from->remoteAddress = $request->getHeader('X-Forwarded-For', true);
+            }
+
             return $this->_httpServer->onOpen($from, $request);
         }
 
diff --git a/src/Ratchet/WebSocket/Version/HyBi10.php b/src/Ratchet/WebSocket/Version/HyBi10.php
index f557a18..5d89078 100644
--- a/src/Ratchet/WebSocket/Version/HyBi10.php
+++ b/src/Ratchet/WebSocket/Version/HyBi10.php
@@ -4,7 +4,8 @@ use Guzzle\Http\Message\RequestInterface;
 
 class HyBi10 extends RFC6455 {
     public function isProtocol(RequestInterface $request) {
-        $version = (int)$request->getHeader('Sec-WebSocket-Version', -1);
+        $version = $request->hasHeader('Sec-WebSocket-Version') ? (int)$request->getHeader('Sec-WebSocket-Version', true) : -1;
+
         return ($version >= 6 && $version < 13);
     }
 
diff --git a/src/Ratchet/WebSocket/Version/RFC6455.php b/src/Ratchet/WebSocket/Version/RFC6455.php
index 94416c3..22a96a0 100644
--- a/src/Ratchet/WebSocket/Version/RFC6455.php
+++ b/src/Ratchet/WebSocket/Version/RFC6455.php
@@ -50,7 +50,7 @@ class RFC6455 implements VersionInterface {
      * {@inheritdoc}
      */
     public function isProtocol(RequestInterface $request) {
-        $version = (int)$request->getHeader('Sec-WebSocket-Version', -1);
+        $version = $request->hasHeader('Sec-WebSocket-Version') ? (int)$request->getHeader('Sec-WebSocket-Version', true) : -1;
 
         return ($this->getVersionNumber() === $version);
     }
@@ -73,7 +73,7 @@ class RFC6455 implements VersionInterface {
         return new Response(101, array(
             'Upgrade'              => 'websocket'
           , 'Connection'           => 'Upgrade'
-          , 'Sec-WebSocket-Accept' => $this->sign($request->getHeader('Sec-WebSocket-Key'))
+          , 'Sec-WebSocket-Accept' => $this->sign($request->getHeader('Sec-WebSocket-Key', true))
         ));
     }
 

From 1ff7998f586e90a2f0e1a0f55afabc67c11b749d Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Thu, 2 May 2013 19:17:47 -0400
Subject: [PATCH 25/48] [Http] Only update remoteAddress if local and header

---
 src/Ratchet/Http/HttpServer.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Ratchet/Http/HttpServer.php b/src/Ratchet/Http/HttpServer.php
index 4568067..1ce78a8 100644
--- a/src/Ratchet/Http/HttpServer.php
+++ b/src/Ratchet/Http/HttpServer.php
@@ -50,7 +50,7 @@ class HttpServer implements MessageComponentInterface {
 
             $from->httpHeadersReceived = true;
 
-            if ($request->hasHeader('X-Forwarded-For')) {
+            if (isset($from->remoteAddress) && '127.0.0.1' == $from->remoteAddress && $request->hasHeader('X-Forwarded-For')) {
                 $from->remoteAddress = $request->getHeader('X-Forwarded-For', true);
             }
 

From 37d13393596bdfb125db4c5377938d5b5ac92ce9 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Wed, 8 May 2013 20:31:01 -0400
Subject: [PATCH 26/48] [Tests] Refactor AB Fuzzing

AbFuzzyServer is now first class EchoServer
Updated meta files
Cleaned up a WAMP unit test slightly
composer alpha7
---
 CHANGELOG.md                                  |  6 +--
 Makefile                                      |  6 +--
 README.md                                     |  2 +-
 composer.lock                                 | 48 +++++++++----------
 .../Ratchet/Server/EchoServer.php             |  4 +-
 .../bin/fuzzingserver-libev.php               |  2 +-
 .../bin/fuzzingserver-libevent.php            |  2 +-
 .../bin/fuzzingserver-libuv.php               |  2 +-
 .../bin/fuzzingserver-noutf8.php              |  2 +-
 .../bin/fuzzingserver-stream.php              |  2 +-
 .../AutobahnTestSuite/fuzzingclient-all.json  |  8 ++--
 tests/Ratchet/Tests/Server/EchoServerTest.php | 26 ++++++++++
 tests/Ratchet/Tests/Wamp/TopicManagerTest.php | 12 ++++-
 13 files changed, 76 insertions(+), 46 deletions(-)
 rename tests/Ratchet/Tests/AbFuzzyServer.php => src/Ratchet/Server/EchoServer.php (83%)
 create mode 100644 tests/Ratchet/Tests/Server/EchoServerTest.php

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e0771e2..cada583 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,9 +10,9 @@ CHANGELOG
 
 * 0.3.0 (2013-xx-xx)
 
- * BC: Require hostname and do Origin HTTP header check against it by default, helping prevent CSRF attacks
- * Added HTTP Router component to allowing for a single Ratchet server to handle multiple apps
- * BC: Decoupled HTTP from WebSocket component
+ * Added Symfony/2.2 based HTTP Router component to allowing for a single Ratchet server to handle multiple apps -> Ratchet\Http\Router
+ * BC: Decoupled HTTP from WebSocket component -> Ratchet\Http\HttpServer
+ * Updated dependency to React/0.3
 
 * 0.2.5 (2013-04-01)
 
diff --git a/Makefile b/Makefile
index d5e12a2..3a1ac95 100644
--- a/Makefile
+++ b/Makefile
@@ -8,10 +8,8 @@ cover:
 	phpunit --coverage-text --coverage-html=reports/coverage
 
 abtests:
-	ulimit -n 2048 && php tests/AutobahnTestSuite/bin/fuzzingserver-libevent.php 8002 &
-	ulimit -n 2048 && php tests/AutobahnTestSuite/bin/fuzzingserver-stream.php 8001 &
-	ulimit -n 2048 && php tests/AutobahnTestSuite/bin/fuzzingserver-libev.php 8004 &
-	ulimit -n 2048 && php tests/AutobahnTestSuite/bin/fuzzingserver-libuv.php 8005 &
+	ulimit -n 2048 && php tests/AutobahnTestSuite/bin/fuzzingserver-libevent.php 8001 &
+	ulimit -n 2048 && php tests/AutobahnTestSuite/bin/fuzzingserver-stream.php 8002 &
 	ulimit -n 2048 && php tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php 8003 &
 	wstest -m testeeserver -w ws://localhost:8000 &
 	wstest -m fuzzingclient -s tests/AutobahnTestSuite/fuzzingclient-all.json
diff --git a/README.md b/README.md
index 3f78953..aa60b78 100644
--- a/README.md
+++ b/README.md
@@ -17,10 +17,10 @@ Shell access is required and root access is recommended.
 To avoid proxy/firewall blockage it's recommended WebSockets are run on port 80, which requires root access. 
 In order to do this, along with your sync web stack, you can either use a proxy or two separate machines. You can find more details in the [server conf docs](http://socketo.me/docs/deploy#sconf).
 
-PHP 5.3.3 (or higher) is required. If you have access, PHP 5.4 is *highly* recommended for its performance improvements. 
 
 Cookies from your domain will be passed to the socket server, allowing you to identify users.
 Accessing your website's session data in Ratchet requires you to use [Symfony2 Sessions](http://symfony.com/doc/master/components/http_foundation/sessions.html) on your website. 
+PHP 5.3.9 (or higher) is required. If you have access, PHP 5.4 is *highly* recommended for its performance improvements.
 
 ### Documentation
 
diff --git a/composer.lock b/composer.lock
index f7408e1..e12161a 100644
--- a/composer.lock
+++ b/composer.lock
@@ -46,17 +46,17 @@
         },
         {
             "name": "guzzle/common",
-            "version": "v3.4.1",
+            "version": "v3.4.3",
             "target-dir": "Guzzle/Common",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/common.git",
-                "reference": "v3.4.1"
+                "reference": "v3.4.3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/common/zipball/v3.4.1",
-                "reference": "v3.4.1",
+                "url": "https://api.github.com/repos/guzzle/common/zipball/v3.4.3",
+                "reference": "v3.4.3",
                 "shasum": ""
             },
             "require": {
@@ -66,7 +66,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.3-dev"
+                    "dev-master": "3.4-dev"
                 }
             },
             "autoload": {
@@ -86,21 +86,21 @@
                 "event",
                 "exception"
             ],
-            "time": "2013-04-16 20:56:26"
+            "time": "2013-04-30 20:30:19"
         },
         {
             "name": "guzzle/http",
-            "version": "v3.4.1",
+            "version": "v3.4.3",
             "target-dir": "Guzzle/Http",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/http.git",
-                "reference": "v3.4.1"
+                "reference": "v3.4.3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/http/zipball/v3.4.1",
-                "reference": "v3.4.1",
+                "url": "https://api.github.com/repos/guzzle/http/zipball/v3.4.3",
+                "reference": "v3.4.3",
                 "shasum": ""
             },
             "require": {
@@ -115,7 +115,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.3-dev"
+                    "dev-master": "3.4-dev"
                 }
             },
             "autoload": {
@@ -143,21 +143,21 @@
                 "http",
                 "http client"
             ],
-            "time": "2013-04-16 20:27:11"
+            "time": "2013-04-30 20:30:19"
         },
         {
             "name": "guzzle/parser",
-            "version": "v3.4.1",
+            "version": "v3.4.3",
             "target-dir": "Guzzle/Parser",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/parser.git",
-                "reference": "v3.4.1"
+                "reference": "v3.4.3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/parser/zipball/v3.4.1",
-                "reference": "v3.4.1",
+                "url": "https://api.github.com/repos/guzzle/parser/zipball/v3.4.3",
+                "reference": "v3.4.3",
                 "shasum": ""
             },
             "require": {
@@ -166,7 +166,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.3-dev"
+                    "dev-master": "3.4-dev"
                 }
             },
             "autoload": {
@@ -187,21 +187,21 @@
                 "message",
                 "url"
             ],
-            "time": "2013-03-07 22:13:59"
+            "time": "2013-04-26 15:47:38"
         },
         {
             "name": "guzzle/stream",
-            "version": "v3.4.1",
+            "version": "v3.4.3",
             "target-dir": "Guzzle/Stream",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/stream.git",
-                "reference": "v3.4.1"
+                "reference": "v3.4.3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/stream/zipball/v3.4.1",
-                "reference": "v3.4.1",
+                "url": "https://api.github.com/repos/guzzle/stream/zipball/v3.4.3",
+                "reference": "v3.4.3",
                 "shasum": ""
             },
             "require": {
@@ -214,7 +214,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.3-dev"
+                    "dev-master": "3.4-dev"
                 }
             },
             "autoload": {
@@ -240,7 +240,7 @@
                 "component",
                 "stream"
             ],
-            "time": "2013-04-06 18:28:51"
+            "time": "2013-04-26 15:47:38"
         },
         {
             "name": "react/event-loop",
diff --git a/tests/Ratchet/Tests/AbFuzzyServer.php b/src/Ratchet/Server/EchoServer.php
similarity index 83%
rename from tests/Ratchet/Tests/AbFuzzyServer.php
rename to src/Ratchet/Server/EchoServer.php
index 025cb4b..3f5069b 100644
--- a/tests/Ratchet/Tests/AbFuzzyServer.php
+++ b/src/Ratchet/Server/EchoServer.php
@@ -1,9 +1,9 @@
 <?php
-namespace Ratchet\Tests;
+namespace Ratchet\Server;
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
 
-class AbFuzzyServer implements MessageComponentInterface {
+class EchoServer implements MessageComponentInterface {
     public function onOpen(ConnectionInterface $conn) {
     }
 
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-libev.php b/tests/AutobahnTestSuite/bin/fuzzingserver-libev.php
index fb6d03f..b3dec26 100644
--- a/tests/AutobahnTestSuite/bin/fuzzingserver-libev.php
+++ b/tests/AutobahnTestSuite/bin/fuzzingserver-libev.php
@@ -4,7 +4,7 @@
 
     $loop = new React\EventLoop\LibEvLoop;
     $sock = new React\Socket\Server($loop);
-    $app  = new Ratchet\Http\HttpServer(new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer));
+    $app  = new Ratchet\Http\HttpServer(new Ratchet\WebSocket\WsServer(new Ratchet\Server\EchoServer));
 
     $port = $argc > 1 ? $argv[1] : 8000;
     $sock->listen($port, '0.0.0.0');
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-libevent.php b/tests/AutobahnTestSuite/bin/fuzzingserver-libevent.php
index ea1fbad..729e7d7 100644
--- a/tests/AutobahnTestSuite/bin/fuzzingserver-libevent.php
+++ b/tests/AutobahnTestSuite/bin/fuzzingserver-libevent.php
@@ -4,7 +4,7 @@
 
     $loop = new React\EventLoop\LibEventLoop;
     $sock = new React\Socket\Server($loop);
-    $app  = new Ratchet\Http\HttpServer(new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer));
+    $app  = new Ratchet\Http\HttpServer(new Ratchet\WebSocket\WsServer(new Ratchet\Server\EchoServer));
 
     $port = $argc > 1 ? $argv[1] : 8000;
     $sock->listen($port, '0.0.0.0');
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-libuv.php b/tests/AutobahnTestSuite/bin/fuzzingserver-libuv.php
index fb6d03f..b3dec26 100644
--- a/tests/AutobahnTestSuite/bin/fuzzingserver-libuv.php
+++ b/tests/AutobahnTestSuite/bin/fuzzingserver-libuv.php
@@ -4,7 +4,7 @@
 
     $loop = new React\EventLoop\LibEvLoop;
     $sock = new React\Socket\Server($loop);
-    $app  = new Ratchet\Http\HttpServer(new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer));
+    $app  = new Ratchet\Http\HttpServer(new Ratchet\WebSocket\WsServer(new Ratchet\Server\EchoServer));
 
     $port = $argc > 1 ? $argv[1] : 8000;
     $sock->listen($port, '0.0.0.0');
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php b/tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php
index b20b3a1..01205f5 100644
--- a/tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php
+++ b/tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php
@@ -4,7 +4,7 @@
 
     $loop = new React\EventLoop\StreamSelectLoop;
     $sock = new React\Socket\Server($loop);
-    $web  = new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer);
+    $web  = new Ratchet\WebSocket\WsServer(new Ratchet\Server\EchoServer);
     $app  = new Ratchet\Http\HttpServer($web);
     $web->setEncodingChecks(false);
 
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-stream.php b/tests/AutobahnTestSuite/bin/fuzzingserver-stream.php
index 98b4448..b10dc10 100644
--- a/tests/AutobahnTestSuite/bin/fuzzingserver-stream.php
+++ b/tests/AutobahnTestSuite/bin/fuzzingserver-stream.php
@@ -4,7 +4,7 @@
 
     $loop = new React\EventLoop\StreamSelectLoop;
     $sock = new React\Socket\Server($loop);
-    $app  = new Ratchet\Http\HttpServer(new Ratchet\WebSocket\WsServer(new Ratchet\Tests\AbFuzzyServer));
+    $app  = new Ratchet\Http\HttpServer(new Ratchet\WebSocket\WsServer(new Ratchet\Server\EchoyServer));
 
     $port = $argc > 1 ? $argv[1] : 8000;
     $sock->listen($port, '0.0.0.0');
diff --git a/tests/AutobahnTestSuite/fuzzingclient-all.json b/tests/AutobahnTestSuite/fuzzingclient-all.json
index 8ebe6d8..5dbd204 100644
--- a/tests/AutobahnTestSuite/fuzzingclient-all.json
+++ b/tests/AutobahnTestSuite/fuzzingclient-all.json
@@ -3,11 +3,9 @@
   , "outdir": "reports/ab"
 
   , "servers": [
-        {"agent": "Ratchet/0.2.5 libevent", "url": "ws://localhost:8002", "options": {"version": 18}}
-      , {"agent": "Ratchet/0.2.5 libuv", "url": "ws://localhost:8005", "options": {"version": 18}}
-      , {"agent": "Ratchet/0.2.5 libev", "url": "ws://localhost:8004", "options": {"version": 18}}
-      , {"agent": "Ratchet/0.2.5 -utf8", "url": "ws://localhost:8003", "options": {"version": 18}}
-      , {"agent": "Ratchet/0.2.5 streams", "url": "ws://localhost:8001", "options": {"version": 18}}
+        {"agent": "Ratchet/0.3 libevent", "url": "ws://localhost:8001", "options": {"version": 18}}
+      , {"agent": "Ratchet/0.3 streams", "url": "ws://localhost:8002", "options": {"version": 18}}
+      , {"agent": "Ratchet/0.3 -utf8", "url": "ws://localhost:8003", "options": {"version": 18}}
       , {"agent": "AutobahnTestSuite/0.5.9", "url": "ws://localhost:8000", "options": {"version": 18}}
     ]
 
diff --git a/tests/Ratchet/Tests/Server/EchoServerTest.php b/tests/Ratchet/Tests/Server/EchoServerTest.php
new file mode 100644
index 0000000..4910dad
--- /dev/null
+++ b/tests/Ratchet/Tests/Server/EchoServerTest.php
@@ -0,0 +1,26 @@
+<?php
+namespace Ratchet\Tests\Server;
+use Ratchet\Server\EchoServer;
+
+class EchoServerTest extends \PHPUnit_Framework_TestCase {
+    protected $_conn;
+    protected $_comp;
+
+    public function setUp() {
+        $this->_conn = $this->getMock('\Ratchet\ConnectionInterface');
+        $this->_comp = new EchoServer;
+    }
+
+    public function testMessageEchod() {
+        $message = 'Tillsonburg, my back still aches when I hear that word.';
+        $this->_conn->expects($this->once())->method('send')->with($message);
+        $this->_comp->onMessage($this->_conn, $message);
+    }
+
+    public function testErrorClosesConnection() {
+        ob_start();
+        $this->_conn->expects($this->once())->method('close');
+        $this->_comp->onError($this->_conn, new \Exception);
+        ob_end_clean();
+    }
+}
diff --git a/tests/Ratchet/Tests/Wamp/TopicManagerTest.php b/tests/Ratchet/Tests/Wamp/TopicManagerTest.php
index 8388550..3c00cd1 100644
--- a/tests/Ratchet/Tests/Wamp/TopicManagerTest.php
+++ b/tests/Ratchet/Tests/Wamp/TopicManagerTest.php
@@ -7,12 +7,20 @@ use Ratchet\Wamp\TopicManager;
  */
 class TopicManagerTest extends \PHPUnit_Framework_TestCase {
     private $mock;
+
+    /**
+     * @var \Ratchet\Wamp\TopicManager
+     */
     private $mngr;
+
+    /**
+     * @var \Ratchet\ConnectionInterface
+     */
     private $conn;
 
     public function setUp() {
-        $this->conn = $this->getMock('Ratchet\\ConnectionInterface');
-        $this->mock = $this->getMock('Ratchet\\Wamp\\WampServerInterface');
+        $this->conn = $this->getMock('\Ratchet\ConnectionInterface');
+        $this->mock = $this->getMock('\Ratchet\Wamp\\WampServerInterface');
         $this->mngr = new TopicManager($this->mock);
 
         $this->conn->WAMP = new \StdClass;

From 8b3591ce0d03c3ab325d73c353e055f6711d9f15 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Wed, 8 May 2013 20:42:49 -0400
Subject: [PATCH 27/48] App class

---
 CHANGELOG.md                          |  4 +-
 README.md                             | 13 ++--
 composer.lock                         |  1 +
 src/Ratchet/App.php                   | 96 +++++++++++++++++++++++++++
 src/Ratchet/Http/RoutedHttpServer.php | 65 ------------------
 5 files changed, 104 insertions(+), 75 deletions(-)
 create mode 100644 src/Ratchet/App.php
 delete mode 100644 src/Ratchet/Http/RoutedHttpServer.php

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cada583..aac7b5f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ CHANGELOG
 
 * 0.3.0 (2013-xx-xx)
 
+ * Sugar and spice and everything nice: Added the Ratchet\App class for ease of use
  * Added Symfony/2.2 based HTTP Router component to allowing for a single Ratchet server to handle multiple apps -> Ratchet\Http\Router
  * BC: Decoupled HTTP from WebSocket component -> Ratchet\Http\HttpServer
  * Updated dependency to React/0.3
@@ -79,4 +80,5 @@ CHANGELOG
 * 0.1 (2012-05-11)
 
  * First release with components: IoServer, WsServer, SessionProvider, WampServer, FlashPolicy, IpBlackList
- * I/O now handled by React, making Ratchet fully asynchronous 
\ No newline at end of file
+ * I/O now handled by React, making Ratchet fully asynchronous
+
diff --git a/README.md b/README.md
index ca1a448..767e45c 100644
--- a/README.md
+++ b/README.md
@@ -36,9 +36,6 @@ Need help?  Have a question?  Want to provide feedback?  Write a message on the
 <?php
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
-use Ratchet\Http\RoutedHttpServer;
-use Ratchet\Server\IoServer;
-use Ratchet\Tests\AbFuzzyServer;
 
     require __DIR__ . '/vendor/autoload.php';
 
@@ -75,12 +72,10 @@ class Chat implements MessageComponentInterface {
 }
 
     // Run the server application through the WebSocket protocol on port 8080
-    $router = new RoutedHttpServer;
-    $router->addRoute('/echo', new AbFuzzyServer);
-    $router->addRoute('/chat', new Chat);
-
-    $server = IoServer::factory($router, 8000);
-    $server->run();
+    $app = new Ratchet\App('example.com', 8080);
+    $app->route('/chat', new Chat);
+    $app->route('/echo', new Ratchet\Server\EchoServer);
+    $app->run();
 ```
 
     $ php chat.php
\ No newline at end of file
diff --git a/composer.lock b/composer.lock
index e12161a..f49c13e 100644
--- a/composer.lock
+++ b/composer.lock
@@ -28,6 +28,7 @@
                     "Evenement": "src"
                 }
             },
+            "notification-url": "https://packagist.org/downloads/",
             "license": [
                 "MIT"
             ],
diff --git a/src/Ratchet/App.php b/src/Ratchet/App.php
new file mode 100644
index 0000000..2aeca35
--- /dev/null
+++ b/src/Ratchet/App.php
@@ -0,0 +1,96 @@
+<?php
+namespace Ratchet;
+use React\EventLoop\LoopInterface;
+use React\EventLoop\Factory as LoopFactory;
+use React\Socket\Server as Reactor;
+use Ratchet\Http\HttpServerInterface;
+use Ratchet\Wamp\WampServerInterface;
+use Ratchet\Server\IoServer;
+use Ratchet\Server\FlashPolicy;
+use Ratchet\Http\HttpServer;
+use Ratchet\Http\Router;
+use Ratchet\WebSocket\WsServer;
+use Ratchet\Wamp\WampServer;
+use Symfony\Component\Routing\RouteCollection;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\Routing\RequestContext;
+use Symfony\Component\Routing\Matcher\UrlMatcher;
+
+/**
+ * @todo Security - same origin by default
+ */
+class App {
+    /**
+     * @var \Symfony\Component\Routing\RouteCollection
+     */
+    public $routes;
+
+    /**
+     * @var \Ratchet\Server\IoServer
+     */
+    public $flashServer;
+
+    /**
+     * @var \Ratchet\Server\IoServer
+     */
+    protected $_server;
+
+    /**
+     * @param string        $httpHost
+     * @param int           $port
+     * @param string        $address
+     * @param LoopInterface $loop
+     */
+    public function __construct($httpHost = 'localhost', $port = 8080, $address = '127.0.0.1', LoopInterface $loop = null) {
+        if (extension_loaded('xdebug')) {
+            echo "XDebug extension detected. Remember to disable this if performance testing or going live!\n";
+        }
+
+        if (null === $loop) {
+            $loop = LoopFactory::create();
+        }
+
+        $socket = new Reactor($loop);
+        $socket->listen($port, $address);
+
+        $this->routes  = new RouteCollection;
+        $this->_server = new IoServer(new HttpServer(new Router(new UrlMatcher($this->routes, new RequestContext))), $socket, $loop);
+
+        $policy = new FlashPolicy;
+        $policy->addAllowedAccess($httpHost, 80);
+        $policy->addAllowedAccess($httpHost, $port);
+        $flashSock = new Reactor($loop);
+        $this->flashServer = new IoServer($policy, $flashSock);
+
+        if (80 == $port) {
+            $flashSock->listen(843, '0.0.0.0');
+        } else {
+            $flashSock->listen(8843);
+        }
+    }
+
+    /**
+     * @param string             $path
+     * @param ComponentInterface $controller
+     * @return ComponentInterface
+     */
+    public function route($path, ComponentInterface $controller) {
+        if ($controller instanceof HttpServerInterface || $controller instanceof WsServer) {
+            $decorated = $controller;
+        } elseif ($controller instanceof WampServerInterface) {
+            $decorated = new WsServer(new WampServer($controller));
+        } elseif ($controller instanceof MessageComponentInterface) {
+            $decorated = new WsServer($controller);
+        } else {
+            $decorated = $controller;
+        }
+
+        $this->routes->add(uniqid(), new Route($path, array('_controller' => $decorated)));
+
+        return $decorated;
+    }
+
+    public function run() {
+        $this->_server->run();
+    }
+}
\ No newline at end of file
diff --git a/src/Ratchet/Http/RoutedHttpServer.php b/src/Ratchet/Http/RoutedHttpServer.php
deleted file mode 100644
index 728424c..0000000
--- a/src/Ratchet/Http/RoutedHttpServer.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-namespace Ratchet\Http;
-use Ratchet\MessageComponentInterface;
-use Ratchet\ConnectionInterface;
-use Ratchet\WebSocket\WsServer;
-use Symfony\Component\Routing\RouteCollection;
-use Symfony\Component\Routing\Route;
-use Symfony\Component\Routing\RequestContext;
-use Symfony\Component\Routing\Matcher\UrlMatcher;
-
-/**
- */
-class RoutedHttpServer implements MessageComponentInterface {
-    protected $_routes;
-    protected $_server;
-
-    public function __construct(RouteCollection $routes = null) {
-        if (null == $routes) {
-            $routes = new RouteCollection;
-        }
-
-        $this->_routes = $routes;
-        $this->_server = new HttpServer(new Router(new UrlMatcher($routes, new RequestContext)));
-    }
-
-    public function addRoute($path, MessageComponentInterface $controller) {
-        $this->_routes->add(uniqid(), new Route($path, array(
-            '_controller' => new WsServer($controller)
-        )));
-    }
-
-    public function addHttpRoute($path, HttpServerInterface $controller) {
-        $this->_routes->add(uniqid(), new Route($path, array(
-            '_controller' => $controller
-        )));
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    function onOpen(ConnectionInterface $conn) {
-        $this->_server->onOpen($conn);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    function onMessage(ConnectionInterface $from, $msg) {
-        $this->_server->onMessage($from, $msg);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    function onClose(ConnectionInterface $conn) {
-        $this->_server->onClose($conn);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    function onError(ConnectionInterface $conn, \Exception $e) {
-        $this->_server->onError($conn, $e);
-    }
-}
\ No newline at end of file

From f4ddea5f44bc64c06016acea9da80e5e87830a7a Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Wed, 29 May 2013 07:51:33 -0400
Subject: [PATCH 28/48] Removed updating remoteAddress via proxy header

---
 src/Ratchet/Http/HttpServer.php | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/Ratchet/Http/HttpServer.php b/src/Ratchet/Http/HttpServer.php
index 1ce78a8..5788807 100644
--- a/src/Ratchet/Http/HttpServer.php
+++ b/src/Ratchet/Http/HttpServer.php
@@ -50,10 +50,6 @@ class HttpServer implements MessageComponentInterface {
 
             $from->httpHeadersReceived = true;
 
-            if (isset($from->remoteAddress) && '127.0.0.1' == $from->remoteAddress && $request->hasHeader('X-Forwarded-For')) {
-                $from->remoteAddress = $request->getHeader('X-Forwarded-For', true);
-            }
-
             return $this->_httpServer->onOpen($from, $request);
         }
 

From 0edd37af3f98032c9f02c129297f493ef0553eac Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sun, 9 Jun 2013 14:09:57 -0400
Subject: [PATCH 29/48] Hostname check verification refs #102

host parameter of App now verified on incoming connections
---
 src/Ratchet/App.php                               | 15 ++++++++++-----
 src/Ratchet/Http/Router.php                       | 12 ++++++++++--
 .../bin/fuzzingserver-stream.php                  |  2 +-
 tests/Ratchet/Tests/Http/RouterTest.php           |  4 ++++
 4 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/src/Ratchet/App.php b/src/Ratchet/App.php
index 2aeca35..7382653 100644
--- a/src/Ratchet/App.php
+++ b/src/Ratchet/App.php
@@ -16,9 +16,6 @@ use Symfony\Component\Routing\Route;
 use Symfony\Component\Routing\RequestContext;
 use Symfony\Component\Routing\Matcher\UrlMatcher;
 
-/**
- * @todo Security - same origin by default
- */
 class App {
     /**
      * @var \Symfony\Component\Routing\RouteCollection
@@ -35,6 +32,12 @@ class App {
      */
     protected $_server;
 
+    /**
+     * The Host passed in construct used for same origin policy
+     * @var string
+     */
+    protected $httpHost;
+
     /**
      * @param string        $httpHost
      * @param int           $port
@@ -50,6 +53,8 @@ class App {
             $loop = LoopFactory::create();
         }
 
+        $this->httpHost = $httpHost;
+
         $socket = new Reactor($loop);
         $socket->listen($port, $address);
 
@@ -72,7 +77,7 @@ class App {
     /**
      * @param string             $path
      * @param ComponentInterface $controller
-     * @return ComponentInterface
+     * @return Symfony\Component\Routing\Route
      */
     public function route($path, ComponentInterface $controller) {
         if ($controller instanceof HttpServerInterface || $controller instanceof WsServer) {
@@ -85,7 +90,7 @@ class App {
             $decorated = $controller;
         }
 
-        $this->routes->add(uniqid(), new Route($path, array('_controller' => $decorated)));
+        $this->routes->add(uniqid(), new Route($path, array('_controller' => $decorated), array(), array(), $this->httpHost));
 
         return $decorated;
     }
diff --git a/src/Ratchet/Http/Router.php b/src/Ratchet/Http/Router.php
index 08e0c1a..8e6611e 100644
--- a/src/Ratchet/Http/Router.php
+++ b/src/Ratchet/Http/Router.php
@@ -26,6 +26,10 @@ class Router implements HttpServerInterface {
             throw new \UnexpectedValueException('$request can not be null');
         }
 
+        $context = $this->_matcher->getContext();
+        $context->setMethod($request->getMethod());
+        $context->setHost($request->getHost());
+
         try {
             $route = $this->_matcher->match($request->getPath());
         } catch (MethodNotAllowedException $nae) {
@@ -57,14 +61,18 @@ class Router implements HttpServerInterface {
      * {@inheritdoc}
      */
     function onClose(ConnectionInterface $conn) {
-        $conn->controller->onClose($conn);
+        if (isset($conn->controller)) {
+            $conn->controller->onClose($conn);
+        }
     }
 
     /**
      * {@inheritdoc}
      */
     function onError(ConnectionInterface $conn, \Exception $e) {
-        $conn->controller->onError($conn, $e);
+        if (isset($conn->controller)) {
+            $conn->controller->onError($conn, $e);
+        }
     }
 
     /**
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-stream.php b/tests/AutobahnTestSuite/bin/fuzzingserver-stream.php
index b10dc10..ae3db8d 100644
--- a/tests/AutobahnTestSuite/bin/fuzzingserver-stream.php
+++ b/tests/AutobahnTestSuite/bin/fuzzingserver-stream.php
@@ -4,7 +4,7 @@
 
     $loop = new React\EventLoop\StreamSelectLoop;
     $sock = new React\Socket\Server($loop);
-    $app  = new Ratchet\Http\HttpServer(new Ratchet\WebSocket\WsServer(new Ratchet\Server\EchoyServer));
+    $app  = new Ratchet\Http\HttpServer(new Ratchet\WebSocket\WsServer(new Ratchet\Server\EchoServer));
 
     $port = $argc > 1 ? $argv[1] : 8000;
     $sock->listen($port, '0.0.0.0');
diff --git a/tests/Ratchet/Tests/Http/RouterTest.php b/tests/Ratchet/Tests/Http/RouterTest.php
index cc3309b..30abfed 100644
--- a/tests/Ratchet/Tests/Http/RouterTest.php
+++ b/tests/Ratchet/Tests/Http/RouterTest.php
@@ -16,6 +16,10 @@ class RouterTest extends \PHPUnit_Framework_TestCase {
         $this->_conn    = $this->getMock('\Ratchet\ConnectionInterface');
         $this->_req     = $this->getMock('\Guzzle\Http\Message\RequestInterface');
         $this->_matcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface');
+        $this->_matcher
+            ->expects($this->any())
+            ->method('getContext')
+            ->will($this->returnValue($this->getMock('Symfony\Component\Routing\RequestContext')));
         $this->_router  = new Router($this->_matcher);
 
         $this->_req->expects($this->any())->method('getPath')->will($this->returnValue('/whatever'));

From e7541fdfcf6a1e27370be89dc14421457a0ea2ad Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sat, 15 Jun 2013 14:09:19 -0400
Subject: [PATCH 30/48] App uses counter for ID instead of random

---
 src/Ratchet/App.php | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/Ratchet/App.php b/src/Ratchet/App.php
index 7382653..6728c30 100644
--- a/src/Ratchet/App.php
+++ b/src/Ratchet/App.php
@@ -38,6 +38,8 @@ class App {
      */
     protected $httpHost;
 
+    protected $_routeCounter = 0;
+
     /**
      * @param string        $httpHost
      * @param int           $port
@@ -90,7 +92,7 @@ class App {
             $decorated = $controller;
         }
 
-        $this->routes->add(uniqid(), new Route($path, array('_controller' => $decorated), array(), array(), $this->httpHost));
+        $this->routes->add('rr-' . ++$this->_routeCounter, new Route($path, array('_controller' => $decorated), array(), array(), $this->httpHost));
 
         return $decorated;
     }

From a876770cda0b9ce96cd1bfc31d88116779dccc31 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sun, 16 Jun 2013 10:12:48 -0400
Subject: [PATCH 31/48] [Tests] Restructured test filesystem layout

---
 Makefile                                      | 16 +++++------
 composer.json                                 |  3 +-
 composer.lock                                 | 10 +++----
 phpunit.xml.dist                              | 13 ++++-----
 .../bin/fuzzingserver-libev.php               |  0
 .../bin/fuzzingserver-libevent.php            |  0
 .../bin/fuzzingserver-libuv.php               |  0
 .../bin/fuzzingserver-noutf8.php              |  0
 .../bin/fuzzingserver-stream.php              |  0
 .../fuzzingclient-all.json                    |  0
 .../fuzzingclient-profile.json                |  0
 .../fuzzingclient-quick.json                  |  0
 tests/bootstrap.php                           |  5 ++++
 .../AbstractMessageComponentTestCase.php      |  2 +-
 .../Ratchet}/Mock/Component.php               |  2 +-
 .../Ratchet}/Mock/Connection.php              |  2 +-
 .../Ratchet}/Mock/ConnectionDecorator.php     |  2 +-
 .../Ratchet}/Mock/WampComponent.php           |  2 +-
 .../Ratchet}/NullComponent.php                |  2 +-
 .../Wamp/Stub/WsWampServerInterface.php       |  2 +-
 .../Stub/WsMessageComponentInterface.php      |  2 +-
 .../AbstractConnectionDecoratorTest.php       |  4 +--
 .../Http/Message/RequestFactoryTest.php       |  2 +-
 .../Http/HttpRequestParserTest.php            |  2 +-
 .../Tests => unit}/Http/HttpServerTest.php    |  4 +--
 .../Tests => unit}/Http/RouterTest.php        |  2 +-
 .../Tests => unit}/Server/EchoServerTest.php  |  2 +-
 .../Server/FlashPolicyComponentTest.php       |  2 +-
 .../Server/IoConnectionTest.php               |  2 +-
 .../Tests => unit}/Server/IoServerTest.php    |  2 +-
 .../Server/IpBlackListComponentTest.php       |  2 +-
 .../Session/Serialize/PhpHandlerTest.php      |  2 +-
 .../Session/SessionComponentTest.php          | 10 +++----
 .../Wamp/ServerProtocolTest.php               |  6 ++--
 .../Tests => unit}/Wamp/TopicManagerTest.php  | 28 +++++++++----------
 .../Tests => unit}/Wamp/TopicTest.php         |  2 +-
 .../Wamp/WampConnectionTest.php               |  2 +-
 .../Tests => unit}/Wamp/WampServerTest.php    |  4 +--
 .../WebSocket/Version/Hixie76Test.php         |  2 +-
 .../WebSocket/Version/HyBi10Test.php          |  2 +-
 .../WebSocket/Version/RFC6455/FrameTest.php   |  2 +-
 .../Version/RFC6455/HandshakeVerifierTest.php |  2 +-
 .../WebSocket/Version/RFC6455/MessageTest.php |  2 +-
 .../WebSocket/Version/RFC6455Test.php         |  2 +-
 .../WebSocket/VersionManagerTest.php          |  2 +-
 .../Tests => unit}/WebSocket/WsServerTest.php |  4 +--
 46 files changed, 81 insertions(+), 78 deletions(-)
 rename tests/{AutobahnTestSuite => autobahn}/bin/fuzzingserver-libev.php (100%)
 rename tests/{AutobahnTestSuite => autobahn}/bin/fuzzingserver-libevent.php (100%)
 rename tests/{AutobahnTestSuite => autobahn}/bin/fuzzingserver-libuv.php (100%)
 rename tests/{AutobahnTestSuite => autobahn}/bin/fuzzingserver-noutf8.php (100%)
 rename tests/{AutobahnTestSuite => autobahn}/bin/fuzzingserver-stream.php (100%)
 rename tests/{AutobahnTestSuite => autobahn}/fuzzingclient-all.json (100%)
 rename tests/{AutobahnTestSuite => autobahn}/fuzzingclient-profile.json (100%)
 rename tests/{AutobahnTestSuite => autobahn}/fuzzingclient-quick.json (100%)
 create mode 100644 tests/bootstrap.php
 rename tests/{Ratchet/Tests => helpers/Ratchet}/AbstractMessageComponentTestCase.php (98%)
 rename tests/{Ratchet/Tests => helpers/Ratchet}/Mock/Component.php (96%)
 rename tests/{Ratchet/Tests => helpers/Ratchet}/Mock/Connection.php (92%)
 rename tests/{Ratchet/Tests => helpers/Ratchet}/Mock/ConnectionDecorator.php (93%)
 rename tests/{Ratchet/Tests => helpers/Ratchet}/Mock/WampComponent.php (97%)
 rename tests/{Ratchet/Tests/Mock => helpers/Ratchet}/NullComponent.php (96%)
 rename tests/{Ratchet/Tests => helpers/Ratchet}/Wamp/Stub/WsWampServerInterface.php (82%)
 rename tests/{Ratchet/Tests => helpers/Ratchet}/WebSocket/Stub/WsMessageComponentInterface.php (81%)
 rename tests/{Ratchet/Tests => unit}/AbstractConnectionDecoratorTest.php (98%)
 rename tests/{Ratchet/Tests => unit}/Http/Guzzle/Http/Message/RequestFactoryTest.php (97%)
 rename tests/{Ratchet/Tests => unit}/Http/HttpRequestParserTest.php (98%)
 rename tests/{Ratchet/Tests => unit}/Http/HttpServerTest.php (96%)
 rename tests/{Ratchet/Tests => unit}/Http/RouterTest.php (99%)
 rename tests/{Ratchet/Tests => unit}/Server/EchoServerTest.php (96%)
 rename tests/{Ratchet/Tests => unit}/Server/FlashPolicyComponentTest.php (99%)
 rename tests/{Ratchet/Tests => unit}/Server/IoConnectionTest.php (94%)
 rename tests/{Ratchet/Tests => unit}/Server/IoServerTest.php (99%)
 rename tests/{Ratchet/Tests => unit}/Server/IpBlackListComponentTest.php (99%)
 rename tests/{Ratchet/Tests => unit}/Session/Serialize/PhpHandlerTest.php (95%)
 rename tests/{Ratchet/Tests => unit}/Session/SessionComponentTest.php (95%)
 rename tests/{Ratchet/Tests => unit}/Wamp/ServerProtocolTest.php (98%)
 rename tests/{Ratchet/Tests => unit}/Wamp/TopicManagerTest.php (85%)
 rename tests/{Ratchet/Tests => unit}/Wamp/TopicTest.php (98%)
 rename tests/{Ratchet/Tests => unit}/Wamp/WampConnectionTest.php (98%)
 rename tests/{Ratchet/Tests => unit}/Wamp/WampServerTest.php (93%)
 rename tests/{Ratchet/Tests => unit}/WebSocket/Version/Hixie76Test.php (98%)
 rename tests/{Ratchet/Tests => unit}/WebSocket/Version/HyBi10Test.php (98%)
 rename tests/{Ratchet/Tests => unit}/WebSocket/Version/RFC6455/FrameTest.php (99%)
 rename tests/{Ratchet/Tests => unit}/WebSocket/Version/RFC6455/HandshakeVerifierTest.php (98%)
 rename tests/{Ratchet/Tests => unit}/WebSocket/Version/RFC6455/MessageTest.php (96%)
 rename tests/{Ratchet/Tests => unit}/WebSocket/Version/RFC6455Test.php (99%)
 rename tests/{Ratchet/Tests => unit}/WebSocket/VersionManagerTest.php (98%)
 rename tests/{Ratchet/Tests => unit}/WebSocket/WsServerTest.php (94%)

diff --git a/Makefile b/Makefile
index 3a1ac95..aa143cc 100644
--- a/Makefile
+++ b/Makefile
@@ -8,21 +8,21 @@ cover:
 	phpunit --coverage-text --coverage-html=reports/coverage
 
 abtests:
-	ulimit -n 2048 && php tests/AutobahnTestSuite/bin/fuzzingserver-libevent.php 8001 &
-	ulimit -n 2048 && php tests/AutobahnTestSuite/bin/fuzzingserver-stream.php 8002 &
-	ulimit -n 2048 && php tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php 8003 &
+	ulimit -n 2048 && php tests/autobahn/bin/fuzzingserver-libevent.php 8001 &
+	ulimit -n 2048 && php tests/autobahn/bin/fuzzingserver-stream.php 8002 &
+	ulimit -n 2048 && php tests/autobahn/bin/fuzzingserver-noutf8.php 8003 &
 	wstest -m testeeserver -w ws://localhost:8000 &
-	wstest -m fuzzingclient -s tests/AutobahnTestSuite/fuzzingclient-all.json
+	wstest -m fuzzingclient -s tests/autobahn/fuzzingclient-all.json
 	killall php wstest
 
 abtest:
-	ulimit -n 2048 && php tests/AutobahnTestSuite/bin/fuzzingserver-stream.php &
-	wstest -m fuzzingclient -s tests/AutobahnTestSuite/fuzzingclient-quick.json
+	ulimit -n 2048 && php tests/autobahn/bin/fuzzingserver-stream.php &
+	wstest -m fuzzingclient -s tests/autobahn/fuzzingclient-quick.json
 	killall php
 
 profile:
-	php -d 'xdebug.profiler_enable=1' tests/AutobahnTestSuite/bin/fuzzingserver-libevent.php &
-	wstest -m fuzzingclient -s tests/AutobahnTestSuite/fuzzingclient-profile.json
+	php -d 'xdebug.profiler_enable=1' tests/autobahn/bin/fuzzingserver-libevent.php &
+	wstest -m fuzzingclient -s tests/autobahn/fuzzingclient-profile.json
 	killall php
 
 apidocs:
diff --git a/composer.json b/composer.json
index a790d55..293c6be 100644
--- a/composer.json
+++ b/composer.json
@@ -20,8 +20,7 @@
     }
   , "autoload": {
         "psr-0": {
-            "Ratchet\\Tests": "tests"
-          , "Ratchet": "src"
+            "Ratchet": "src"
         }
     }
   , "require": {
diff --git a/composer.lock b/composer.lock
index a803718..1ed2a55 100644
--- a/composer.lock
+++ b/composer.lock
@@ -3,7 +3,7 @@
         "This file locks the dependencies of your project to a known state",
         "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
     ],
-    "hash": "d5a238bcdccc33fab13dd3c65b663beb",
+    "hash": "f5d2fe5b143f2c5d2e8f674dd2f6bc16",
     "packages": [
         {
             "name": "evenement/evenement",
@@ -429,17 +429,17 @@
         },
         {
             "name": "symfony/http-foundation",
-            "version": "v2.3.0",
+            "version": "v2.3.1",
             "target-dir": "Symfony/Component/HttpFoundation",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/HttpFoundation.git",
-                "reference": "v2.3.0-RC1"
+                "reference": "v2.3.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/v2.3.0-RC1",
-                "reference": "v2.3.0-RC1",
+                "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/v2.3.1",
+                "reference": "v2.3.1",
                 "shasum": ""
             },
             "require": {
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 78b3128..117227a 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -2,7 +2,7 @@
 <phpunit
     forceCoversAnnotation="true"
     mapTestClassNameToCoveredClassName="true"
-    bootstrap="vendor/autoload.php"
+    bootstrap="tests/bootstrap.php"
     colors="true"
     backupGlobals="false"
     backupStaticAttributes="false"
@@ -11,15 +11,14 @@
 >
 
     <testsuites>
-        <testsuite name="Ratchet Test Suite">
-            <directory>./tests/Ratchet/</directory>
+        <testsuite name="unit">
+            <directory>./tests/unit/</directory>
         </testsuite>
     </testsuites>
 
     <filter>
-        <blacklist>
-            <directory>./tests/</directory>
-            <directory>./vendor/</directory>
-        </blacklist>
+        <whitelist>
+            <directory>./src/</directory>
+        </whitelist>
     </filter>
 </phpunit>
\ No newline at end of file
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-libev.php b/tests/autobahn/bin/fuzzingserver-libev.php
similarity index 100%
rename from tests/AutobahnTestSuite/bin/fuzzingserver-libev.php
rename to tests/autobahn/bin/fuzzingserver-libev.php
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-libevent.php b/tests/autobahn/bin/fuzzingserver-libevent.php
similarity index 100%
rename from tests/AutobahnTestSuite/bin/fuzzingserver-libevent.php
rename to tests/autobahn/bin/fuzzingserver-libevent.php
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-libuv.php b/tests/autobahn/bin/fuzzingserver-libuv.php
similarity index 100%
rename from tests/AutobahnTestSuite/bin/fuzzingserver-libuv.php
rename to tests/autobahn/bin/fuzzingserver-libuv.php
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php b/tests/autobahn/bin/fuzzingserver-noutf8.php
similarity index 100%
rename from tests/AutobahnTestSuite/bin/fuzzingserver-noutf8.php
rename to tests/autobahn/bin/fuzzingserver-noutf8.php
diff --git a/tests/AutobahnTestSuite/bin/fuzzingserver-stream.php b/tests/autobahn/bin/fuzzingserver-stream.php
similarity index 100%
rename from tests/AutobahnTestSuite/bin/fuzzingserver-stream.php
rename to tests/autobahn/bin/fuzzingserver-stream.php
diff --git a/tests/AutobahnTestSuite/fuzzingclient-all.json b/tests/autobahn/fuzzingclient-all.json
similarity index 100%
rename from tests/AutobahnTestSuite/fuzzingclient-all.json
rename to tests/autobahn/fuzzingclient-all.json
diff --git a/tests/AutobahnTestSuite/fuzzingclient-profile.json b/tests/autobahn/fuzzingclient-profile.json
similarity index 100%
rename from tests/AutobahnTestSuite/fuzzingclient-profile.json
rename to tests/autobahn/fuzzingclient-profile.json
diff --git a/tests/AutobahnTestSuite/fuzzingclient-quick.json b/tests/autobahn/fuzzingclient-quick.json
similarity index 100%
rename from tests/AutobahnTestSuite/fuzzingclient-quick.json
rename to tests/autobahn/fuzzingclient-quick.json
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
new file mode 100644
index 0000000..9d21c77
--- /dev/null
+++ b/tests/bootstrap.php
@@ -0,0 +1,5 @@
+<?php
+
+    $loader = require __DIR__ . '/../vendor/autoload.php';
+    $loader->add('Ratchet', __DIR__ . '/helpers');
+    $loader->register();
diff --git a/tests/Ratchet/Tests/AbstractMessageComponentTestCase.php b/tests/helpers/Ratchet/AbstractMessageComponentTestCase.php
similarity index 98%
rename from tests/Ratchet/Tests/AbstractMessageComponentTestCase.php
rename to tests/helpers/Ratchet/AbstractMessageComponentTestCase.php
index a9223af..990e98c 100644
--- a/tests/Ratchet/Tests/AbstractMessageComponentTestCase.php
+++ b/tests/helpers/Ratchet/AbstractMessageComponentTestCase.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests;
+namespace Ratchet;
 
 abstract class AbstractMessageComponentTestCase extends \PHPUnit_Framework_TestCase {
     protected $_app;
diff --git a/tests/Ratchet/Tests/Mock/Component.php b/tests/helpers/Ratchet/Mock/Component.php
similarity index 96%
rename from tests/Ratchet/Tests/Mock/Component.php
rename to tests/helpers/Ratchet/Mock/Component.php
index 26427b4..d2ef27d 100644
--- a/tests/Ratchet/Tests/Mock/Component.php
+++ b/tests/helpers/Ratchet/Mock/Component.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Mock;
+namespace Ratchet\Mock;
 use Ratchet\MessageComponentInterface;
 use Ratchet\WebSocket\WsServerInterface;
 use Ratchet\ConnectionInterface;
diff --git a/tests/Ratchet/Tests/Mock/Connection.php b/tests/helpers/Ratchet/Mock/Connection.php
similarity index 92%
rename from tests/Ratchet/Tests/Mock/Connection.php
rename to tests/helpers/Ratchet/Mock/Connection.php
index 8707266..525487f 100644
--- a/tests/Ratchet/Tests/Mock/Connection.php
+++ b/tests/helpers/Ratchet/Mock/Connection.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Mock;
+namespace Ratchet\Mock;
 use Ratchet\ConnectionInterface;
 
 class Connection implements ConnectionInterface {
diff --git a/tests/Ratchet/Tests/Mock/ConnectionDecorator.php b/tests/helpers/Ratchet/Mock/ConnectionDecorator.php
similarity index 93%
rename from tests/Ratchet/Tests/Mock/ConnectionDecorator.php
rename to tests/helpers/Ratchet/Mock/ConnectionDecorator.php
index 72a430c..c8a0d17 100644
--- a/tests/Ratchet/Tests/Mock/ConnectionDecorator.php
+++ b/tests/helpers/Ratchet/Mock/ConnectionDecorator.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Mock;
+namespace Ratchet\Mock;
 use Ratchet\AbstractConnectionDecorator;
 
 class ConnectionDecorator extends AbstractConnectionDecorator {
diff --git a/tests/Ratchet/Tests/Mock/WampComponent.php b/tests/helpers/Ratchet/Mock/WampComponent.php
similarity index 97%
rename from tests/Ratchet/Tests/Mock/WampComponent.php
rename to tests/helpers/Ratchet/Mock/WampComponent.php
index 7493d6f..87af27c 100644
--- a/tests/Ratchet/Tests/Mock/WampComponent.php
+++ b/tests/helpers/Ratchet/Mock/WampComponent.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Mock;
+namespace Ratchet\Mock;
 use Ratchet\Wamp\WampServerInterface;
 use Ratchet\WebSocket\WsServerInterface;
 use Ratchet\ConnectionInterface;
diff --git a/tests/Ratchet/Tests/Mock/NullComponent.php b/tests/helpers/Ratchet/NullComponent.php
similarity index 96%
rename from tests/Ratchet/Tests/Mock/NullComponent.php
rename to tests/helpers/Ratchet/NullComponent.php
index 73a44a1..4352830 100644
--- a/tests/Ratchet/Tests/Mock/NullComponent.php
+++ b/tests/helpers/Ratchet/NullComponent.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Mock;
+namespace Ratchet;
 use Ratchet\ConnectionInterface;
 use Ratchet\MessageComponentInterface;
 use Ratchet\WebSocket\WsServerInterface;
diff --git a/tests/Ratchet/Tests/Wamp/Stub/WsWampServerInterface.php b/tests/helpers/Ratchet/Wamp/Stub/WsWampServerInterface.php
similarity index 82%
rename from tests/Ratchet/Tests/Wamp/Stub/WsWampServerInterface.php
rename to tests/helpers/Ratchet/Wamp/Stub/WsWampServerInterface.php
index d1f8341..45cb35f 100644
--- a/tests/Ratchet/Tests/Wamp/Stub/WsWampServerInterface.php
+++ b/tests/helpers/Ratchet/Wamp/Stub/WsWampServerInterface.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Wamp\Stub;
+namespace Ratchet\Wamp\Stub;
 use Ratchet\WebSocket\WsServerInterface;
 use Ratchet\Wamp\WampServerInterface;
 
diff --git a/tests/Ratchet/Tests/WebSocket/Stub/WsMessageComponentInterface.php b/tests/helpers/Ratchet/WebSocket/Stub/WsMessageComponentInterface.php
similarity index 81%
rename from tests/Ratchet/Tests/WebSocket/Stub/WsMessageComponentInterface.php
rename to tests/helpers/Ratchet/WebSocket/Stub/WsMessageComponentInterface.php
index 2e39a0b..40e6928 100644
--- a/tests/Ratchet/Tests/WebSocket/Stub/WsMessageComponentInterface.php
+++ b/tests/helpers/Ratchet/WebSocket/Stub/WsMessageComponentInterface.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\WebSocket\Stub;
+namespace Ratchet\WebSocket\Stub;
 use Ratchet\MessageComponentInterface;
 use Ratchet\WebSocket\WsServerInterface;
 
diff --git a/tests/Ratchet/Tests/AbstractConnectionDecoratorTest.php b/tests/unit/AbstractConnectionDecoratorTest.php
similarity index 98%
rename from tests/Ratchet/Tests/AbstractConnectionDecoratorTest.php
rename to tests/unit/AbstractConnectionDecoratorTest.php
index f196c79..905cce1 100644
--- a/tests/Ratchet/Tests/AbstractConnectionDecoratorTest.php
+++ b/tests/unit/AbstractConnectionDecoratorTest.php
@@ -1,6 +1,6 @@
 <?php
-namespace Ratchet\Tests;
-use Ratchet\Tests\Mock\ConnectionDecorator;
+namespace Ratchet;
+use Ratchet\Mock\ConnectionDecorator;
 
 /**
  * @covers Ratchet\AbstractConnectionDecorator
diff --git a/tests/Ratchet/Tests/Http/Guzzle/Http/Message/RequestFactoryTest.php b/tests/unit/Http/Guzzle/Http/Message/RequestFactoryTest.php
similarity index 97%
rename from tests/Ratchet/Tests/Http/Guzzle/Http/Message/RequestFactoryTest.php
rename to tests/unit/Http/Guzzle/Http/Message/RequestFactoryTest.php
index 9709745..8cada8c 100644
--- a/tests/Ratchet/Tests/Http/Guzzle/Http/Message/RequestFactoryTest.php
+++ b/tests/unit/Http/Guzzle/Http/Message/RequestFactoryTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Http\Guzzle\Http\Message;
+namespace Ratchet\Http\Guzzle\Http\Message;
 use Ratchet\Http\Guzzle\Http\Message\RequestFactory;
 
 /**
diff --git a/tests/Ratchet/Tests/Http/HttpRequestParserTest.php b/tests/unit/Http/HttpRequestParserTest.php
similarity index 98%
rename from tests/Ratchet/Tests/Http/HttpRequestParserTest.php
rename to tests/unit/Http/HttpRequestParserTest.php
index 3a540ec..89a0e80 100644
--- a/tests/Ratchet/Tests/Http/HttpRequestParserTest.php
+++ b/tests/unit/Http/HttpRequestParserTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Http;
+namespace Ratchet\Http;
 use Ratchet\Http\HttpRequestParser;
 
 /**
diff --git a/tests/Ratchet/Tests/Http/HttpServerTest.php b/tests/unit/Http/HttpServerTest.php
similarity index 96%
rename from tests/Ratchet/Tests/Http/HttpServerTest.php
rename to tests/unit/Http/HttpServerTest.php
index 203172a..2c069f1 100644
--- a/tests/Ratchet/Tests/Http/HttpServerTest.php
+++ b/tests/unit/Http/HttpServerTest.php
@@ -1,6 +1,6 @@
 <?php
-namespace Ratchet\Tests\Http;
-use Ratchet\Tests\AbstractMessageComponentTestCase;
+namespace Ratchet\Http;
+use Ratchet\AbstractMessageComponentTestCase;
 
 /**
  * @covers Ratchet\Http\HttpServer
diff --git a/tests/Ratchet/Tests/Http/RouterTest.php b/tests/unit/Http/RouterTest.php
similarity index 99%
rename from tests/Ratchet/Tests/Http/RouterTest.php
rename to tests/unit/Http/RouterTest.php
index 30abfed..8656dd3 100644
--- a/tests/Ratchet/Tests/Http/RouterTest.php
+++ b/tests/unit/Http/RouterTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Http;
+namespace Ratchet\Http;
 use Ratchet\Http\Router;
 use Symfony\Component\Routing\Exception\ResourceNotFoundException;
 
diff --git a/tests/Ratchet/Tests/Server/EchoServerTest.php b/tests/unit/Server/EchoServerTest.php
similarity index 96%
rename from tests/Ratchet/Tests/Server/EchoServerTest.php
rename to tests/unit/Server/EchoServerTest.php
index 4910dad..47fb0e2 100644
--- a/tests/Ratchet/Tests/Server/EchoServerTest.php
+++ b/tests/unit/Server/EchoServerTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Server;
+namespace Ratchet\Server;
 use Ratchet\Server\EchoServer;
 
 class EchoServerTest extends \PHPUnit_Framework_TestCase {
diff --git a/tests/Ratchet/Tests/Server/FlashPolicyComponentTest.php b/tests/unit/Server/FlashPolicyComponentTest.php
similarity index 99%
rename from tests/Ratchet/Tests/Server/FlashPolicyComponentTest.php
rename to tests/unit/Server/FlashPolicyComponentTest.php
index 60088b4..67f88a7 100644
--- a/tests/Ratchet/Tests/Server/FlashPolicyComponentTest.php
+++ b/tests/unit/Server/FlashPolicyComponentTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Application\Server;
+namespace Ratchet\Application\Server;
 use Ratchet\Server\FlashPolicy;
 
 /**
diff --git a/tests/Ratchet/Tests/Server/IoConnectionTest.php b/tests/unit/Server/IoConnectionTest.php
similarity index 94%
rename from tests/Ratchet/Tests/Server/IoConnectionTest.php
rename to tests/unit/Server/IoConnectionTest.php
index d2ff568..0cb7fb4 100644
--- a/tests/Ratchet/Tests/Server/IoConnectionTest.php
+++ b/tests/unit/Server/IoConnectionTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Application\Server;
+namespace Ratchet\Application\Server;
 use Ratchet\Server\IoConnection;
 
 /**
diff --git a/tests/Ratchet/Tests/Server/IoServerTest.php b/tests/unit/Server/IoServerTest.php
similarity index 99%
rename from tests/Ratchet/Tests/Server/IoServerTest.php
rename to tests/unit/Server/IoServerTest.php
index d375da8..2b0258c 100644
--- a/tests/Ratchet/Tests/Server/IoServerTest.php
+++ b/tests/unit/Server/IoServerTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Server;
+namespace Ratchet\Server;
 use Ratchet\Server\IoServer;
 use React\EventLoop\StreamSelectLoop;
 use React\Socket\Server;
diff --git a/tests/Ratchet/Tests/Server/IpBlackListComponentTest.php b/tests/unit/Server/IpBlackListComponentTest.php
similarity index 99%
rename from tests/Ratchet/Tests/Server/IpBlackListComponentTest.php
rename to tests/unit/Server/IpBlackListComponentTest.php
index c847bce..419f077 100644
--- a/tests/Ratchet/Tests/Server/IpBlackListComponentTest.php
+++ b/tests/unit/Server/IpBlackListComponentTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Server;
+namespace Ratchet\Server;
 use Ratchet\Server\IpBlackList;
 
 /**
diff --git a/tests/Ratchet/Tests/Session/Serialize/PhpHandlerTest.php b/tests/unit/Session/Serialize/PhpHandlerTest.php
similarity index 95%
rename from tests/Ratchet/Tests/Session/Serialize/PhpHandlerTest.php
rename to tests/unit/Session/Serialize/PhpHandlerTest.php
index c8bf0dc..cf1ef48 100644
--- a/tests/Ratchet/Tests/Session/Serialize/PhpHandlerTest.php
+++ b/tests/unit/Session/Serialize/PhpHandlerTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Session\Serialize;
+namespace Ratchet\Session\Serialize;
 use Ratchet\Session\Serialize\PhpHandler;
 
 /**
diff --git a/tests/Ratchet/Tests/Session/SessionComponentTest.php b/tests/unit/Session/SessionComponentTest.php
similarity index 95%
rename from tests/Ratchet/Tests/Session/SessionComponentTest.php
rename to tests/unit/Session/SessionComponentTest.php
index a411eb1..4b3f87b 100644
--- a/tests/Ratchet/Tests/Session/SessionComponentTest.php
+++ b/tests/unit/Session/SessionComponentTest.php
@@ -1,8 +1,8 @@
 <?php
-namespace Ratchet\Tests\Session;
-use Ratchet\Tests\AbstractMessageComponentTestCase;
+namespace Ratchet\Session;
+use Ratchet\AbstractMessageComponentTestCase;
 use Ratchet\Session\SessionProvider;
-use Ratchet\Tests\Mock\MemorySessionHandler;
+use Ratchet\Mock\MemorySessionHandler;
 use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
 use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler;
 use Guzzle\Http\Message\Request;
@@ -31,7 +31,7 @@ class SessionProviderTest extends AbstractMessageComponentTestCase {
     }
 
     public function getDecoratorClassString() {
-        return '\Ratchet\Tests\Mock\NullComponent';
+        return '\Ratchet\NullComponent';
     }
 
     public function getComponentClassString() {
@@ -119,7 +119,7 @@ class SessionProviderTest extends AbstractMessageComponentTestCase {
     }
 
     public function testGetSubProtocolsGetFromApp() {
-        $mock = $this->getMock('Ratchet\\Tests\\WebSocket\\Stub\\WsMessageComponentInterface');
+        $mock = $this->getMock('Ratchet\WebSocket\Stub\WsMessageComponentInterface');
         $mock->expects($this->once())->method('getSubProtocols')->will($this->returnValue(array('hello', 'world')));
         $comp = new SessionProvider($mock, new NullSessionHandler);
 
diff --git a/tests/Ratchet/Tests/Wamp/ServerProtocolTest.php b/tests/unit/Wamp/ServerProtocolTest.php
similarity index 98%
rename from tests/Ratchet/Tests/Wamp/ServerProtocolTest.php
rename to tests/unit/Wamp/ServerProtocolTest.php
index 4217ea3..9ecd89d 100644
--- a/tests/Ratchet/Tests/Wamp/ServerProtocolTest.php
+++ b/tests/unit/Wamp/ServerProtocolTest.php
@@ -1,9 +1,9 @@
 <?php
-namespace Ratchet\Tests\Wamp;
+namespace Ratchet\Wamp;
 use Ratchet\Wamp\ServerProtocol;
 use Ratchet\Wamp\WampConnection;
-use Ratchet\Tests\Mock\Connection;
-use Ratchet\Tests\Mock\WampComponent as TestComponent;
+use Ratchet\Mock\Connection;
+use Ratchet\Mock\WampComponent as TestComponent;
 
 /**
  * @covers Ratchet\Wamp\ServerProtocol
diff --git a/tests/Ratchet/Tests/Wamp/TopicManagerTest.php b/tests/unit/Wamp/TopicManagerTest.php
similarity index 85%
rename from tests/Ratchet/Tests/Wamp/TopicManagerTest.php
rename to tests/unit/Wamp/TopicManagerTest.php
index 3c00cd1..e096a28 100644
--- a/tests/Ratchet/Tests/Wamp/TopicManagerTest.php
+++ b/tests/unit/Wamp/TopicManagerTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Wamp;
+namespace Ratchet\Wamp;
 use Ratchet\Wamp\TopicManager;
 
 /**
@@ -20,7 +20,7 @@ class TopicManagerTest extends \PHPUnit_Framework_TestCase {
 
     public function setUp() {
         $this->conn = $this->getMock('\Ratchet\ConnectionInterface');
-        $this->mock = $this->getMock('\Ratchet\Wamp\\WampServerInterface');
+        $this->mock = $this->getMock('\Ratchet\Wamp\WampServerInterface');
         $this->mngr = new TopicManager($this->mock);
 
         $this->conn->WAMP = new \StdClass;
@@ -28,19 +28,19 @@ class TopicManagerTest extends \PHPUnit_Framework_TestCase {
     }
 
     public function testGetTopicReturnsTopicObject() {
-        $class  = new \ReflectionClass('Ratchet\\Wamp\\TopicManager');
+        $class  = new \ReflectionClass('Ratchet\Wamp\TopicManager');
         $method = $class->getMethod('getTopic');
         $method->setAccessible(true);
 
         $topic = $method->invokeArgs($this->mngr, array('The Topic'));
 
-        $this->assertInstanceOf('Ratchet\\Wamp\\Topic', $topic);
+        $this->assertInstanceOf('Ratchet\Wamp\Topic', $topic);
     }
 
     public function testGetTopicCreatesTopicWithSameName() {
         $name = 'The Topic';
 
-        $class  = new \ReflectionClass('Ratchet\\Wamp\\TopicManager');
+        $class  = new \ReflectionClass('Ratchet\Wamp\TopicManager');
         $method = $class->getMethod('getTopic');
         $method->setAccessible(true);
 
@@ -50,7 +50,7 @@ class TopicManagerTest extends \PHPUnit_Framework_TestCase {
     }
 
     public function testGetTopicReturnsSameObject() {
-        $class  = new \ReflectionClass('Ratchet\\Wamp\\TopicManager');
+        $class  = new \ReflectionClass('Ratchet\Wamp\TopicManager');
         $method = $class->getMethod('getTopic');
         $method->setAccessible(true);
 
@@ -71,7 +71,7 @@ class TopicManagerTest extends \PHPUnit_Framework_TestCase {
         $this->mock->expects($this->once())->method('onCall')->with(
             $this->conn
           , $id
-          , $this->isInstanceOf('Ratchet\\Wamp\\Topic')
+          , $this->isInstanceOf('Ratchet\Wamp\Topic')
           , array()
         );
 
@@ -80,7 +80,7 @@ class TopicManagerTest extends \PHPUnit_Framework_TestCase {
 
     public function testOnSubscribeCreatesTopicObject() {
         $this->mock->expects($this->once())->method('onSubscribe')->with(
-            $this->conn, $this->isInstanceOf('Ratchet\\Wamp\\Topic')
+            $this->conn, $this->isInstanceOf('Ratchet\Wamp\Topic')
         );
 
         $this->mngr->onSubscribe($this->conn, 'new topic');
@@ -89,7 +89,7 @@ class TopicManagerTest extends \PHPUnit_Framework_TestCase {
     public function testTopicIsInConnectionOnSubscribe() {
         $name = 'New Topic';
 
-        $class  = new \ReflectionClass('Ratchet\\Wamp\\TopicManager');
+        $class  = new \ReflectionClass('Ratchet\Wamp\TopicManager');
         $method = $class->getMethod('getTopic');
         $method->setAccessible(true);
 
@@ -110,7 +110,7 @@ class TopicManagerTest extends \PHPUnit_Framework_TestCase {
     public function testUnsubscribeEvent() {
         $name = 'in and out';
         $this->mock->expects($this->once())->method('onUnsubscribe')->with(
-            $this->conn, $this->isInstanceOf('Ratchet\\Wamp\\Topic')
+            $this->conn, $this->isInstanceOf('Ratchet\Wamp\Topic')
         );
 
         $this->mngr->onSubscribe($this->conn, $name);
@@ -129,7 +129,7 @@ class TopicManagerTest extends \PHPUnit_Framework_TestCase {
     public function testUnsubscribeRemovesTopicFromConnection() {
         $name = 'Bye Bye Topic';
 
-        $class  = new \ReflectionClass('Ratchet\\Wamp\\TopicManager');
+        $class  = new \ReflectionClass('Ratchet\Wamp\TopicManager');
         $method = $class->getMethod('getTopic');
         $method->setAccessible(true);
 
@@ -146,7 +146,7 @@ class TopicManagerTest extends \PHPUnit_Framework_TestCase {
 
         $this->mock->expects($this->once())->method('onPublish')->with(
             $this->conn
-          , $this->isInstanceOf('Ratchet\\Wamp\\Topic')
+          , $this->isInstanceOf('Ratchet\Wamp\Topic')
           , $msg
           , $this->isType('array')
           , $this->isType('array')
@@ -163,7 +163,7 @@ class TopicManagerTest extends \PHPUnit_Framework_TestCase {
     public function testConnIsRemovedFromTopicOnClose() {
         $name = 'State testing';
 
-        $class  = new \ReflectionClass('Ratchet\\Wamp\\TopicManager');
+        $class  = new \ReflectionClass('Ratchet\Wamp\TopicManager');
         $method = $class->getMethod('getTopic');
         $method->setAccessible(true);
 
@@ -188,7 +188,7 @@ class TopicManagerTest extends \PHPUnit_Framework_TestCase {
 
     public function testGetSubProtocolsBubbles() {
         $subs = array('hello', 'world');
-        $app  = $this->getMock('Ratchet\\Tests\\Wamp\\Stub\\WsWampServerInterface');
+        $app  = $this->getMock('Ratchet\Wamp\Stub\WsWampServerInterface');
         $app->expects($this->once())->method('getSubProtocols')->will($this->returnValue($subs));
         $mngr = new TopicManager($app);
 
diff --git a/tests/Ratchet/Tests/Wamp/TopicTest.php b/tests/unit/Wamp/TopicTest.php
similarity index 98%
rename from tests/Ratchet/Tests/Wamp/TopicTest.php
rename to tests/unit/Wamp/TopicTest.php
index d5358d1..0a2102b 100644
--- a/tests/Ratchet/Tests/Wamp/TopicTest.php
+++ b/tests/unit/Wamp/TopicTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Wamp;
+namespace Ratchet\Wamp;
 use Ratchet\Wamp\Topic;
 use Ratchet\Wamp\WampConnection;
 
diff --git a/tests/Ratchet/Tests/Wamp/WampConnectionTest.php b/tests/unit/Wamp/WampConnectionTest.php
similarity index 98%
rename from tests/Ratchet/Tests/Wamp/WampConnectionTest.php
rename to tests/unit/Wamp/WampConnectionTest.php
index a1679ed..7f82f98 100644
--- a/tests/Ratchet/Tests/Wamp/WampConnectionTest.php
+++ b/tests/unit/Wamp/WampConnectionTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\Wamp;
+namespace Ratchet\Wamp;
 use Ratchet\Wamp\WampConnection;
 
 /**
diff --git a/tests/Ratchet/Tests/Wamp/WampServerTest.php b/tests/unit/Wamp/WampServerTest.php
similarity index 93%
rename from tests/Ratchet/Tests/Wamp/WampServerTest.php
rename to tests/unit/Wamp/WampServerTest.php
index e83dc28..b1ee6f1 100644
--- a/tests/Ratchet/Tests/Wamp/WampServerTest.php
+++ b/tests/unit/Wamp/WampServerTest.php
@@ -1,7 +1,7 @@
 <?php
-namespace Ratchet\Tests\Wamp;
+namespace Ratchet\Wamp;
 use Ratchet\Wamp\WampServer;
-use Ratchet\Tests\AbstractMessageComponentTestCase;
+use Ratchet\AbstractMessageComponentTestCase;
 
 /**
  * @covers Ratchet\Wamp\WampServer
diff --git a/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php b/tests/unit/WebSocket/Version/Hixie76Test.php
similarity index 98%
rename from tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php
rename to tests/unit/WebSocket/Version/Hixie76Test.php
index 3ac1f4a..07d863b 100644
--- a/tests/Ratchet/Tests/WebSocket/Version/Hixie76Test.php
+++ b/tests/unit/WebSocket/Version/Hixie76Test.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\WebSocket\Version;
+namespace Ratchet\WebSocket\Version;
 use Ratchet\WebSocket\Version\Hixie76;
 use Ratchet\Http\HttpServer;
 use Ratchet\WebSocket\WsServer;
diff --git a/tests/Ratchet/Tests/WebSocket/Version/HyBi10Test.php b/tests/unit/WebSocket/Version/HyBi10Test.php
similarity index 98%
rename from tests/Ratchet/Tests/WebSocket/Version/HyBi10Test.php
rename to tests/unit/WebSocket/Version/HyBi10Test.php
index 11ebaa2..74044df 100644
--- a/tests/Ratchet/Tests/WebSocket/Version/HyBi10Test.php
+++ b/tests/unit/WebSocket/Version/HyBi10Test.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\WebSocket\Version;
+namespace Ratchet\WebSocket\Version;
 use Ratchet\WebSocket\Version\HyBi10;
 use Ratchet\WebSocket\Version\RFC6455\Frame;
 
diff --git a/tests/Ratchet/Tests/WebSocket/Version/RFC6455/FrameTest.php b/tests/unit/WebSocket/Version/RFC6455/FrameTest.php
similarity index 99%
rename from tests/Ratchet/Tests/WebSocket/Version/RFC6455/FrameTest.php
rename to tests/unit/WebSocket/Version/RFC6455/FrameTest.php
index 7b860f3..ca4447c 100644
--- a/tests/Ratchet/Tests/WebSocket/Version/RFC6455/FrameTest.php
+++ b/tests/unit/WebSocket/Version/RFC6455/FrameTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\WebSocket\Version\RFC6455;
+namespace Ratchet\WebSocket\Version\RFC6455;
 use Ratchet\WebSocket\Version\RFC6455\Frame;
 
 /**
diff --git a/tests/Ratchet/Tests/WebSocket/Version/RFC6455/HandshakeVerifierTest.php b/tests/unit/WebSocket/Version/RFC6455/HandshakeVerifierTest.php
similarity index 98%
rename from tests/Ratchet/Tests/WebSocket/Version/RFC6455/HandshakeVerifierTest.php
rename to tests/unit/WebSocket/Version/RFC6455/HandshakeVerifierTest.php
index 3822ff3..cdaec6d 100644
--- a/tests/Ratchet/Tests/WebSocket/Version/RFC6455/HandshakeVerifierTest.php
+++ b/tests/unit/WebSocket/Version/RFC6455/HandshakeVerifierTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\WebSocket\Version\RFC6455;
+namespace Ratchet\WebSocket\Version\RFC6455;
 use Ratchet\WebSocket\Version\RFC6455\HandshakeVerifier;
 
 /**
diff --git a/tests/Ratchet/Tests/WebSocket/Version/RFC6455/MessageTest.php b/tests/unit/WebSocket/Version/RFC6455/MessageTest.php
similarity index 96%
rename from tests/Ratchet/Tests/WebSocket/Version/RFC6455/MessageTest.php
rename to tests/unit/WebSocket/Version/RFC6455/MessageTest.php
index 5cc2a58..4b72170 100644
--- a/tests/Ratchet/Tests/WebSocket/Version/RFC6455/MessageTest.php
+++ b/tests/unit/WebSocket/Version/RFC6455/MessageTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\WebSocket\Version\RFC6455\Message;
+namespace Ratchet\WebSocket\Version\RFC6455\Message;
 use Ratchet\WebSocket\Version\RFC6455\Message;
 use Ratchet\WebSocket\Version\RFC6455\Frame;
 
diff --git a/tests/Ratchet/Tests/WebSocket/Version/RFC6455Test.php b/tests/unit/WebSocket/Version/RFC6455Test.php
similarity index 99%
rename from tests/Ratchet/Tests/WebSocket/Version/RFC6455Test.php
rename to tests/unit/WebSocket/Version/RFC6455Test.php
index 007eb83..89a9ae6 100644
--- a/tests/Ratchet/Tests/WebSocket/Version/RFC6455Test.php
+++ b/tests/unit/WebSocket/Version/RFC6455Test.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\WebSocket\Version;
+namespace Ratchet\WebSocket\Version;
 use Ratchet\WebSocket\Version\RFC6455;
 use Ratchet\WebSocket\Version\RFC6455\Frame;
 use Guzzle\Http\Message\RequestFactory;
diff --git a/tests/Ratchet/Tests/WebSocket/VersionManagerTest.php b/tests/unit/WebSocket/VersionManagerTest.php
similarity index 98%
rename from tests/Ratchet/Tests/WebSocket/VersionManagerTest.php
rename to tests/unit/WebSocket/VersionManagerTest.php
index 68fa336..6083548 100644
--- a/tests/Ratchet/Tests/WebSocket/VersionManagerTest.php
+++ b/tests/unit/WebSocket/VersionManagerTest.php
@@ -1,5 +1,5 @@
 <?php
-namespace Ratchet\Tests\WebSocket;
+namespace Ratchet\WebSocket;
 use Ratchet\WebSocket\VersionManager;
 use Ratchet\WebSocket\Version\RFC6455;
 use Ratchet\WebSocket\Version\HyBi10;
diff --git a/tests/Ratchet/Tests/WebSocket/WsServerTest.php b/tests/unit/WebSocket/WsServerTest.php
similarity index 94%
rename from tests/Ratchet/Tests/WebSocket/WsServerTest.php
rename to tests/unit/WebSocket/WsServerTest.php
index 510b5aa..1a3626c 100644
--- a/tests/Ratchet/Tests/WebSocket/WsServerTest.php
+++ b/tests/unit/WebSocket/WsServerTest.php
@@ -1,7 +1,7 @@
 <?php
-namespace Ratchet\Tests\WebSocket;
+namespace Ratchet\WebSocket;
 use Ratchet\WebSocket\WsServer;
-use Ratchet\Tests\Mock\Component as MockComponent;
+use Ratchet\Mock\Component as MockComponent;
 
 /**
  * @covers Ratchet\WebSocket\WsServer

From b1b5fbe1a7c2d22e59f3d4b8092c6cf84f67fce3 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sun, 16 Jun 2013 17:40:38 -0400
Subject: [PATCH 32/48] [Tests] Added Guzzle integration tests

---
 phpunit.xml.dist                 |  6 ++++
 tests/integration/GuzzleTest.php | 53 ++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)
 create mode 100644 tests/integration/GuzzleTest.php

diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 117227a..0cc5451 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -16,6 +16,12 @@
         </testsuite>
     </testsuites>
 
+    <testsuites>
+        <testsuite name="integration">
+            <directory>./tests/integration/</directory>
+        </testsuite>
+    </testsuites>
+
     <filter>
         <whitelist>
             <directory>./src/</directory>
diff --git a/tests/integration/GuzzleTest.php b/tests/integration/GuzzleTest.php
new file mode 100644
index 0000000..6d3a544
--- /dev/null
+++ b/tests/integration/GuzzleTest.php
@@ -0,0 +1,53 @@
+<?php
+use Guzzle\Http\Message\Request;
+
+class GuzzleTest extends \PHPUnit_Framework_TestCase {
+    protected $_request;
+
+    protected $_headers = array(
+        'Upgrade' => 'websocket'
+      , 'Connection' => 'Upgrade'
+      , 'Host' => 'localhost:8080'
+      , 'Origin' => 'chrome://newtab'
+      , 'Sec-WebSocket-Protocol' => 'one, two, three'
+      , 'Sec-WebSocket-Key' => '9bnXNp3ae6FbFFRtPdiPXA=='
+      , 'Sec-WebSocket-Version' => '13'
+    );
+
+    public function setUp() {
+        $this->_request = new Request('GET', 'http://localhost', $this->_headers);
+    }
+
+    public function testGetHeaderString() {
+        $this->assertEquals('Upgrade', (string)$this->_request->getHeader('connection'));
+        $this->assertEquals('9bnXNp3ae6FbFFRtPdiPXA==', (string)$this->_request->getHeader('Sec-Websocket-Key'));
+    }
+
+    public function testGetHeaderInteger() {
+        $this->assertSame('13', (string)$this->_request->getHeader('Sec-Websocket-Version'));
+        $this->assertSame(13, (int)(string)$this->_request->getHeader('Sec-WebSocket-Version'));
+    }
+
+    public function testGetHeaderObject() {
+        $this->assertInstanceOf('Guzzle\Http\Message\Header', $this->_request->getHeader('Origin'));
+        $this->assertNull($this->_request->getHeader('Non-existant-header'));
+    }
+
+    public function testHeaderObjectNormalizeValues() {
+        $expected  = 1 + substr_count($this->_headers['Sec-WebSocket-Protocol'], ',');
+        $protocols = $this->_request->getHeader('Sec-WebSocket-Protocol')->normalize();
+        $count     = 0;
+
+        foreach ($protocols as $protocol) {
+            $count++;
+        }
+
+        $this->assertEquals($expected, $count);
+        $this->assertEquals($expected, count($protocols));
+    }
+
+    public function testRequestFactoryCreateSignature() {
+        $ref = new \ReflectionMethod('Guzzle\Http\Message\RequestFactory', 'create');
+        $this->assertEquals(2, $ref->getNumberOfRequiredParameters());
+    }
+}
\ No newline at end of file

From b658ae6e7eb42c4b222044df579d858b4f181916 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sat, 20 Jul 2013 11:11:34 -0400
Subject: [PATCH 33/48] Composer restrictions + update

---
 composer.json       |   2 +-
 composer.lock       | 108 ++++++++++++++++++++++----------------------
 src/Ratchet/App.php |   2 +-
 3 files changed, 56 insertions(+), 56 deletions(-)

diff --git a/composer.json b/composer.json
index 293c6be..12c95f0 100644
--- a/composer.json
+++ b/composer.json
@@ -26,7 +26,7 @@
   , "require": {
         "php": ">=5.3.9"
       , "react/socket": "0.3.*"
-      , "guzzle/http": "3.6.*"
+      , "guzzle/http": ">=3.6.0,<3.8.0-dev"
       , "symfony/http-foundation": "~2.2"
       , "symfony/routing": "~2.2"
     }
diff --git a/composer.lock b/composer.lock
index 1ed2a55..4800ed7 100644
--- a/composer.lock
+++ b/composer.lock
@@ -3,7 +3,7 @@
         "This file locks the dependencies of your project to a known state",
         "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
     ],
-    "hash": "f5d2fe5b143f2c5d2e8f674dd2f6bc16",
+    "hash": "a45c5bcb9c18e390adc2a60ffd059a52",
     "packages": [
         {
             "name": "evenement/evenement",
@@ -47,17 +47,17 @@
         },
         {
             "name": "guzzle/common",
-            "version": "v3.6.0",
+            "version": "v3.7.1",
             "target-dir": "Guzzle/Common",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/common.git",
-                "reference": "v3.6.0"
+                "reference": "v3.7.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/common/zipball/v3.6.0",
-                "reference": "v3.6.0",
+                "url": "https://api.github.com/repos/guzzle/common/zipball/v3.7.1",
+                "reference": "v3.7.1",
                 "shasum": ""
             },
             "require": {
@@ -67,7 +67,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.6-dev"
+                    "dev-master": "3.7-dev"
                 }
             },
             "autoload": {
@@ -87,21 +87,21 @@
                 "event",
                 "exception"
             ],
-            "time": "2013-05-30 07:01:25"
+            "time": "2013-07-05 20:17:54"
         },
         {
             "name": "guzzle/http",
-            "version": "v3.6.0",
+            "version": "v3.7.1",
             "target-dir": "Guzzle/Http",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/http.git",
-                "reference": "v3.6.0"
+                "reference": "v3.7.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/http/zipball/v3.6.0",
-                "reference": "v3.6.0",
+                "url": "https://api.github.com/repos/guzzle/http/zipball/v3.7.1",
+                "reference": "v3.7.1",
                 "shasum": ""
             },
             "require": {
@@ -116,7 +116,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.6-dev"
+                    "dev-master": "3.7-dev"
                 }
             },
             "autoload": {
@@ -144,21 +144,21 @@
                 "http",
                 "http client"
             ],
-            "time": "2013-05-30 07:01:25"
+            "time": "2013-07-02 19:53:26"
         },
         {
             "name": "guzzle/parser",
-            "version": "v3.6.0",
+            "version": "v3.7.1",
             "target-dir": "Guzzle/Parser",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/parser.git",
-                "reference": "v3.6.0"
+                "reference": "v3.7.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/parser/zipball/v3.6.0",
-                "reference": "v3.6.0",
+                "url": "https://api.github.com/repos/guzzle/parser/zipball/v3.7.1",
+                "reference": "v3.7.1",
                 "shasum": ""
             },
             "require": {
@@ -167,7 +167,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.6-dev"
+                    "dev-master": "3.7-dev"
                 }
             },
             "autoload": {
@@ -188,21 +188,21 @@
                 "message",
                 "url"
             ],
-            "time": "2013-05-30 07:01:25"
+            "time": "2013-06-11 00:24:07"
         },
         {
             "name": "guzzle/stream",
-            "version": "v3.6.0",
+            "version": "v3.7.1",
             "target-dir": "Guzzle/Stream",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/stream.git",
-                "reference": "v3.6.0"
+                "reference": "v3.7.1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/stream/zipball/v3.6.0",
-                "reference": "v3.6.0",
+                "url": "https://api.github.com/repos/guzzle/stream/zipball/v3.7.1",
+                "reference": "v3.7.1",
                 "shasum": ""
             },
             "require": {
@@ -215,7 +215,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "3.6-dev"
+                    "dev-master": "3.7-dev"
                 }
             },
             "autoload": {
@@ -241,21 +241,21 @@
                 "component",
                 "stream"
             ],
-            "time": "2013-05-30 07:01:25"
+            "time": "2013-06-27 00:50:43"
         },
         {
             "name": "react/event-loop",
-            "version": "v0.3.2",
+            "version": "v0.3.3",
             "target-dir": "React/EventLoop",
             "source": {
                 "type": "git",
                 "url": "https://github.com/reactphp/event-loop.git",
-                "reference": "v0.3.2"
+                "reference": "v0.3.3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/reactphp/event-loop/zipball/v0.3.2",
-                "reference": "v0.3.2",
+                "url": "https://api.github.com/repos/reactphp/event-loop/zipball/v0.3.3",
+                "reference": "v0.3.3",
                 "shasum": ""
             },
             "require": {
@@ -284,7 +284,7 @@
             "keywords": [
                 "event-loop"
             ],
-            "time": "2013-01-14 23:11:47"
+            "time": "2013-07-08 22:38:22"
         },
         {
             "name": "react/socket",
@@ -330,17 +330,17 @@
         },
         {
             "name": "react/stream",
-            "version": "v0.3.2",
+            "version": "v0.3.3",
             "target-dir": "React/Stream",
             "source": {
                 "type": "git",
                 "url": "https://github.com/reactphp/stream.git",
-                "reference": "v0.3.2"
+                "reference": "v0.3.3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/reactphp/stream/zipball/v0.3.2",
-                "reference": "v0.3.2",
+                "url": "https://api.github.com/repos/reactphp/stream/zipball/v0.3.3",
+                "reference": "v0.3.3",
                 "shasum": ""
             },
             "require": {
@@ -371,28 +371,28 @@
                 "pipe",
                 "stream"
             ],
-            "time": "2013-05-10 15:12:22"
+            "time": "2013-07-09 00:44:12"
         },
         {
             "name": "symfony/event-dispatcher",
-            "version": "v2.3.0",
+            "version": "v2.3.2",
             "target-dir": "Symfony/Component/EventDispatcher",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/EventDispatcher.git",
-                "reference": "v2.3.0-RC1"
+                "reference": "v2.3.2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.3.0-RC1",
-                "reference": "v2.3.0-RC1",
+                "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.3.2",
+                "reference": "v2.3.2",
                 "shasum": ""
             },
             "require": {
                 "php": ">=5.3.3"
             },
             "require-dev": {
-                "symfony/dependency-injection": ">=2.0,<3.0"
+                "symfony/dependency-injection": "~2.0"
             },
             "suggest": {
                 "symfony/dependency-injection": "",
@@ -429,17 +429,17 @@
         },
         {
             "name": "symfony/http-foundation",
-            "version": "v2.3.1",
+            "version": "v2.3.2",
             "target-dir": "Symfony/Component/HttpFoundation",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/HttpFoundation.git",
-                "reference": "v2.3.1"
+                "reference": "v2.3.2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/v2.3.1",
-                "reference": "v2.3.1",
+                "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/v2.3.2",
+                "reference": "v2.3.2",
                 "shasum": ""
             },
             "require": {
@@ -475,31 +475,31 @@
             ],
             "description": "Symfony HttpFoundation Component",
             "homepage": "http://symfony.com",
-            "time": "2013-05-10 06:00:03"
+            "time": "2013-07-17 05:57:53"
         },
         {
             "name": "symfony/routing",
-            "version": "v2.3.0",
+            "version": "v2.3.2",
             "target-dir": "Symfony/Component/Routing",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/Routing.git",
-                "reference": "v2.3.0"
+                "reference": "v2.3.2"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Routing/zipball/v2.3.0",
-                "reference": "v2.3.0",
+                "url": "https://api.github.com/repos/symfony/Routing/zipball/v2.3.2",
+                "reference": "v2.3.2",
                 "shasum": ""
             },
             "require": {
                 "php": ">=5.3.3"
             },
             "require-dev": {
-                "doctrine/common": ">=2.2,<3.0",
-                "psr/log": ">=1.0,<2.0",
-                "symfony/config": ">=2.2,<3.0",
-                "symfony/yaml": ">=2.0,<3.0"
+                "doctrine/common": "~2.2",
+                "psr/log": "~1.0",
+                "symfony/config": "~2.2",
+                "symfony/yaml": "~2.0"
             },
             "suggest": {
                 "doctrine/common": "",
@@ -533,7 +533,7 @@
             ],
             "description": "Symfony Routing Component",
             "homepage": "http://symfony.com",
-            "time": "2013-05-20 08:57:26"
+            "time": "2013-06-23 08:16:02"
         }
     ],
     "packages-dev": [
diff --git a/src/Ratchet/App.php b/src/Ratchet/App.php
index 6728c30..a3db257 100644
--- a/src/Ratchet/App.php
+++ b/src/Ratchet/App.php
@@ -79,7 +79,7 @@ class App {
     /**
      * @param string             $path
      * @param ComponentInterface $controller
-     * @return Symfony\Component\Routing\Route
+     * @return \Symfony\Component\Routing\Route
      */
     public function route($path, ComponentInterface $controller) {
         if ($controller instanceof HttpServerInterface || $controller instanceof WsServer) {

From 0dad9f1c03413cf59b040b572a336dbcc3c8e4f1 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sat, 20 Jul 2013 11:14:20 -0400
Subject: [PATCH 34/48] Removed libuv test

---
 tests/autobahn/bin/fuzzingserver-libuv.php | 13 -------------
 1 file changed, 13 deletions(-)
 delete mode 100644 tests/autobahn/bin/fuzzingserver-libuv.php

diff --git a/tests/autobahn/bin/fuzzingserver-libuv.php b/tests/autobahn/bin/fuzzingserver-libuv.php
deleted file mode 100644
index b3dec26..0000000
--- a/tests/autobahn/bin/fuzzingserver-libuv.php
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php
-
-    require dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';
-
-    $loop = new React\EventLoop\LibEvLoop;
-    $sock = new React\Socket\Server($loop);
-    $app  = new Ratchet\Http\HttpServer(new Ratchet\WebSocket\WsServer(new Ratchet\Server\EchoServer));
-
-    $port = $argc > 1 ? $argv[1] : 8000;
-    $sock->listen($port, '0.0.0.0');
-
-    $server = new Ratchet\Server\IoServer($app, $sock, $loop);
-    $server->run();

From 9a508356376ebeeb8fc8353ea57e1a9f58e94e6f Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sat, 20 Jul 2013 12:31:44 -0400
Subject: [PATCH 35/48] [WAMP] Message verification, fixes #105

Validate all messages follow WAMP protocol
---
 src/Ratchet/Wamp/ServerProtocol.php    |  6 +++++-
 src/Ratchet/Wamp/WampConnection.php    |  6 +++---
 src/Ratchet/Wamp/WampServer.php        |  8 +++++++-
 tests/unit/Wamp/ServerProtocolTest.php | 19 +++++++++++++++++++
 tests/unit/Wamp/WampServerTest.php     | 14 ++++++++++----
 5 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/src/Ratchet/Wamp/ServerProtocol.php b/src/Ratchet/Wamp/ServerProtocol.php
index 7900659..7842c82 100644
--- a/src/Ratchet/Wamp/ServerProtocol.php
+++ b/src/Ratchet/Wamp/ServerProtocol.php
@@ -6,7 +6,7 @@ use Ratchet\ConnectionInterface;
 
 /**
  * WebSocket Application Messaging Protocol
- * 
+ *
  * @link http://wamp.ws/spec
  * @link https://github.com/oberstet/AutobahnJS
  *
@@ -89,6 +89,10 @@ class ServerProtocol implements MessageComponentInterface, WsServerInterface {
             throw new JsonException;
         }
 
+        if (!is_array($json) || $json !== array_values($json)) {
+            throw new \UnexpectedValueException("Invalid WAMP message format");
+        }
+
         switch ($json[0]) {
             case static::MSG_PREFIX:
                 $from->WAMP->prefixes[$json[1]] = $json[2];
diff --git a/src/Ratchet/Wamp/WampConnection.php b/src/Ratchet/Wamp/WampConnection.php
index b5eb04a..de13844 100644
--- a/src/Ratchet/Wamp/WampConnection.php
+++ b/src/Ratchet/Wamp/WampConnection.php
@@ -6,7 +6,7 @@ use Ratchet\Wamp\ServerProtocol as WAMP;
 
 /**
  * A ConnectionInterface object wrapper that is passed to your WAMP application
- * representing a client. Methods on this Connection are therefore different. 
+ * representing a client. Methods on this Connection are therefore different.
  * @property \stdClass $WAMP
  */
 class WampConnection extends AbstractConnectionDecorator {
@@ -96,7 +96,7 @@ class WampConnection extends AbstractConnectionDecorator {
     /**
      * {@inheritdoc}
      */
-    public function close() {
-        $this->getConnection()->close();
+    public function close($opt = null) {
+        $this->getConnection()->close($opt);
     }
 }
\ No newline at end of file
diff --git a/src/Ratchet/Wamp/WampServer.php b/src/Ratchet/Wamp/WampServer.php
index d2bfdcf..9e7951f 100644
--- a/src/Ratchet/Wamp/WampServer.php
+++ b/src/Ratchet/Wamp/WampServer.php
@@ -37,7 +37,13 @@ class WampServer implements MessageComponentInterface, WsServerInterface {
      * {@inheritdoc}
      */
     public function onMessage(ConnectionInterface $conn, $msg) {
-        $this->wampProtocol->onMessage($conn, $msg);
+        try {
+            $this->wampProtocol->onMessage($conn, $msg);
+        } catch (JsonException $je) {
+            $conn->close(1007);
+        } catch (\UnexpectedValueException $uve) {
+            $conn->close(1007);
+        }
     }
 
     /**
diff --git a/tests/unit/Wamp/ServerProtocolTest.php b/tests/unit/Wamp/ServerProtocolTest.php
index 9ecd89d..b4f57a4 100644
--- a/tests/unit/Wamp/ServerProtocolTest.php
+++ b/tests/unit/Wamp/ServerProtocolTest.php
@@ -247,4 +247,23 @@ class ServerProtocolTest extends \PHPUnit_Framework_TestCase {
 
         $this->assertContains('wamp', $wamp->getSubProtocols());
     }
+
+    public function badFormatProvider() {
+        return array(
+            array(json_encode(true))
+          , array('{"valid":"json", "invalid": "message"}')
+          , array('{"0": "fail", "hello": "world"}')
+        );
+    }
+
+    /**
+     * @dataProvider badFormatProvider
+     */
+    public function testValidJsonButInvalidProtocol($message) {
+        $this->setExpectedException('\UnexpectedValueException');
+
+        $conn = $this->newConn();
+        $this->_comp->onOpen($conn);
+        $this->_comp->onMessage($conn, $message);
+    }
 }
\ No newline at end of file
diff --git a/tests/unit/Wamp/WampServerTest.php b/tests/unit/Wamp/WampServerTest.php
index b1ee6f1..e76d693 100644
--- a/tests/unit/Wamp/WampServerTest.php
+++ b/tests/unit/Wamp/WampServerTest.php
@@ -7,10 +7,6 @@ use Ratchet\AbstractMessageComponentTestCase;
  * @covers Ratchet\Wamp\WampServer
  */
 class WampServerTest extends AbstractMessageComponentTestCase {
-    private $serv;
-    private $mock;
-    private $conn;
-
     public function getConnectionClassString() {
         return '\Ratchet\Wamp\WampConnection';
     }
@@ -41,4 +37,14 @@ class WampServerTest extends AbstractMessageComponentTestCase {
         // todo: could expand on this
         $this->assertInternalType('array', $this->_serv->getSubProtocols());
     }
+
+    public function testConnectionClosesOnInvalidJson() {
+        $this->_conn->expects($this->once())->method('close');
+        $this->_serv->onMessage($this->_conn, 'invalid json');
+    }
+
+    public function testConnectionClosesOnProtocolError() {
+        $this->_conn->expects($this->once())->method('close');
+        $this->_serv->onMessage($this->_conn, json_encode(array('valid' => 'json', 'invalid' => 'protocol')));
+    }
 }
\ No newline at end of file

From 5676161277bae08e11103a188c43395e8ba8f758 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sat, 20 Jul 2013 12:38:23 -0400
Subject: [PATCH 36/48] [WebSocket] Only select one sub-protocol, fixes #103

---
 src/Ratchet/WebSocket/WsServer.php    | 16 ++++++----------
 tests/unit/WebSocket/WsServerTest.php |  3 ++-
 2 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/src/Ratchet/WebSocket/WsServer.php b/src/Ratchet/WebSocket/WsServer.php
index 460e328..9337934 100644
--- a/src/Ratchet/WebSocket/WsServer.php
+++ b/src/Ratchet/WebSocket/WsServer.php
@@ -199,19 +199,15 @@ class WsServer implements HttpServerInterface {
      * @return string
      */
     protected function getSubProtocolString(\Traversable $requested = null) {
-        if (null === $requested) {
-            return '';
-        }
-
-        $result = array();
-
-        foreach ($requested as $sub) {
-            if ($this->isSubProtocolSupported($sub)) {
-                $result[] = $sub;
+        if (null !== $requested) {
+            foreach ($requested as $sub) {
+                if ($this->isSubProtocolSupported($sub)) {
+                    return $sub;
+                }
             }
         }
 
-        return implode(',', $result);
+        return '';
     }
 
     /**
diff --git a/tests/unit/WebSocket/WsServerTest.php b/tests/unit/WebSocket/WsServerTest.php
index 1a3626c..c923e16 100644
--- a/tests/unit/WebSocket/WsServerTest.php
+++ b/tests/unit/WebSocket/WsServerTest.php
@@ -27,10 +27,11 @@ class WsServerTest extends \PHPUnit_Framework_TestCase {
 
     public function protocolProvider() {
         return array(
-            array('hello,world', array('hello', 'world'), array('hello', 'world'))
+            array('hello', array('hello', 'world'), array('hello', 'world'))
           , array('', array('hello', 'world'), array('wamp'))
           , array('', array(), null)
           , array('wamp', array('hello', 'wamp', 'world'), array('herp', 'derp', 'wamp'))
+          , array('wamp', array('wamp'), array('wamp'))
         );
     }
 

From 0cf4b614a11fe7b584d7c34008937d405dd82bd6 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sat, 20 Jul 2013 14:52:18 -0400
Subject: [PATCH 37/48] 5.5 tests

---
 .travis.yml                     | 1 +
 README.md                       | 2 +-
 src/Ratchet/Http/HttpServer.php | 3 ---
 3 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 5625a26..7604e9c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,6 +3,7 @@ language: php
 php:
   - 5.3
   - 5.4
+  - 5.5
 
 before_script:
   - curl -s http://getcomposer.org/installer | php
diff --git a/README.md b/README.md
index 8de8cc1..a9cefad 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ Build up your application through simple interfaces and re-use your application
 ##WebSocket Compliance
 
 * Supports the RFC6455, HyBi-10+, and Hixie76 protocol versions (at the same time)
-* Tested on Chrome 13 - 27, Firefox 6 - 21, Safari 5.0.1 - 6, iOS 4.2 - 6
+* Tested on Chrome 13 - 28, Firefox 6 - 22, Safari 5.0.1 - 6, iOS 4.2 - 7
 * Ratchet [passes](http://socketo.me/reports/ab/) the [Autobahn Testsuite](http://autobahn.ws/testsuite) (non-binary messages)
 
 ##Requirements
diff --git a/src/Ratchet/Http/HttpServer.php b/src/Ratchet/Http/HttpServer.php
index 5788807..f1b8f69 100644
--- a/src/Ratchet/Http/HttpServer.php
+++ b/src/Ratchet/Http/HttpServer.php
@@ -4,9 +4,6 @@ use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
 use Guzzle\Http\Message\Response;
 
-/**
- * @todo Detect HTTP proxy header IP, re-map remoteAddress
- */
 class HttpServer implements MessageComponentInterface {
     /**
      * Buffers incoming HTTP requests returning a Guzzle Request when coalesced

From f50af83fa7bbeb260ad9ec3288e1d2b53fbc4ea5 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sat, 20 Jul 2013 18:41:08 -0400
Subject: [PATCH 38/48] [Http][Security] OriginCheck + same host/origin policy

Added the Http\OriginCheck component that will only allow connections coming from desired Origins
Same host+origin policy by default: App.php, by default, will only allow connections from the given hostname
Fixes #102
---
 CHANGELOG.md                                  |  5 +-
 src/Ratchet/App.php                           | 21 ++++--
 src/Ratchet/Http/OriginCheck.php              | 69 +++++++++++++++++++
 .../AbstractMessageComponentTestCase.php      | 13 +++-
 tests/unit/Http/OriginCheckTest.php           | 46 +++++++++++++
 5 files changed, 147 insertions(+), 7 deletions(-)
 create mode 100644 src/Ratchet/Http/OriginCheck.php
 create mode 100644 tests/unit/Http/OriginCheckTest.php

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6066d00..b42cc47 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,10 +10,13 @@ CHANGELOG
 
 * 0.3.0 (2013-xx-xx)
 
- * Sugar and spice and everything nice: Added the Ratchet\App class for ease of use
+ * Added the `App` class to help making Ratchet so easy to use it's silly
+ * BC: Require hostname to do HTTP Host header match and do Origin HTTP header check, verify same name by default, helping prevent CSRF attacks
  * Added Symfony/2.2 based HTTP Router component to allowing for a single Ratchet server to handle multiple apps -> Ratchet\Http\Router
  * BC: Decoupled HTTP from WebSocket component -> Ratchet\Http\HttpServer
  * Updated dependency to React/0.3
+ * BF: Single sub-protocol selection to conform with RFC6455
+ * BF: Sanity checks on WAMP protocol to prevent errors
 
 * 0.2.7 (2013-06-09)
 
diff --git a/src/Ratchet/App.php b/src/Ratchet/App.php
index a3db257..5a00fdd 100644
--- a/src/Ratchet/App.php
+++ b/src/Ratchet/App.php
@@ -4,6 +4,7 @@ use React\EventLoop\LoopInterface;
 use React\EventLoop\Factory as LoopFactory;
 use React\Socket\Server as Reactor;
 use Ratchet\Http\HttpServerInterface;
+use Ratchet\Http\OriginCheck;
 use Ratchet\Wamp\WampServerInterface;
 use Ratchet\Server\IoServer;
 use Ratchet\Server\FlashPolicy;
@@ -77,11 +78,13 @@ class App {
     }
 
     /**
-     * @param string             $path
+     * @param                    $path
      * @param ComponentInterface $controller
-     * @return \Symfony\Component\Routing\Route
+     * @param array              $allowedOrigins An array of hosts allowed to connect (same host by default), [*] for any
+     * @param string             $httpHost Override the $httpHost variable provided in the __construct
+     * @return ComponentInterface|WsServer
      */
-    public function route($path, ComponentInterface $controller) {
+    public function route($path, ComponentInterface $controller, array $allowedOrigins = array(), $httpHost = null) {
         if ($controller instanceof HttpServerInterface || $controller instanceof WsServer) {
             $decorated = $controller;
         } elseif ($controller instanceof WampServerInterface) {
@@ -92,7 +95,17 @@ class App {
             $decorated = $controller;
         }
 
-        $this->routes->add('rr-' . ++$this->_routeCounter, new Route($path, array('_controller' => $decorated), array(), array(), $this->httpHost));
+        $httpHost = $httpHost ?: $this->httpHost;
+
+        if (0 === count($allowedOrigins)) {
+            $allowedOrigins[] = $httpHost;
+        }
+        $allowedOrigins = array_values($allowedOrigins);
+        if ('*' !== $allowedOrigins[0]) {
+            $decorated = new OriginCheck($decorated, $allowedOrigins);
+        }
+
+        $this->routes->add('rr-' . ++$this->_routeCounter, new Route($path, array('_controller' => $decorated), array('Origin' => $this->httpHost), array(), $httpHost));
 
         return $decorated;
     }
diff --git a/src/Ratchet/Http/OriginCheck.php b/src/Ratchet/Http/OriginCheck.php
new file mode 100644
index 0000000..e043fd8
--- /dev/null
+++ b/src/Ratchet/Http/OriginCheck.php
@@ -0,0 +1,69 @@
+<?php
+namespace Ratchet\Http;
+use Guzzle\Http\Message\RequestInterface;
+use Ratchet\ConnectionInterface;
+use Ratchet\MessageComponentInterface;
+use Guzzle\Http\Message\Response;
+
+class OriginCheck implements HttpServerInterface {
+    /**
+     * @var \Ratchet\MessageComponentInterface
+     */
+    protected $_component;
+
+    public $allowedOrigins = array();
+
+    public function __construct(MessageComponentInterface $component, array $allowed = array()) {
+        $this->_component = $component;
+        $this->allowedOrigins += $allowed;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) {
+        $origin = (string)$request->getHeader('Origin');
+
+        if (!in_array($origin, $this->allowedOrigins)) {
+            return $this->close($conn, 403);
+        }
+
+        return $this->_component->onOpen($conn, $request);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    function onMessage(ConnectionInterface $from, $msg) {
+        return $this->_component->onMessage($from, $msg);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    function onClose(ConnectionInterface $conn) {
+        return $this->_component->onClose($conn);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    function onError(ConnectionInterface $conn, \Exception $e) {
+        return $this->_component->onError($conn, $e);
+    }
+
+    /**
+     * Close a connection with an HTTP response
+     * @param \Ratchet\ConnectionInterface $conn
+     * @param int                          $code HTTP status code
+     * @return null
+     */
+    protected function close(ConnectionInterface $conn, $code = 400) {
+        $response = new Response($code, array(
+            'X-Powered-By' => \Ratchet\VERSION
+        ));
+
+        $conn->send((string)$response);
+        $conn->close();
+    }
+}
\ No newline at end of file
diff --git a/tests/helpers/Ratchet/AbstractMessageComponentTestCase.php b/tests/helpers/Ratchet/AbstractMessageComponentTestCase.php
index 990e98c..2ab458e 100644
--- a/tests/helpers/Ratchet/AbstractMessageComponentTestCase.php
+++ b/tests/helpers/Ratchet/AbstractMessageComponentTestCase.php
@@ -16,7 +16,11 @@ abstract class AbstractMessageComponentTestCase extends \PHPUnit_Framework_TestC
         $this->_serv = new $decorator($this->_app);
         $this->_conn = $this->getMock('\Ratchet\ConnectionInterface');
 
-        $this->_serv->onOpen($this->_conn);
+        $this->doOpen($this->_conn);
+    }
+
+    protected function doOpen($conn) {
+        $this->_serv->onOpen($conn);
     }
 
     public function isExpectedConnection() {
@@ -25,7 +29,7 @@ abstract class AbstractMessageComponentTestCase extends \PHPUnit_Framework_TestC
 
     public function testOpen() {
         $this->_app->expects($this->once())->method('onOpen')->with($this->isExpectedConnection());
-        $this->_serv->onOpen($this->getMock('\Ratchet\ConnectionInterface'));
+        $this->doOpen($this->getMock('\Ratchet\ConnectionInterface'));
     }
 
     public function testOnClose() {
@@ -38,4 +42,9 @@ abstract class AbstractMessageComponentTestCase extends \PHPUnit_Framework_TestC
         $this->_app->expects($this->once())->method('onError')->with($this->isExpectedConnection(), $e);
         $this->_serv->onError($this->_conn, $e);
     }
+
+    public function passthroughMessageTest($value) {
+        $this->_app->expects($this->once())->method('onMessage')->with($this->isExpectedConnection(), $value);
+        $this->_serv->onMessage($this->_conn, $value);
+    }
 }
\ No newline at end of file
diff --git a/tests/unit/Http/OriginCheckTest.php b/tests/unit/Http/OriginCheckTest.php
new file mode 100644
index 0000000..34db439
--- /dev/null
+++ b/tests/unit/Http/OriginCheckTest.php
@@ -0,0 +1,46 @@
+<?php
+namespace Ratchet\Http;
+use Ratchet\AbstractMessageComponentTestCase;
+
+/**
+ * @covers Ratchet\Http\OriginCheck
+ */
+class OriginCheckTest extends AbstractMessageComponentTestCase {
+    protected $_reqStub;
+
+    public function setUp() {
+        $this->_reqStub = $this->getMock('Guzzle\Http\Message\RequestInterface');
+        $this->_reqStub->expects($this->any())->method('getHeader')->will($this->returnValue('localhost'));
+
+        parent::setUp();
+
+        $this->_serv->allowedOrigins[] = 'localhost';
+    }
+
+    protected function doOpen($conn) {
+        $this->_serv->onOpen($conn, $this->_reqStub);
+    }
+
+    public function getConnectionClassString() {
+        return '\Ratchet\ConnectionInterface';
+    }
+
+    public function getDecoratorClassString() {
+        return '\Ratchet\Http\OriginCheck';
+    }
+
+    public function getComponentClassString() {
+        return '\Ratchet\Http\HttpServerInterface';
+    }
+
+    public function testCloseOnNonMatchingOrigin() {
+        $this->_serv->allowedOrigins = array('socketo.me');
+        $this->_conn->expects($this->once())->method('close');
+
+        $this->_serv->onOpen($this->_conn, $this->_reqStub);
+    }
+
+    public function testOnMessage() {
+        $this->passthroughMessageTest('Hello World!');
+    }
+}

From eb77cf139ef54729b7e8dd97664fe48850bd9b20 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sat, 20 Jul 2013 22:03:46 -0400
Subject: [PATCH 39/48] Updated example, slight Origin order change in app

---
 README.md           | 20 ++++++++++++++------
 src/Ratchet/App.php |  2 +-
 2 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/README.md b/README.md
index a9cefad..1ea2fca 100644
--- a/README.md
+++ b/README.md
@@ -30,20 +30,21 @@ Need help?  Have a question?  Want to provide feedback?  Write a message on the
 
 ---
 
-###A quick server example
+###A quick example
 
 ```php
 <?php
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
 
+    // Make sure composer dependencies have been installed
     require __DIR__ . '/vendor/autoload.php';
 
 /**
  * chat.php
  * Send any incoming messages to all connected clients (except sender)
  */
-class Chat implements MessageComponentInterface {
+class MyChat implements MessageComponentInterface {
     protected $clients;
 
     public function __construct() {
@@ -72,10 +73,17 @@ class Chat implements MessageComponentInterface {
 }
 
     // Run the server application through the WebSocket protocol on port 8080
-    $app = new Ratchet\App('example.com', 8080);
-    $app->route('/chat', new Chat);
-    $app->route('/echo', new Ratchet\Server\EchoServer);
+    $app = new Ratchet\App('localhost', 8080);
+    $app->route('/chat', new MyChat);
+    $app->route('/echo', new Ratchet\Server\EchoServer, array(*));
     $app->run();
 ```
 
-    $ php chat.php
\ No newline at end of file
+    $ php chat.php
+
+```javascript
+    // Then some JavaScript in the browser:
+    var conn = new WebSocket('ws://localhost/echo');
+    conn.onmessage = function(e) { console.log(e.data); };
+    conn.send('Hello Me!');
+```
\ No newline at end of file
diff --git a/src/Ratchet/App.php b/src/Ratchet/App.php
index 5a00fdd..3d8dec0 100644
--- a/src/Ratchet/App.php
+++ b/src/Ratchet/App.php
@@ -97,10 +97,10 @@ class App {
 
         $httpHost = $httpHost ?: $this->httpHost;
 
+        $allowedOrigins = array_values($allowedOrigins);
         if (0 === count($allowedOrigins)) {
             $allowedOrigins[] = $httpHost;
         }
-        $allowedOrigins = array_values($allowedOrigins);
         if ('*' !== $allowedOrigins[0]) {
             $decorated = new OriginCheck($decorated, $allowedOrigins);
         }

From 55c880a1002fc67a64ce7c32f6ba79168e5afee6 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Sat, 20 Jul 2013 22:04:23 -0400
Subject: [PATCH 40/48] ReadMe port fix

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 1ea2fca..5ac53b6 100644
--- a/README.md
+++ b/README.md
@@ -83,7 +83,7 @@ class MyChat implements MessageComponentInterface {
 
 ```javascript
     // Then some JavaScript in the browser:
-    var conn = new WebSocket('ws://localhost/echo');
+    var conn = new WebSocket('ws://localhost:8080/echo');
     conn.onmessage = function(e) { console.log(e.data); };
     conn.send('Hello Me!');
 ```
\ No newline at end of file

From 4039a643eae9f1386bb4e2c78cb834cd798b3249 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Mon, 22 Jul 2013 21:03:19 -0400
Subject: [PATCH 41/48] API docs on new features

---
 src/Ratchet/App.php               | 23 +++++++++++++++++------
 src/Ratchet/Http/OriginCheck.php  |  9 +++++++++
 src/Ratchet/Server/EchoServer.php |  5 +++--
 3 files changed, 29 insertions(+), 8 deletions(-)

diff --git a/src/Ratchet/App.php b/src/Ratchet/App.php
index 3d8dec0..cc44694 100644
--- a/src/Ratchet/App.php
+++ b/src/Ratchet/App.php
@@ -17,6 +17,10 @@ use Symfony\Component\Routing\Route;
 use Symfony\Component\Routing\RequestContext;
 use Symfony\Component\Routing\Matcher\UrlMatcher;
 
+/**
+ * An opinionated facade class to quickly and easily create a WebSocket server.
+ * A few configuration assumptions are made and some best-practice security conventions are applied by default.
+ */
 class App {
     /**
      * @var \Symfony\Component\Routing\RouteCollection
@@ -39,13 +43,16 @@ class App {
      */
     protected $httpHost;
 
+    /**
+     * @var int
+     */
     protected $_routeCounter = 0;
 
     /**
-     * @param string        $httpHost
-     * @param int           $port
-     * @param string        $address
-     * @param LoopInterface $loop
+     * @param string        $httpHost HTTP hostname clients intend to connect to. MUST match JS `new WebSocket('ws://$httpHost');`
+     * @param int           $port     Port to listen on. If 80, assuming production, Flash on 843 otherwise expecting Flash to be proxied through 8843
+     * @param string        $address  IP address to bind to. Default is localhost/proxy only. '0.0.0.0' for any machine.
+     * @param LoopInterface $loop     Specific React\EventLoop to bind the application to. null will create one for you.
      */
     public function __construct($httpHost = 'localhost', $port = 8080, $address = '127.0.0.1', LoopInterface $loop = null) {
         if (extension_loaded('xdebug')) {
@@ -78,8 +85,9 @@ class App {
     }
 
     /**
-     * @param                    $path
-     * @param ComponentInterface $controller
+     * Add an endpiont/application to the server
+     * @param string             $path The URI the client will connect to
+     * @param ComponentInterface $controller Your application to server for the route. If not specified, assumed to be for a WebSocket
      * @param array              $allowedOrigins An array of hosts allowed to connect (same host by default), [*] for any
      * @param string             $httpHost Override the $httpHost variable provided in the __construct
      * @return ComponentInterface|WsServer
@@ -110,6 +118,9 @@ class App {
         return $decorated;
     }
 
+    /**
+     * Run the server by entering the event loop
+     */
     public function run() {
         $this->_server->run();
     }
diff --git a/src/Ratchet/Http/OriginCheck.php b/src/Ratchet/Http/OriginCheck.php
index e043fd8..580935a 100644
--- a/src/Ratchet/Http/OriginCheck.php
+++ b/src/Ratchet/Http/OriginCheck.php
@@ -5,6 +5,11 @@ use Ratchet\ConnectionInterface;
 use Ratchet\MessageComponentInterface;
 use Guzzle\Http\Message\Response;
 
+/**
+ * A middleware to ensure JavaScript clients connecting are from the expected domain.
+ * This protects other websites from open WebSocket connections to your application.
+ * Note: This can be spoofed from non-web browser clients
+ */
 class OriginCheck implements HttpServerInterface {
     /**
      * @var \Ratchet\MessageComponentInterface
@@ -13,6 +18,10 @@ class OriginCheck implements HttpServerInterface {
 
     public $allowedOrigins = array();
 
+    /**
+     * @param MessageComponentInterface $component Component/Application to decorate
+     * @param array                     $allowed An array of allowed domains that are allowed to connect from
+     */
     public function __construct(MessageComponentInterface $component, array $allowed = array()) {
         $this->_component = $component;
         $this->allowedOrigins += $allowed;
diff --git a/src/Ratchet/Server/EchoServer.php b/src/Ratchet/Server/EchoServer.php
index 3f5069b..4011d66 100644
--- a/src/Ratchet/Server/EchoServer.php
+++ b/src/Ratchet/Server/EchoServer.php
@@ -3,6 +3,9 @@ namespace Ratchet\Server;
 use Ratchet\MessageComponentInterface;
 use Ratchet\ConnectionInterface;
 
+/**
+ * A simple Ratchet application that will reply to all messages with the message it received
+ */
 class EchoServer implements MessageComponentInterface {
     public function onOpen(ConnectionInterface $conn) {
     }
@@ -15,8 +18,6 @@ class EchoServer implements MessageComponentInterface {
     }
 
     public function onError(ConnectionInterface $conn, \Exception $e) {
-        echo $e->getMessage() . "\n";
-
         $conn->close();
     }
 }
\ No newline at end of file

From 6559aaf1d45b4bcdde7fdf69e967efd8ea521357 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Mon, 5 Aug 2013 16:23:38 -0400
Subject: [PATCH 42/48] [Http] Fixed bug in Origin check - browser may pass
 http://

---
 src/Ratchet/Http/OriginCheck.php | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/Ratchet/Http/OriginCheck.php b/src/Ratchet/Http/OriginCheck.php
index 580935a..8d5f7a1 100644
--- a/src/Ratchet/Http/OriginCheck.php
+++ b/src/Ratchet/Http/OriginCheck.php
@@ -31,7 +31,8 @@ class OriginCheck implements HttpServerInterface {
      * {@inheritdoc}
      */
     public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) {
-        $origin = (string)$request->getHeader('Origin');
+        $header = (string)$request->getHeader('Origin');
+        $origin = parse_url($header, PHP_URL_HOST) ?: $header;
 
         if (!in_array($origin, $this->allowedOrigins)) {
             return $this->close($conn, 403);

From 25ff6deb77c8877136d0305fc0e39a094ce10ca9 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Mon, 5 Aug 2013 17:20:05 -0400
Subject: [PATCH 43/48] [Flash] Close connection after delivering policy

---
 src/Ratchet/Server/FlashPolicy.php | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/Ratchet/Server/FlashPolicy.php b/src/Ratchet/Server/FlashPolicy.php
index ec64c78..f0ee26f 100644
--- a/src/Ratchet/Server/FlashPolicy.php
+++ b/src/Ratchet/Server/FlashPolicy.php
@@ -108,6 +108,7 @@ class FlashPolicy implements MessageComponentInterface {
         }
 
         $from->send($this->_cache . "\0");
+        $from->close();
     }
 
     /**

From 1370cb6109e8e061dcda43bd38cd424b37ac727b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lo=C3=AFc=20Doigni=C3=A9?= <loic.doignie.ext@nordnet.fr>
Date: Tue, 8 Oct 2013 08:51:25 +0200
Subject: [PATCH 44/48] This modification gives Ratchet its own RequestFactory
 instance.

This way you can use guzzle as REST Client.
---
 .../Http/Guzzle/Http/Message/RequestFactory.php | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/src/Ratchet/Http/Guzzle/Http/Message/RequestFactory.php b/src/Ratchet/Http/Guzzle/Http/Message/RequestFactory.php
index abf8aac..7457871 100644
--- a/src/Ratchet/Http/Guzzle/Http/Message/RequestFactory.php
+++ b/src/Ratchet/Http/Guzzle/Http/Message/RequestFactory.php
@@ -4,6 +4,23 @@ use Guzzle\Http\Message\RequestFactory as GuzzleRequestFactory;
 use Guzzle\Http\EntityBody;
 
 class RequestFactory extends GuzzleRequestFactory {
+
+    protected static $ratchetInstance;
+    
+    /**
+     * {@inheritdoc}
+     */
+    public static function getInstance()
+    {
+        // @codeCoverageIgnoreStart
+        if (!static::$ratchetInstance) {
+            static::$ratchetInstance = new static();
+        }
+        // @codeCoverageIgnoreEnd
+
+        return static::$ratchetInstance;
+    }
+		
     /**
      * {@inheritdoc}
      */

From f40bb94a922f81197964e409f5cd2321ddc82863 Mon Sep 17 00:00:00 2001
From: Florian Rey <nervo@nervo.net>
Date: Thu, 10 Oct 2013 13:40:26 +0200
Subject: [PATCH 45/48] Test for connection attachement before cascading error

---
 src/Ratchet/WebSocket/WsServer.php | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/Ratchet/WebSocket/WsServer.php b/src/Ratchet/WebSocket/WsServer.php
index 9337934..1b7c199 100644
--- a/src/Ratchet/WebSocket/WsServer.php
+++ b/src/Ratchet/WebSocket/WsServer.php
@@ -150,7 +150,9 @@ class WsServer implements HttpServerInterface {
      */
     public function onError(ConnectionInterface $conn, \Exception $e) {
         if ($conn->WebSocket->established) {
-            $this->component->onError($this->connections[$conn], $e);
+            if ($this->connections->contains($conn)) {
+                $this->component->onError($this->connections[$conn], $e);
+            }
         } else {
             $conn->close();
         }

From 069133ca352525a90840d71918b0067f6a73eb25 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Mon, 14 Oct 2013 10:20:32 -0400
Subject: [PATCH 46/48] Updated ops files for 0.3 release

---
 CHANGELOG.md                        |  8 +----
 Makefile                            |  2 +-
 README.md                           |  2 +-
 composer.lock                       | 46 ++++++++++++++---------------
 src/Ratchet/ConnectionInterface.php |  2 +-
 5 files changed, 27 insertions(+), 33 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6b55312..2c16bde 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,7 +14,6 @@ CHANGELOG
  * BC: Require hostname to do HTTP Host header match and do Origin HTTP header check, verify same name by default, helping prevent CSRF attacks
  * Added Symfony/2.2 based HTTP Router component to allowing for a single Ratchet server to handle multiple apps -> Ratchet\Http\Router
  * BC: Decoupled HTTP from WebSocket component -> Ratchet\Http\HttpServer
- * Updated dependency to React/0.3
  * BF: Single sub-protocol selection to conform with RFC6455
  * BF: Sanity checks on WAMP protocol to prevent errors
 
@@ -95,9 +94,4 @@ CHANGELOG
 * 0.1 (2012-05-11)
 
  * First release with components: IoServer, WsServer, SessionProvider, WampServer, FlashPolicy, IpBlackList
-<<<<<<< HEAD
- * I/O now handled by React, making Ratchet fully asynchronous
-
-=======
- * I/O now handled by React, making Ratchet fully asynchronous 
->>>>>>> refs/heads/master
+ * I/O now handled by React, making Ratchet fully asynchronous
\ No newline at end of file
diff --git a/Makefile b/Makefile
index aa143cc..0595b04 100644
--- a/Makefile
+++ b/Makefile
@@ -30,5 +30,5 @@ apidocs:
 		-s vendor/react \
 		-s vendor/guzzle \
 		-s vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/Session \
-		-s vendor/symfony/http-foundation/Symfony/Component/Routing \
+		-s vendor/symfony/routing/Symfony/Component/Routing \
 		-s vendor/evenement/evenement/src/Evenement
diff --git a/README.md b/README.md
index 5ac53b6..fa127b6 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ Build up your application through simple interfaces and re-use your application
 ##WebSocket Compliance
 
 * Supports the RFC6455, HyBi-10+, and Hixie76 protocol versions (at the same time)
-* Tested on Chrome 13 - 28, Firefox 6 - 22, Safari 5.0.1 - 6, iOS 4.2 - 7
+* Tested on Chrome 13 - 30, Firefox 6 - 24, Safari 5.0.1 - 6, iOS 4.2 - 7
 * Ratchet [passes](http://socketo.me/reports/ab/) the [Autobahn Testsuite](http://autobahn.ws/testsuite) (non-binary messages)
 
 ##Requirements
diff --git a/composer.lock b/composer.lock
index fba7c14..ec801f4 100644
--- a/composer.lock
+++ b/composer.lock
@@ -47,17 +47,17 @@
         },
         {
             "name": "guzzle/common",
-            "version": "v3.7.3",
+            "version": "v3.7.4",
             "target-dir": "Guzzle/Common",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/common.git",
-                "reference": "bf73c87375f60861f8c7ccc7b95878023ade5306"
+                "reference": "5126e268446c7e7df961b89128d71878e0652432"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/common/zipball/bf73c87375f60861f8c7ccc7b95878023ade5306",
-                "reference": "bf73c87375f60861f8c7ccc7b95878023ade5306",
+                "url": "https://api.github.com/repos/guzzle/common/zipball/5126e268446c7e7df961b89128d71878e0652432",
+                "reference": "5126e268446c7e7df961b89128d71878e0652432",
                 "shasum": ""
             },
             "require": {
@@ -87,21 +87,21 @@
                 "event",
                 "exception"
             ],
-            "time": "2013-09-08 21:09:18"
+            "time": "2013-10-02 20:47:00"
         },
         {
             "name": "guzzle/http",
-            "version": "v3.7.3",
+            "version": "v3.7.4",
             "target-dir": "Guzzle/Http",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/http.git",
-                "reference": "1034125dfd906b73119e535f03153a62fccb1989"
+                "reference": "3420035adcf312d62a2e64f3e6b3e3e590121786"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/http/zipball/1034125dfd906b73119e535f03153a62fccb1989",
-                "reference": "1034125dfd906b73119e535f03153a62fccb1989",
+                "url": "https://api.github.com/repos/guzzle/http/zipball/3420035adcf312d62a2e64f3e6b3e3e590121786",
+                "reference": "3420035adcf312d62a2e64f3e6b3e3e590121786",
                 "shasum": ""
             },
             "require": {
@@ -144,11 +144,11 @@
                 "http",
                 "http client"
             ],
-            "time": "2013-09-06 11:34:26"
+            "time": "2013-09-20 22:05:53"
         },
         {
             "name": "guzzle/parser",
-            "version": "v3.7.3",
+            "version": "v3.7.4",
             "target-dir": "Guzzle/Parser",
             "source": {
                 "type": "git",
@@ -192,7 +192,7 @@
         },
         {
             "name": "guzzle/stream",
-            "version": "v3.7.3",
+            "version": "v3.7.4",
             "target-dir": "Guzzle/Stream",
             "source": {
                 "type": "git",
@@ -375,7 +375,7 @@
         },
         {
             "name": "symfony/event-dispatcher",
-            "version": "v2.3.5",
+            "version": "v2.3.6",
             "target-dir": "Symfony/Component/EventDispatcher",
             "source": {
                 "type": "git",
@@ -429,17 +429,17 @@
         },
         {
             "name": "symfony/http-foundation",
-            "version": "v2.3.4",
+            "version": "v2.3.6",
             "target-dir": "Symfony/Component/HttpFoundation",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/HttpFoundation.git",
-                "reference": "fdf130fe65457aedbc4639a22f4ef9d3be5c002c"
+                "reference": "59e712338cd05463ebcb8da6422a01b1291871e3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/fdf130fe65457aedbc4639a22f4ef9d3be5c002c",
-                "reference": "fdf130fe65457aedbc4639a22f4ef9d3be5c002c",
+                "url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/59e712338cd05463ebcb8da6422a01b1291871e3",
+                "reference": "59e712338cd05463ebcb8da6422a01b1291871e3",
                 "shasum": ""
             },
             "require": {
@@ -475,21 +475,21 @@
             ],
             "description": "Symfony HttpFoundation Component",
             "homepage": "http://symfony.com",
-            "time": "2013-08-26 05:49:51"
+            "time": "2013-09-29 19:41:41"
         },
         {
             "name": "symfony/routing",
-            "version": "v2.3.5",
+            "version": "v2.3.6",
             "target-dir": "Symfony/Component/Routing",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/Routing.git",
-                "reference": "6d1f7b101337594fe790c47166068583b60b6460"
+                "reference": "7d41463094752e87a0fae60316d236abecb8a034"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Routing/zipball/6d1f7b101337594fe790c47166068583b60b6460",
-                "reference": "6d1f7b101337594fe790c47166068583b60b6460",
+                "url": "https://api.github.com/repos/symfony/Routing/zipball/7d41463094752e87a0fae60316d236abecb8a034",
+                "reference": "7d41463094752e87a0fae60316d236abecb8a034",
                 "shasum": ""
             },
             "require": {
@@ -533,7 +533,7 @@
             ],
             "description": "Symfony Routing Component",
             "homepage": "http://symfony.com",
-            "time": "2013-09-19 09:45:20"
+            "time": "2013-09-29 19:41:41"
         }
     ],
     "packages-dev": [
diff --git a/src/Ratchet/ConnectionInterface.php b/src/Ratchet/ConnectionInterface.php
index 088823d..5cf8e71 100644
--- a/src/Ratchet/ConnectionInterface.php
+++ b/src/Ratchet/ConnectionInterface.php
@@ -5,7 +5,7 @@ namespace Ratchet;
  * The version of Ratchet being used
  * @var string
  */
-const VERSION = 'Ratchet/0.3-beta';
+const VERSION = 'Ratchet/0.3';
 
 /**
  * A proxy object representing a connection to the application

From ef5ece0739ea62cedbd9f865e122b5f41975fcfe Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Mon, 14 Oct 2013 10:25:51 -0400
Subject: [PATCH 47/48] [ws] Updated onError handle to make sure to close if
 conditions aren't met

---
 src/Ratchet/WebSocket/WsServer.php | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/Ratchet/WebSocket/WsServer.php b/src/Ratchet/WebSocket/WsServer.php
index 1b7c199..c76fd3f 100644
--- a/src/Ratchet/WebSocket/WsServer.php
+++ b/src/Ratchet/WebSocket/WsServer.php
@@ -149,10 +149,8 @@ class WsServer implements HttpServerInterface {
      * {@inheritdoc}
      */
     public function onError(ConnectionInterface $conn, \Exception $e) {
-        if ($conn->WebSocket->established) {
-            if ($this->connections->contains($conn)) {
-                $this->component->onError($this->connections[$conn], $e);
-            }
+        if ($conn->WebSocket->established && $this->connections->contains($conn)) {
+            $this->component->onError($this->connections[$conn], $e);
         } else {
             $conn->close();
         }

From 7336bc71ac2654dd3251e31f0b5ec147cc9c8490 Mon Sep 17 00:00:00 2001
From: Chris Boden <cboden@gmail.com>
Date: Mon, 14 Oct 2013 10:38:06 -0400
Subject: [PATCH 48/48] Added release date on changelog

---
 CHANGELOG.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2c16bde..7aae881 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,7 +8,7 @@ CHANGELOG
 
 ---
 
-* 0.3.0 (2013-xx-xx)
+* 0.3.0 (2013-10-14)
 
  * Added the `App` class to help making Ratchet so easy to use it's silly
  * BC: Require hostname to do HTTP Host header match and do Origin HTTP header check, verify same name by default, helping prevent CSRF attacks