Replace guzzle based request/response object with PSR-17 factory

This commit is contained in:
Dawid Królak 2019-10-16 22:51:02 +02:00
parent 9eae01044a
commit f9a5094726
7 changed files with 70 additions and 49 deletions

View File

@ -22,11 +22,12 @@
}, },
"require": { "require": {
"php": ">=5.4.2", "php": ">=5.4.2",
"guzzlehttp/psr7": "^1.0" "psr/http-factory-implementation": "^1.0"
}, },
"require-dev": { "require-dev": {
"react/http": "^0.4.1", "react/http": "^0.4.1",
"react/socket-client": "^0.4.3", "react/socket-client": "^0.4.3",
"phpunit/phpunit": "4.8.*" "phpunit/phpunit": "4.8.*",
"guzzlehttp/psr7": "^2.0-dev"
} }
} }

View File

@ -3,7 +3,7 @@ namespace Ratchet\RFC6455\Handshake;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UriInterface; use Psr\Http\Message\UriInterface;
use GuzzleHttp\Psr7\Request; use Psr\Http\Message\RequestFactoryInterface;
class ClientNegotiator { class ClientNegotiator {
/** /**
@ -16,20 +16,26 @@ class ClientNegotiator {
*/ */
private $defaultHeader; private $defaultHeader;
function __construct() { /**
$this->verifier = new ResponseVerifier; * @var RequestFactoryInterface
*/
private $requestFactory;
$this->defaultHeader = new Request('GET', '', [ function __construct(RequestFactoryInterface $requestFactory) {
'Connection' => 'Upgrade' $this->verifier = new ResponseVerifier;
, 'Upgrade' => 'websocket' $this->requestFactory = $requestFactory;
, 'Sec-WebSocket-Version' => $this->getVersion()
, 'User-Agent' => "Ratchet" $this->defaultHeader = $this->requestFactory
]); ->createRequest('GET', '')
->withHeader('Connection' , 'Upgrade')
->withHeader('Upgrade' , 'websocket')
->withHeader('Sec-WebSocket-Version', $this->getVersion())
->withHeader('User-Agent' , 'Ratchet');
} }
public function generateRequest(UriInterface $uri) { public function generateRequest(UriInterface $uri) {
return $this->defaultHeader->withUri($uri) return $this->defaultHeader->withUri($uri)
->withHeader("Sec-WebSocket-Key", $this->generateKey()); ->withHeader('Sec-WebSocket-Key', $this->generateKey());
} }
public function validateResponse(RequestInterface $request, ResponseInterface $response) { public function validateResponse(RequestInterface $request, ResponseInterface $response) {

View File

@ -1,7 +1,7 @@
<?php <?php
namespace Ratchet\RFC6455\Handshake; namespace Ratchet\RFC6455\Handshake;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use GuzzleHttp\Psr7\Response; use Psr\Http\Message\ResponseFactoryInterface;
/** /**
* The latest version of the WebSocket protocol * The latest version of the WebSocket protocol
@ -13,12 +13,18 @@ class ServerNegotiator implements NegotiatorInterface {
*/ */
private $verifier; private $verifier;
/**
* @var ResponseFactoryInterface
*/
private $responseFactory;
private $_supportedSubProtocols = []; private $_supportedSubProtocols = [];
private $_strictSubProtocols = false; private $_strictSubProtocols = false;
public function __construct(RequestVerifier $requestVerifier) { public function __construct(RequestVerifier $requestVerifier, ResponseFactoryInterface $responseFactory) {
$this->verifier = $requestVerifier; $this->verifier = $requestVerifier;
$this->responseFactory = $responseFactory;
} }
/** /**
@ -39,47 +45,49 @@ class ServerNegotiator implements NegotiatorInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function handshake(RequestInterface $request) { public function handshake(RequestInterface $request) {
$response = $this->responseFactory->createResponse();
if (true !== $this->verifier->verifyMethod($request->getMethod())) { if (true !== $this->verifier->verifyMethod($request->getMethod())) {
return new Response(405, ['Allow' => 'GET']); return $response->withHeader('Allow', 'GET')->withStatus(405);
} }
if (true !== $this->verifier->verifyHTTPVersion($request->getProtocolVersion())) { if (true !== $this->verifier->verifyHTTPVersion($request->getProtocolVersion())) {
return new Response(505); return $response->withStatus(505);
} }
if (true !== $this->verifier->verifyRequestURI($request->getUri()->getPath())) { if (true !== $this->verifier->verifyRequestURI($request->getUri()->getPath())) {
return new Response(400); return $response->withStatus(400);
} }
if (true !== $this->verifier->verifyHost($request->getHeader('Host'))) { if (true !== $this->verifier->verifyHost($request->getHeader('Host'))) {
return new Response(400); return $response->withStatus(400);
} }
$upgradeSuggestion = [ $upgradeResponse = $response
'Connection' => 'Upgrade', ->withHeader('Connection' , 'Upgrade')
'Upgrade' => 'websocket', ->withHeader('Upgrade' , 'websocket')
'Sec-WebSocket-Version' => $this->getVersionNumber() ->withHeader('Sec-WebSocket-Version', $this->getVersionNumber());
];
if (count($this->_supportedSubProtocols) > 0) { if (count($this->_supportedSubProtocols) > 0) {
$upgradeSuggestion['Sec-WebSocket-Protocol'] = implode(', ', array_keys($this->_supportedSubProtocols)); $upgradeResponse = $upgradeResponse->withHeader(
'Sec-WebSocket-Protocol', implode(', ', array_keys($this->_supportedSubProtocols))
);
} }
if (true !== $this->verifier->verifyUpgradeRequest($request->getHeader('Upgrade'))) { if (true !== $this->verifier->verifyUpgradeRequest($request->getHeader('Upgrade'))) {
return new Response(426, $upgradeSuggestion, null, '1.1', 'Upgrade header MUST be provided'); return $upgradeResponse->withStatus(426, 'Upgrade header MUST be provided');
} }
if (true !== $this->verifier->verifyConnection($request->getHeader('Connection'))) { if (true !== $this->verifier->verifyConnection($request->getHeader('Connection'))) {
return new Response(400, [], null, '1.1', 'Connection Upgrade MUST be requested'); return $response->withStatus(400, 'Connection Upgrade MUST be requested');
} }
if (true !== $this->verifier->verifyKey($request->getHeader('Sec-WebSocket-Key'))) { if (true !== $this->verifier->verifyKey($request->getHeader('Sec-WebSocket-Key'))) {
return new Response(400, [], null, '1.1', 'Invalid Sec-WebSocket-Key'); return $response->withStatus(400, 'Invalid Sec-WebSocket-Key');
} }
if (true !== $this->verifier->verifyVersion($request->getHeader('Sec-WebSocket-Version'))) { if (true !== $this->verifier->verifyVersion($request->getHeader('Sec-WebSocket-Version'))) {
return new Response(426, $upgradeSuggestion); return $upgradeResponse->withStatus(426);
} }
$headers = [];
$subProtocols = $request->getHeader('Sec-WebSocket-Protocol'); $subProtocols = $request->getHeader('Sec-WebSocket-Protocol');
if (count($subProtocols) > 0 || (count($this->_supportedSubProtocols) > 0 && $this->_strictSubProtocols)) { if (count($subProtocols) > 0 || (count($this->_supportedSubProtocols) > 0 && $this->_strictSubProtocols)) {
$subProtocols = array_map('trim', explode(',', implode(',', $subProtocols))); $subProtocols = array_map('trim', explode(',', implode(',', $subProtocols)));
@ -89,20 +97,19 @@ class ServerNegotiator implements NegotiatorInterface {
}, null); }, null);
if ($this->_strictSubProtocols && null === $match) { if ($this->_strictSubProtocols && null === $match) {
return new Response(426, $upgradeSuggestion, null, '1.1', 'No Sec-WebSocket-Protocols requested supported'); return $upgradeResponse->withStatus(426, 'No Sec-WebSocket-Protocols requested supported');
} }
if (null !== $match) { if (null !== $match) {
$headers['Sec-WebSocket-Protocol'] = $match; $response = $response->withHeader('Sec-WebSocket-Protocol', $match);
} }
} }
return $response
return new Response(101, array_merge($headers, [ ->withStatus(101)
'Upgrade' => 'websocket' ->withHeader('Upgrade' , 'websocket')
, 'Connection' => 'Upgrade' ->withHeader('Connection' , 'Upgrade')
, 'Sec-WebSocket-Accept' => $this->sign((string)$request->getHeader('Sec-WebSocket-Key')[0]) ->withHeader('Sec-WebSocket-Accept', $this->sign((string)$request->getHeader('Sec-WebSocket-Key')[0]))
, 'X-Powered-By' => 'Ratchet' ->withHeader('X-Powered-By' , 'Ratchet');
]));
} }
/** /**

View File

@ -2,6 +2,7 @@
use GuzzleHttp\Psr7\Uri; use GuzzleHttp\Psr7\Uri;
use React\Promise\Deferred; use React\Promise\Deferred;
use Ratchet\RFC6455\Messaging\Frame; use Ratchet\RFC6455\Messaging\Frame;
use GuzzleHttp\Psr7\HttpFactory;
require __DIR__ . '/../bootstrap.php'; require __DIR__ . '/../bootstrap.php';
@ -48,7 +49,7 @@ function getTestCases() {
$deferred = new Deferred(); $deferred = new Deferred();
$factory->create($testServer, 9001)->then(function (\React\Stream\Stream $stream) use ($deferred) { $factory->create($testServer, 9001)->then(function (\React\Stream\Stream $stream) use ($deferred) {
$cn = new \Ratchet\RFC6455\Handshake\ClientNegotiator(); $cn = new \Ratchet\RFC6455\Handshake\ClientNegotiator(new HttpFactory());
$cnRequest = $cn->generateRequest(new Uri('ws://127.0.0.1:9001/getCaseCount')); $cnRequest = $cn->generateRequest(new Uri('ws://127.0.0.1:9001/getCaseCount'));
$rawResponse = ""; $rawResponse = "";
@ -105,7 +106,7 @@ function runTest($case)
$deferred = new Deferred(); $deferred = new Deferred();
$factory->create($testServer, 9001)->then(function (\React\Stream\Stream $stream) use ($deferred, $casePath, $case) { $factory->create($testServer, 9001)->then(function (\React\Stream\Stream $stream) use ($deferred, $casePath, $case) {
$cn = new \Ratchet\RFC6455\Handshake\ClientNegotiator(); $cn = new \Ratchet\RFC6455\Handshake\ClientNegotiator(new HttpFactory());
$cnRequest = $cn->generateRequest(new Uri('ws://127.0.0.1:9001' . $casePath)); $cnRequest = $cn->generateRequest(new Uri('ws://127.0.0.1:9001' . $casePath));
$rawResponse = ""; $rawResponse = "";
@ -155,7 +156,7 @@ function createReport() {
$factory->create($testServer, 9001)->then(function (\React\Stream\Stream $stream) use ($deferred) { $factory->create($testServer, 9001)->then(function (\React\Stream\Stream $stream) use ($deferred) {
$reportPath = "/updateReports?agent=" . AGENT . "&shutdownOnComplete=true"; $reportPath = "/updateReports?agent=" . AGENT . "&shutdownOnComplete=true";
$cn = new \Ratchet\RFC6455\Handshake\ClientNegotiator(); $cn = new \Ratchet\RFC6455\Handshake\ClientNegotiator(new HttpFactory());
$cnRequest = $cn->generateRequest(new Uri('ws://127.0.0.1:9001' . $reportPath)); $cnRequest = $cn->generateRequest(new Uri('ws://127.0.0.1:9001' . $reportPath));
$rawResponse = ""; $rawResponse = "";

0
tests/ab/run_ab_tests.sh Normal file → Executable file
View File

View File

@ -2,6 +2,7 @@
use Ratchet\RFC6455\Messaging\MessageInterface; use Ratchet\RFC6455\Messaging\MessageInterface;
use Ratchet\RFC6455\Messaging\FrameInterface; use Ratchet\RFC6455\Messaging\FrameInterface;
use Ratchet\RFC6455\Messaging\Frame; use Ratchet\RFC6455\Messaging\Frame;
use GuzzleHttp\Psr7\HttpFactory;
require_once __DIR__ . "/../bootstrap.php"; require_once __DIR__ . "/../bootstrap.php";
@ -11,7 +12,10 @@ $socket = new \React\Socket\Server($loop);
$server = new \React\Http\Server($socket); $server = new \React\Http\Server($socket);
$closeFrameChecker = new \Ratchet\RFC6455\Messaging\CloseFrameChecker; $closeFrameChecker = new \Ratchet\RFC6455\Messaging\CloseFrameChecker;
$negotiator = new \Ratchet\RFC6455\Handshake\ServerNegotiator(new \Ratchet\RFC6455\Handshake\RequestVerifier); $negotiator = new \Ratchet\RFC6455\Handshake\ServerNegotiator(
new \Ratchet\RFC6455\Handshake\RequestVerifier,
new HttpFactory()
);
$uException = new \UnderflowException; $uException = new \UnderflowException;

View File

@ -5,10 +5,12 @@ namespace Ratchet\RFC6455\Test\Unit\Handshake;
use Ratchet\RFC6455\Handshake\RequestVerifier; use Ratchet\RFC6455\Handshake\RequestVerifier;
use Ratchet\RFC6455\Handshake\ServerNegotiator; use Ratchet\RFC6455\Handshake\ServerNegotiator;
use GuzzleHttp\Psr7\HttpFactory;
class ServerNegotiatorTest extends \PHPUnit_Framework_TestCase class ServerNegotiatorTest extends \PHPUnit_Framework_TestCase
{ {
public function testNoUpgradeRequested() { public function testNoUpgradeRequested() {
$negotiator = new ServerNegotiator(new RequestVerifier()); $negotiator = new ServerNegotiator(new RequestVerifier(), new HttpFactory());
$requestText = 'GET / HTTP/1.1 $requestText = 'GET / HTTP/1.1
Host: 127.0.0.1:6789 Host: 127.0.0.1:6789
@ -36,7 +38,7 @@ Accept-Language: en-US,en;q=0.8
} }
public function testNoConnectionUpgradeRequested() { public function testNoConnectionUpgradeRequested() {
$negotiator = new ServerNegotiator(new RequestVerifier()); $negotiator = new ServerNegotiator(new RequestVerifier(), new HttpFactory());
$requestText = 'GET / HTTP/1.1 $requestText = 'GET / HTTP/1.1
Host: 127.0.0.1:6789 Host: 127.0.0.1:6789
@ -62,7 +64,7 @@ Accept-Language: en-US,en;q=0.8
} }
public function testInvalidSecWebsocketKey() { public function testInvalidSecWebsocketKey() {
$negotiator = new ServerNegotiator(new RequestVerifier()); $negotiator = new ServerNegotiator(new RequestVerifier(), new HttpFactory());
$requestText = 'GET / HTTP/1.1 $requestText = 'GET / HTTP/1.1
Host: 127.0.0.1:6789 Host: 127.0.0.1:6789
@ -89,7 +91,7 @@ Accept-Language: en-US,en;q=0.8
} }
public function testInvalidSecWebsocketVersion() { public function testInvalidSecWebsocketVersion() {
$negotiator = new ServerNegotiator(new RequestVerifier()); $negotiator = new ServerNegotiator(new RequestVerifier(), new HttpFactory());
$requestText = 'GET / HTTP/1.1 $requestText = 'GET / HTTP/1.1
Host: 127.0.0.1:6789 Host: 127.0.0.1:6789
@ -119,7 +121,7 @@ Accept-Language: en-US,en;q=0.8
} }
public function testBadSubprotocolResponse() { public function testBadSubprotocolResponse() {
$negotiator = new ServerNegotiator(new RequestVerifier()); $negotiator = new ServerNegotiator(new RequestVerifier(), new HttpFactory());
$negotiator->setStrictSubProtocolCheck(true); $negotiator->setStrictSubProtocolCheck(true);
$negotiator->setSupportedSubProtocols([]); $negotiator->setSupportedSubProtocols([]);
@ -153,7 +155,7 @@ Accept-Language: en-US,en;q=0.8
} }
public function testNonStrictSubprotocolDoesNotIncludeHeaderWhenNoneAgreedOn() { public function testNonStrictSubprotocolDoesNotIncludeHeaderWhenNoneAgreedOn() {
$negotiator = new ServerNegotiator(new RequestVerifier()); $negotiator = new ServerNegotiator(new RequestVerifier(), new HttpFactory());
$negotiator->setStrictSubProtocolCheck(false); $negotiator->setStrictSubProtocolCheck(false);
$negotiator->setSupportedSubProtocols(['someproto']); $negotiator->setSupportedSubProtocols(['someproto']);
@ -187,7 +189,7 @@ Accept-Language: en-US,en;q=0.8
public function testSuggestsAppropriateSubprotocol() public function testSuggestsAppropriateSubprotocol()
{ {
$negotiator = new ServerNegotiator(new RequestVerifier()); $negotiator = new ServerNegotiator(new RequestVerifier(), new HttpFactory());
$negotiator->setStrictSubProtocolCheck(true); $negotiator->setStrictSubProtocolCheck(true);
$negotiator->setSupportedSubProtocols(['someproto']); $negotiator->setSupportedSubProtocols(['someproto']);