Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/WebSocket/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ abstract public function onOpen(callable $callback): self;
*/
abstract public function onMessage(callable $callback): self;

/**
* Is called when an HTTP request is received.
* @param callable $callback
* @return self
*/
abstract public function onRequest(callable $callback): self;

/**
* Is called when a connection is closed.
* @param callable $callback
Expand Down
10 changes: 10 additions & 0 deletions src/WebSocket/Adapter/Swoole.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Utopia\WebSocket\Adapter;

use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\Process;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;
Expand Down Expand Up @@ -125,6 +126,15 @@ public function onClose(callable $callback): self
return $this;
}

public function onRequest(callable $callback): self
{
$this->server->on('request', function (Request $request, Response $response) use ($callback) {
call_user_func($callback, $request, $response);
});

return $this;
}

public function setPackageMaxLength(int $bytes): self
{
$this->config['package_max_length'] = $bytes;
Expand Down
36 changes: 33 additions & 3 deletions src/WebSocket/Adapter/Workerman.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Utopia\WebSocket\Adapter;
use Workerman\Connection\TcpConnection;
use Workerman\Worker;
use Workerman\Protocols\Http\Request;

class Workerman extends Adapter
{
Expand All @@ -16,6 +17,10 @@ class Workerman extends Adapter

private mixed $callbackOnStart;

private mixed $callbackOnMessage;

private mixed $callbackOnRequest;

public function __construct(string $host = '0.0.0.0', int $port = 80)
{
parent::__construct($host, $port);
Expand Down Expand Up @@ -88,9 +93,8 @@ public function onOpen(callable $callback): self

public function onMessage(callable $callback): self
{
$this->server->onMessage = function (TcpConnection $connection, string $data) use ($callback): void {
call_user_func($callback, $connection->id, $data);
};
$this->callbackOnMessage = $callback;
$this->setupMessageHandler();

return $this;
}
Expand All @@ -104,6 +108,32 @@ public function onClose(callable $callback): self
return $this;
}

public function onRequest(callable $callback): self
{
$this->callbackOnRequest = $callback;
$this->setupMessageHandler();

return $this;
}

/**
* Sets up the unified message handler that routes between WebSocket messages and HTTP requests
*/
private function setupMessageHandler(): void
{
$this->server->onMessage = function (TcpConnection $connection, $data) {
if ($data instanceof Request) {
if (is_callable($this->callbackOnRequest)) {
call_user_func($this->callbackOnRequest, $connection, $data);
}
} elseif (is_string($data)) {
if (is_callable($this->callbackOnMessage)) {
call_user_func($this->callbackOnMessage, $connection->id, $data);
}
}
};
}

public function setPackageMaxLength(int $bytes): self
{
return $this;
Expand Down
18 changes: 18 additions & 0 deletions src/WebSocket/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,24 @@ public function onClose(callable $callback): self
return $this;
}

/**
* Is called when an HTTP request is received.
* @param callable $callback
* @return self
*/
public function onRequest(callable $callback): self
{
try {
$this->adapter->onRequest($callback);
} catch (Throwable $error) {
foreach ($this->errorCallbacks as $errorCallback) {
$errorCallback($error, 'onRequest');
}
}

return $this;
}

/**
* Returns all connections.
*
Expand Down
21 changes: 21 additions & 0 deletions tests/servers/Swoole/server.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require_once __DIR__.'/../../../vendor/autoload.php';

use Swoole\Http\Request;
use Swoole\Http\Response;
use Utopia\WebSocket;

$adapter = new WebSocket\Adapter\Swoole();
Expand Down Expand Up @@ -42,4 +43,24 @@
break;
}
})
->onRequest(function (Request $request, Response $response) use ($server) {
echo 'HTTP request received: ', $request->server['request_uri'], PHP_EOL;

if ($request->server['request_uri'] === '/health') {
$response->header('Content-Type', 'application/json');
$response->status(200);
$response->end(json_encode(['status' => 'ok', 'message' => 'WebSocket server is running']));
} elseif ($request->server['request_uri'] === '/info') {
$response->header('Content-Type', 'application/json');
$response->status(200);
$response->end(json_encode([
'server' => 'Swoole WebSocket',
'connections' => count($server->getConnections()),
'timestamp' => time()
]));
} else {
$response->status(404);
$response->end('Not Found');
}
})
->start();
29 changes: 29 additions & 0 deletions tests/servers/Workerman/server.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
require_once __DIR__.'/../../../vendor/autoload.php';

use Utopia\WebSocket;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;

$adapter = new WebSocket\Adapter\Workerman();
$adapter->setWorkerNumber(1); // Important for tests
Expand Down Expand Up @@ -41,4 +43,31 @@
break;
}
})
->onRequest(function (TcpConnection $connection, Request $request) use ($server) {
$path = $request->path();
if (!is_string($path)) {
throw new \Exception('Invalid path ' . $path . ' for request: ' . json_encode($request, JSON_PRETTY_PRINT));
}
echo 'HTTP request received: ', $path, PHP_EOL;

if ($path === '/health') {
$connection->send('HTTP/1.1 200 OK' . "\r\n" .
'Content-Type: application/json' . "\r\n" .
'Connection: close' . "\r\n\r\n" .
json_encode(['status' => 'ok', 'message' => 'WebSocket server is running']));
} elseif ($path === '/info') {
$connection->send('HTTP/1.1 200 OK' . "\r\n" .
'Content-Type: application/json' . "\r\n" .
'Connection: close' . "\r\n\r\n" .
json_encode([
'server' => 'Workerman WebSocket',
'connections' => count($server->getConnections()),
'timestamp' => time()
]));
} else {
$connection->send('HTTP/1.1 404 Not Found' . "\r\n" .
'Connection: close' . "\r\n\r\n" .
'Not Found');
}
})
->start();