diff --git a/src/main/php/websocket/protocol/Connection.class.php b/src/main/php/websocket/protocol/Connection.class.php index ba9f8a1..880be46 100755 --- a/src/main/php/websocket/protocol/Connection.class.php +++ b/src/main/php/websocket/protocol/Connection.class.php @@ -12,7 +12,7 @@ class Connection { const MAXLENGTH= 0x8000000; - private $socket, $id, $listener, $path, $headers; + private $socket, $id, $listener, $path, $params, $headers; /** * Creates a new connection @@ -27,7 +27,16 @@ public function __construct($socket, $id, $listener, $path= '/', $headers= []) { $this->socket= $socket; $this->id= $id; $this->listener= $listener; - $this->path= $path; + + $p= strpos($path, '?'); + if (false === $p) { + $this->path= $path; + $this->params= []; + } else { + $this->path= substr($path, 0, $p); + parse_str(substr($path, $p + 1), $this->params); + } + $this->headers= $headers; } @@ -40,9 +49,23 @@ public function listener() { return $this->listener; } /** @return string */ public function path() { return $this->path; } + /** @return [:var] */ + public function params() { return $this->params; } + /** @return [:var] */ public function headers() { return $this->headers; } + /** + * Returns a named parameter, or NULL if it does not exist. + * + * @param string $name + * @param var $default + * @return var + */ + public function param($name, $default= null) { + return $this->params[$name] ?? $default; + } + /** * Opens connection * diff --git a/src/test/php/websocket/unittest/ConnectionTest.class.php b/src/test/php/websocket/unittest/ConnectionTest.class.php index 1601a72..eb2e238 100755 --- a/src/test/php/websocket/unittest/ConnectionTest.class.php +++ b/src/test/php/websocket/unittest/ConnectionTest.class.php @@ -25,7 +25,7 @@ private function listener($callable= null) { * @return [] */ private function receive($channel) { - $conn= new Connection($channel->connect(), self::ID, $this->listener(), []); + $conn= new Connection($channel->connect(), self::ID, $this->listener()); $r= []; foreach ($conn->receive() as $type => $message) { $r[]= [$type => $message]; @@ -54,6 +54,35 @@ public function path($value) { Assert::equals($value, (new Connection(new Channel(), self::ID, $this->listener(), $value))->path()); } + #[Test] + public function path_does_not_contain_params() { + Assert::equals('/', (new Connection(new Channel(), self::ID, $this->listener(), '/?for=test'))->path()); + } + + #[Test, Values(['/?for=test', '/ws?for=test', '/feed/6100?for=test'])] + public function params($value) { + $conn= new Connection(new Channel(), self::ID, $this->listener(), $value); + + Assert::equals('test', $conn->param('for')); + Assert::equals(['for' => 'test'], $conn->params()); + } + + #[Test] + public function non_existant_param() { + $conn= new Connection(new Channel(), self::ID, $this->listener(), '?for=test'); + + Assert::null($conn->param('non-existant')); + Assert::equals('default', $conn->param('non-existant', 'default')); + } + + #[Test] + public function array_param() { + $conn= new Connection(new Channel(), self::ID, $this->listener(), '?for[]=a&for[]=b'); + + Assert::equals(['a', 'b'], $conn->param('for')); + Assert::equals(['for' => ['a', 'b']], $conn->params()); + } + #[Test, Values([[[]], [['User-Agent' => 'Test', 'Accept' => '*/*']]])] public function headers($value) { Assert::equals($value, (new Connection(new Channel(), self::ID, $this->listener(), '/', $value))->headers()); diff --git a/src/test/php/websocket/unittest/MessagesTest.class.php b/src/test/php/websocket/unittest/MessagesTest.class.php index 51301e3..41b71ed 100755 --- a/src/test/php/websocket/unittest/MessagesTest.class.php +++ b/src/test/php/websocket/unittest/MessagesTest.class.php @@ -33,7 +33,7 @@ private function fixture($channel, $listener= null) { // Simulate handshake $channel->connect(); - $listeners->connections[self::ID]= new Connection($channel, self::ID, $listeners->listener('/ws'), []); + $listeners->connections[self::ID]= new Connection($channel, self::ID, $listeners->listener('/ws')); return new Messages($listeners, $this->log); }