HTTP Decouple spike
This commit is contained in:
parent
3f64caf8cb
commit
7b2b6897e5
99
src/Ratchet/Http/HttpServer.php
Normal file
99
src/Ratchet/Http/HttpServer.php
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
14
src/Ratchet/Http/HttpServerInterface.php
Normal file
14
src/Ratchet/Http/HttpServerInterface.php
Normal file
@ -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);
|
||||||
|
}
|
@ -6,13 +6,16 @@ use Ratchet\WebSocket\Version;
|
|||||||
use Ratchet\WebSocket\Encoding\ToggleableValidator;
|
use Ratchet\WebSocket\Encoding\ToggleableValidator;
|
||||||
use Guzzle\Http\Message\Response;
|
use Guzzle\Http\Message\Response;
|
||||||
|
|
||||||
|
use Guzzle\Http\Message\RequestInterface;
|
||||||
|
use Ratchet\Http\HttpServerInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The adapter to handle WebSocket requests/responses
|
* 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
|
* 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://ca.php.net/manual/en/ref.http.php
|
||||||
* @link http://dev.w3.org/html5/websockets/
|
* @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
|
* Buffers incoming HTTP requests returning a Guzzle Request when coalesced
|
||||||
* @var HttpRequestParser
|
* @var HttpRequestParser
|
||||||
@ -79,9 +82,12 @@ class WsServer implements MessageComponentInterface {
|
|||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function onOpen(ConnectionInterface $conn) {
|
public function onOpen(ConnectionInterface $conn, RequestInterface $headers = null) {
|
||||||
$conn->WebSocket = new \StdClass;
|
$conn->WebSocket = new \StdClass;
|
||||||
|
$conn->WebSocket->request = $headers;
|
||||||
$conn->WebSocket->established = false;
|
$conn->WebSocket->established = false;
|
||||||
|
|
||||||
|
$this->attemptUpgrade($conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,46 +98,42 @@ class WsServer implements MessageComponentInterface {
|
|||||||
return $from->WebSocket->version->onMessage($this->connections[$from], $msg);
|
return $from->WebSocket->version->onMessage($this->connections[$from], $msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($from->WebSocket->request)) {
|
$this->attemptUpgrade($from, $msg);
|
||||||
$from->WebSocket->request->getBody()->write($msg);
|
}
|
||||||
|
|
||||||
|
protected function attemptUpgrade(ConnectionInterface $conn, $data = '') {
|
||||||
|
if ('' !== $data) {
|
||||||
|
$conn->WebSocket->request->getBody()->write($data);
|
||||||
} else {
|
} else {
|
||||||
try {
|
if (!$this->versioner->isVersionEnabled($conn->WebSocket->request)) {
|
||||||
if (null === ($request = $this->reqParser->onMessage($from, $msg))) {
|
return $this->close($conn);
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (\OverflowException $oe) {
|
|
||||||
return $this->close($from, 413);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->versioner->isVersionEnabled($request)) {
|
$conn->WebSocket->request = $conn->WebSocket->request;
|
||||||
return $this->close($from);
|
$conn->WebSocket->version = $this->versioner->getVersion($conn->WebSocket->request);
|
||||||
}
|
|
||||||
|
|
||||||
$from->WebSocket->request = $request;
|
|
||||||
$from->WebSocket->version = $this->versioner->getVersion($request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$response = $from->WebSocket->version->handshake($from->WebSocket->request);
|
$response = $conn->WebSocket->version->handshake($conn->WebSocket->request);
|
||||||
} catch (\UnderflowException $e) {
|
} catch (\UnderflowException $e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This needs to be refactored later on, incorporated with routing
|
// 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('Sec-WebSocket-Protocol', $agreedSubProtocols);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response->setHeader('X-Powered-By', \Ratchet\VERSION);
|
$response->setHeader('X-Powered-By', \Ratchet\VERSION);
|
||||||
$from->send((string)$response);
|
$conn->send((string)$response);
|
||||||
|
|
||||||
if (101 != $response->getStatusCode()) {
|
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;
|
$upgraded->WebSocket->established = true;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user