mxmbsocket/src/Ratchet/Http/Router.php

108 lines
3.4 KiB
PHP

<?php
namespace Ratchet\Http;
use Ratchet\ConnectionInterface;
use Guzzle\Http\Message\RequestInterface;
use Guzzle\Http\Message\Response;
use Guzzle\Http\Url;
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;
}
/**
* {@inheritdoc}
* @throws \UnexpectedValueException If a controller is not \Ratchet\Http\HttpServerInterface
*/
public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) {
if (null === $request) {
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) {
return $this->close($conn, 405, array('Allow' => $nae->getAllowedMethods()));
} catch (ResourceNotFoundException $nfe) {
return $this->close($conn, 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\Http\HttpServerInterface');
}
$parameters = array();
foreach($route as $key => $value) {
if ((is_string($key)) && ('_' !== substr($key, 0, 1))) {
$parameters[$key] = $value;
}
}
$parameters = array_merge($parameters, $request->getQuery()->getAll());
$url = Url::factory($request->getUrl());
$url->setQuery($parameters);
$request->setUrl($url);
$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) {
if (isset($conn->controller)) {
$conn->controller->onClose($conn);
}
}
/**
* {@inheritdoc}
*/
function onError(ConnectionInterface $conn, \Exception $e) {
if (isset($conn->controller)) {
$conn->controller->onError($conn, $e);
}
}
/**
* Close a connection with an HTTP response
* @param \Ratchet\ConnectionInterface $conn
* @param int $code HTTP status code
* @param array $additionalHeaders
* @return null
*/
protected function close(ConnectionInterface $conn, $code = 400, array $additionalHeaders = array()) {
$headers = array_merge(array(
'X-Powered-By' => \Ratchet\VERSION
), $additionalHeaders);
$response = new Response($code, $headers);
$conn->send((string)$response);
$conn->close();
}
}