From ffc568461bdd7ef4292270c68a6f52d6e66c38e4 Mon Sep 17 00:00:00 2001 From: Michiel de Jong Date: Fri, 7 Oct 2022 12:12:03 +0200 Subject: [PATCH 01/10] draft --- server/server.php | 109 ++++++++-------------------------------------- 1 file changed, 18 insertions(+), 91 deletions(-) diff --git a/server/server.php b/server/server.php index 2c4fe72..de56509 100644 --- a/server/server.php +++ b/server/server.php @@ -1,105 +1,32 @@ clients = new \SplObjectStorage; - $this->subscriptions = array(); - $this->subprotocols = array("solid-0.1"); - } - - public function getSubProtocols() { - return $this->subprotocols; - } - public function onOpen(ConnectionInterface $conn) { - - // Store the new connection in $this->clients - $this->clients->attach($conn); - echo "New connection! ({$conn->resourceId})\n"; - } - - public function onMessage(ConnectionInterface $from, $message) { - $messageInfo = explode(" ", $message); - $command = $messageInfo[0]; - $body = trim($messageInfo[1]); - - switch ($command) { - case "auth": - case "dpop": - // FIXME: we should check that the client is allowed to listen - break; - case "sub": - echo "Client sub for $body\n"; - if (!isset($this->subscriptions[$body])) { - $this->subscriptions[$body] = array(); - } - $this->subscriptions[$body][] = $from; - $from->send("ack $body"); - break; - case "pub": - echo "Client pub for $body\n"; - if (isset($this->subscriptions[$body])) { - foreach ( $this->subscriptions[$body] as $client ) { - $client->send("pub $body"); - } - } - break; - default: - echo "Client $from->resourceId said $message\n"; - foreach ( $this->clients as $client ) { - - if ( $from->resourceId == $client->resourceId ) { - continue; - } - - $client->send("Client $from->resourceId said $message\n"); - } - break; - } - } - - public function onClose(ConnectionInterface $conn) { - echo "Client $conn->resourceId left\n"; - foreach ($this->subscriptions as $url => $subscribers) { - foreach ($subscribers as $key => $client) { - if ($client->resourceId == $conn->resourceId) { - echo "Removing subscription for $url\n"; - unset($subscribers[$url][$key]); - } - } - } - } - - public function onError(ConnectionInterface $conn, \Exception $e) { - foreach ($this->subscriptions as $url => $subscribers) { - foreach ($subscribers as $key => $client) { - if ($client->resourceId == $conn->resourceId) { - echo "Removing subscription for $url\n"; - unset($subscribers[$url][$key]); - } - } - } - } -} - -$server = IoServer::factory( +$serverWps = IoServer::factory( new HttpServer( new WsServer( - new Socket() + new SocketWps() ) ), - SOCKET_PORT + SOCKET_PORT_WPS +); + +$serverWh2Ws = IoServer::factory( + new HttpServer( + new WsServer( + new SocketWps() + ) + ), +SOCKET_PORT_WH2WS ); -$server->run(); +$serverWps->run(); +$serverWh2Ws->run(); From d54a4e26f48c7ac4a42789ad98a8fc3337a5fa8c Mon Sep 17 00:00:00 2001 From: Michiel de Jong Date: Fri, 7 Oct 2022 12:20:42 +0200 Subject: [PATCH 02/10] test.sh --- server/server.php | 4 ++-- test.sh | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 test.sh diff --git a/server/server.php b/server/server.php index de56509..44af48f 100644 --- a/server/server.php +++ b/server/server.php @@ -7,8 +7,8 @@ use Ratchet\Http\HttpServer; use Ratchet\WebSocket\WsServer; require dirname(dirname( __FILE__ )) . '/vendor/autoload.php'; -require 'SocketWps'; -require 'SocketWh2Ws'; +require 'SocketWps.php'; +require 'SocketWh2Ws.php'; $serverWps = IoServer::factory( new HttpServer( diff --git a/test.sh b/test.sh new file mode 100644 index 0000000..70d8903 --- /dev/null +++ b/test.sh @@ -0,0 +1,8 @@ +docker network create testnet +docker run -d -v `pwd`:/app --network=testnet --name=pubsub --rm pubsub +# docker exec -it pubsub php /install/composer.phar install --no-dev --prefer-dist +# docker exec -it pubsub /bin/bash +# docker exec -it pubsub php server/server.php +docker run -d --network=testnet --name=tester --rm solidtestsuite/solid-crud-tests:v7.0.5 sleep 30000 +docker exec -it tester npm install -g wscat +docker exec -it tester /bin/bash From eafce01b5c7f71ca148b62f86e00b8c5f334d981 Mon Sep 17 00:00:00 2001 From: Michiel de Jong Date: Fri, 7 Oct 2022 12:58:14 +0200 Subject: [PATCH 03/10] Add second server to run in separate process --- Dockerfile | 2 +- server/{server.php => serverWh2Ws.php} | 5 +- server/serverWps.php | 109 +++++++++++++++++++++++++ test.sh | 10 +++ 4 files changed, 124 insertions(+), 2 deletions(-) rename server/{server.php => serverWh2Ws.php} (91%) create mode 100644 server/serverWps.php create mode 100644 test.sh diff --git a/Dockerfile b/Dockerfile index 48a937e..87549d0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,4 +12,4 @@ ADD . /app WORKDIR /app RUN php /install/composer.phar install --no-dev --prefer-dist EXPOSE 8080 -CMD php server/server.php \ No newline at end of file +CMD php server/serverWps.php diff --git a/server/server.php b/server/serverWh2Ws.php similarity index 91% rename from server/server.php rename to server/serverWh2Ws.php index 2c4fe72..96a9981 100644 --- a/server/server.php +++ b/server/serverWh2Ws.php @@ -1,6 +1,9 @@ clients = new \SplObjectStorage; + $this->subscriptions = array(); + $this->subprotocols = array("solid-0.1"); + } + + public function getSubProtocols() { + return $this->subprotocols; + } + public function onOpen(ConnectionInterface $conn) { + + // Store the new connection in $this->clients + $this->clients->attach($conn); + echo "New connection! ({$conn->resourceId})\n"; + } + + public function onMessage(ConnectionInterface $from, $message) { + $messageInfo = explode(" ", $message); + $command = $messageInfo[0]; + $body = trim($messageInfo[1]); + + switch ($command) { + case "auth": + case "dpop": + // FIXME: we should check that the client is allowed to listen + break; + case "sub": + echo "Client sub for $body\n"; + if (!isset($this->subscriptions[$body])) { + $this->subscriptions[$body] = array(); + } + $this->subscriptions[$body][] = $from; + $from->send("ack $body"); + break; + case "pub": + echo "Client pub for $body\n"; + if (isset($this->subscriptions[$body])) { + foreach ( $this->subscriptions[$body] as $client ) { + $client->send("pub $body"); + } + } + break; + default: + echo "Client $from->resourceId said $message\n"; + foreach ( $this->clients as $client ) { + + if ( $from->resourceId == $client->resourceId ) { + continue; + } + + $client->send("Client $from->resourceId said $message\n"); + } + break; + } + } + + public function onClose(ConnectionInterface $conn) { + echo "Client $conn->resourceId left\n"; + foreach ($this->subscriptions as $url => $subscribers) { + foreach ($subscribers as $key => $client) { + if ($client->resourceId == $conn->resourceId) { + echo "Removing subscription for $url\n"; + unset($subscribers[$url][$key]); + } + } + } + } + + public function onError(ConnectionInterface $conn, \Exception $e) { + foreach ($this->subscriptions as $url => $subscribers) { + foreach ($subscribers as $key => $client) { + if ($client->resourceId == $conn->resourceId) { + echo "Removing subscription for $url\n"; + unset($subscribers[$url][$key]); + } + } + } + } +} + +$server = IoServer::factory( + new HttpServer( + new WsServer( + new Socket() + ) + ), + SOCKET_PORT +); + +$server->run(); diff --git a/test.sh b/test.sh new file mode 100644 index 0000000..f37000e --- /dev/null +++ b/test.sh @@ -0,0 +1,10 @@ +docker network create testnet +docker run -d -v `pwd`:/app --network=testnet --name=pubsub --rm pubsub +# docker exec -it pubsub php /install/composer.phar install --no-dev --prefer-dist +# docker exec -it pubsub /bin/bash +# docker exec -it pubsub php server/server.php +docker run -d --network=testnet --name=tester --rm solidtestsuite/solid-crud-tests:v7.0.5 sleep 30000 +docker exec -it tester npm install -g wscat +docker exec -it tester /bin/bash +# wscat -c ws://pubsub:8080 -s "solid-0.1" +# wscat -c ws://pubsub:8081 From f66f12e321dc440b8f07df029e4f6132f0a2e16c Mon Sep 17 00:00:00 2001 From: Michiel de Jong Date: Fri, 7 Oct 2022 13:36:33 +0200 Subject: [PATCH 04/10] Try with reactphp.org --- composer.json | 1 + composer.lock | 604 ++++++++++++++++++++++++++++++++++++----- server/serverReact.php | 17 ++ server/serverWh2Ws.php | 6 + test.sh | 4 +- 5 files changed, 567 insertions(+), 65 deletions(-) create mode 100644 server/serverReact.php diff --git a/composer.json b/composer.json index 5a0de0c..436b174 100644 --- a/composer.json +++ b/composer.json @@ -19,6 +19,7 @@ "require": { "php": "~7.1", "cboden/ratchet": "0.4.3", + "react/http": "^1.8", "textalk/websocket": "1.4.1" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 5d26651..a979abd 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6b72a32efaa6ea10a75035fe3f8a64ab", + "content-hash": "9394354430d0cff4e55f3eaaeca2459b", "packages": [ { "name": "cboden/ratchet", @@ -104,8 +104,68 @@ "event-dispatcher", "event-emitter" ], + "support": { + "issues": "https://github.com/igorw/evenement/issues", + "source": "https://github.com/igorw/evenement/tree/master" + }, "time": "2017-07-23T21:35:13+00:00" }, + { + "name": "fig/http-message-util", + "version": "1.1.5", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message-util.git", + "reference": "9d94dc0154230ac39e5bf89398b324a86f63f765" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message-util/zipball/9d94dc0154230ac39e5bf89398b324a86f63f765", + "reference": "9d94dc0154230ac39e5bf89398b324a86f63f765", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0 || ^8.0" + }, + "suggest": { + "psr/http-message": "The package containing the PSR-7 interfaces" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Fig\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Utility classes and constants for use with PSR-7 (psr/http-message)", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "issues": "https://github.com/php-fig/http-message-util/issues", + "source": "https://github.com/php-fig/http-message-util/tree/1.1.5" + }, + "time": "2020-11-24T22:02:12+00:00" + }, { "name": "guzzlehttp/psr7", "version": "1.7.0", @@ -225,6 +285,9 @@ "request", "response" ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, "time": "2016-08-06T14:39:51+00:00" }, { @@ -368,16 +431,16 @@ }, { "name": "react/cache", - "version": "v1.1.0", + "version": "v1.1.1", "source": { "type": "git", "url": "https://github.com/reactphp/cache.git", - "reference": "44a568925556b0bd8cacc7b49fb0f1cf0d706a0c" + "reference": "4bf736a2cccec7298bdf745db77585966fc2ca7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/cache/zipball/44a568925556b0bd8cacc7b49fb0f1cf0d706a0c", - "reference": "44a568925556b0bd8cacc7b49fb0f1cf0d706a0c", + "url": "https://api.github.com/repos/reactphp/cache/zipball/4bf736a2cccec7298bdf745db77585966fc2ca7e", + "reference": "4bf736a2cccec7298bdf745db77585966fc2ca7e", "shasum": "" }, "require": { @@ -426,32 +489,46 @@ "promise", "reactphp" ], - "time": "2020-09-18T12:12:35+00:00" + "support": { + "issues": "https://github.com/reactphp/cache/issues", + "source": "https://github.com/reactphp/cache/tree/v1.1.1" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2021-02-02T06:47:52+00:00" }, { "name": "react/dns", - "version": "v1.4.0", + "version": "v1.10.0", "source": { "type": "git", "url": "https://github.com/reactphp/dns.git", - "reference": "665260757171e2ab17485b44e7ffffa7acb6ca1f" + "reference": "a5427e7dfa47713e438016905605819d101f238c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/dns/zipball/665260757171e2ab17485b44e7ffffa7acb6ca1f", - "reference": "665260757171e2ab17485b44e7ffffa7acb6ca1f", + "url": "https://api.github.com/repos/reactphp/dns/zipball/a5427e7dfa47713e438016905605819d101f238c", + "reference": "a5427e7dfa47713e438016905605819d101f238c", "shasum": "" }, "require": { "php": ">=5.3.0", "react/cache": "^1.0 || ^0.6 || ^0.5", - "react/event-loop": "^1.0 || ^0.5", + "react/event-loop": "^1.2", "react/promise": "^3.0 || ^2.7 || ^1.2.1", - "react/promise-timer": "^1.2" + "react/promise-timer": "^1.9" }, "require-dev": { - "clue/block-react": "^1.2", - "phpunit/phpunit": "^9.3 || ^4.8.35" + "phpunit/phpunit": "^9.3 || ^4.8.35", + "react/async": "^4 || ^3 || ^2" }, "type": "library", "autoload": { @@ -492,27 +569,41 @@ "dns-resolver", "reactphp" ], - "time": "2020-09-18T12:12:55+00:00" + "support": { + "issues": "https://github.com/reactphp/dns/issues", + "source": "https://github.com/reactphp/dns/tree/v1.10.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-09-08T12:22:46+00:00" }, { "name": "react/event-loop", - "version": "v1.1.1", + "version": "v1.3.0", "source": { "type": "git", "url": "https://github.com/reactphp/event-loop.git", - "reference": "6d24de090cd59cfc830263cfba965be77b563c13" + "reference": "187fb56f46d424afb6ec4ad089269c72eec2e137" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/event-loop/zipball/6d24de090cd59cfc830263cfba965be77b563c13", - "reference": "6d24de090cd59cfc830263cfba965be77b563c13", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/187fb56f46d424afb6ec4ad089269c72eec2e137", + "reference": "187fb56f46d424afb6ec4ad089269c72eec2e137", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "^7.0 || ^6.4 || ^5.7 || ^4.8.35" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" }, "suggest": { "ext-event": "~1.0 for ExtEventLoop", @@ -529,89 +620,334 @@ "license": [ "MIT" ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", "keywords": [ "asynchronous", "event-loop" ], - "time": "2020-01-01T18:39:52+00:00" + "support": { + "issues": "https://github.com/reactphp/event-loop/issues", + "source": "https://github.com/reactphp/event-loop/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-03-17T11:10:22+00:00" + }, + { + "name": "react/http", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/http.git", + "reference": "aa7512ee17258c88466de30f9cb44ec5f9df3ff3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/http/zipball/aa7512ee17258c88466de30f9cb44ec5f9df3ff3", + "reference": "aa7512ee17258c88466de30f9cb44ec5f9df3ff3", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "fig/http-message-util": "^1.1", + "php": ">=5.3.0", + "psr/http-message": "^1.0", + "react/event-loop": "^1.2", + "react/promise": "^3 || ^2.3 || ^1.2.1", + "react/promise-stream": "^1.4", + "react/socket": "^1.12", + "react/stream": "^1.2", + "ringcentral/psr7": "^1.2" + }, + "require-dev": { + "clue/http-proxy-react": "^1.8", + "clue/reactphp-ssh-proxy": "^1.4", + "clue/socks-react": "^1.4", + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", + "react/async": "^4 || ^3 || ^2", + "react/promise-timer": "^1.9" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Http\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven, streaming HTTP client and server implementation for ReactPHP", + "keywords": [ + "async", + "client", + "event-driven", + "http", + "http client", + "http server", + "https", + "psr-7", + "reactphp", + "server", + "streaming" + ], + "support": { + "issues": "https://github.com/reactphp/http/issues", + "source": "https://github.com/reactphp/http/tree/v1.8.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-09-29T12:55:52+00:00" }, { "name": "react/promise", - "version": "v2.8.0", + "version": "v2.9.0", "source": { "type": "git", "url": "https://github.com/reactphp/promise.git", - "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4" + "reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/f3cff96a19736714524ca0dd1d4130de73dbbbc4", - "reference": "f3cff96a19736714524ca0dd1d4130de73dbbbc4", + "url": "https://api.github.com/repos/reactphp/promise/zipball/234f8fd1023c9158e2314fa9d7d0e6a83db42910", + "reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910", "shasum": "" }, "require": { "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "^7.0 || ^6.5 || ^5.7 || ^4.8.36" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36" }, "type": "library", "autoload": { + "files": [ + "src/functions_include.php" + ], "psr-4": { "React\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "keywords": [ + "promise", + "promises" + ], + "support": { + "issues": "https://github.com/reactphp/promise/issues", + "source": "https://github.com/reactphp/promise/tree/v2.9.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-02-11T10:27:51+00:00" + }, + { + "name": "react/promise-stream", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise-stream.git", + "reference": "e6d2805e09ad50c4896f65f5e8705fe4ee7731a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise-stream/zipball/e6d2805e09ad50c4896f65f5e8705fe4ee7731a3", + "reference": "e6d2805e09ad50c4896f65f5e8705fe4ee7731a3", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "react/promise": "^3 || ^2.1 || ^1.2", + "react/stream": "^1.0 || ^0.7 || ^0.6 || ^0.5 || ^0.4.6" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { "files": [ "src/functions_include.php" - ] + ], + "psr-4": { + "React\\Promise\\Stream\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, { "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com" + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" } ], - "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "description": "The missing link between Promise-land and Stream-land for ReactPHP", + "homepage": "https://github.com/reactphp/promise-stream", "keywords": [ + "Buffer", + "async", "promise", - "promises" + "reactphp", + "stream", + "unwrap" + ], + "support": { + "issues": "https://github.com/reactphp/promise-stream/issues", + "source": "https://github.com/reactphp/promise-stream/tree/v1.5.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } ], - "time": "2020-05-12T15:16:56+00:00" + "time": "2022-09-09T11:42:18+00:00" }, { "name": "react/promise-timer", - "version": "v1.6.0", + "version": "v1.9.0", "source": { "type": "git", "url": "https://github.com/reactphp/promise-timer.git", - "reference": "daee9baf6ef30c43ea4c86399f828bb5f558f6e6" + "reference": "aa7a73c74b8d8c0f622f5982ff7b0351bc29e495" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise-timer/zipball/daee9baf6ef30c43ea4c86399f828bb5f558f6e6", - "reference": "daee9baf6ef30c43ea4c86399f828bb5f558f6e6", + "url": "https://api.github.com/repos/reactphp/promise-timer/zipball/aa7a73c74b8d8c0f622f5982ff7b0351bc29e495", + "reference": "aa7a73c74b8d8c0f622f5982ff7b0351bc29e495", "shasum": "" }, "require": { "php": ">=5.3", - "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3.5", + "react/event-loop": "^1.2", "react/promise": "^3.0 || ^2.7.0 || ^1.2.1" }, "require-dev": { - "phpunit/phpunit": "^9.0 || ^5.7 || ^4.8.35" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" }, "type": "library", "autoload": { - "psr-4": { - "React\\Promise\\Timer\\": "src/" - }, "files": [ "src/functions_include.php" - ] + ], + "psr-4": { + "React\\Promise\\Timer\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -620,7 +956,23 @@ "authors": [ { "name": "Christian Lück", - "email": "christian@lueck.tv" + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" } ], "description": "A trivial implementation of timeouts for Promises, built on top of ReactPHP.", @@ -633,35 +985,49 @@ "timeout", "timer" ], - "time": "2020-07-10T12:18:06+00:00" + "support": { + "issues": "https://github.com/reactphp/promise-timer/issues", + "source": "https://github.com/reactphp/promise-timer/tree/v1.9.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-06-13T13:41:03+00:00" }, { "name": "react/socket", - "version": "v1.6.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/reactphp/socket.git", - "reference": "e2b96b23a13ca9b41ab343268dbce3f8ef4d524a" + "reference": "81e1b4d7f5450ebd8d2e9a95bb008bb15ca95a7b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/e2b96b23a13ca9b41ab343268dbce3f8ef4d524a", - "reference": "e2b96b23a13ca9b41ab343268dbce3f8ef4d524a", + "url": "https://api.github.com/repos/reactphp/socket/zipball/81e1b4d7f5450ebd8d2e9a95bb008bb15ca95a7b", + "reference": "81e1b4d7f5450ebd8d2e9a95bb008bb15ca95a7b", "shasum": "" }, "require": { "evenement/evenement": "^3.0 || ^2.0 || ^1.0", "php": ">=5.3.0", - "react/dns": "^1.1", - "react/event-loop": "^1.0 || ^0.5", - "react/promise": "^2.6.0 || ^1.2.1", - "react/promise-timer": "^1.4.0", - "react/stream": "^1.1" + "react/dns": "^1.8", + "react/event-loop": "^1.2", + "react/promise": "^3 || ^2.6 || ^1.2.1", + "react/promise-timer": "^1.9", + "react/stream": "^1.2" }, "require-dev": { - "clue/block-react": "^1.2", "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", - "react/promise-stream": "^1.2" + "react/async": "^4 || ^3 || ^2", + "react/promise-stream": "^1.4" }, "type": "library", "autoload": { @@ -703,30 +1069,44 @@ "reactphp", "stream" ], - "time": "2020-08-28T12:49:05+00:00" + "support": { + "issues": "https://github.com/reactphp/socket/issues", + "source": "https://github.com/reactphp/socket/tree/v1.12.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-08-25T12:32:25+00:00" }, { "name": "react/stream", - "version": "v1.1.1", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/reactphp/stream.git", - "reference": "7c02b510ee3f582c810aeccd3a197b9c2f52ff1a" + "reference": "7a423506ee1903e89f1e08ec5f0ed430ff784ae9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/stream/zipball/7c02b510ee3f582c810aeccd3a197b9c2f52ff1a", - "reference": "7c02b510ee3f582c810aeccd3a197b9c2f52ff1a", + "url": "https://api.github.com/repos/reactphp/stream/zipball/7a423506ee1903e89f1e08ec5f0ed430ff784ae9", + "reference": "7a423506ee1903e89f1e08ec5f0ed430ff784ae9", "shasum": "" }, "require": { "evenement/evenement": "^3.0 || ^2.0 || ^1.0", "php": ">=5.3.8", - "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3.5" + "react/event-loop": "^1.2" }, "require-dev": { "clue/stream-filter": "~1.2", - "phpunit/phpunit": "^7.0 || ^6.4 || ^5.7 || ^4.8.35" + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" }, "type": "library", "autoload": { @@ -738,6 +1118,28 @@ "license": [ "MIT" ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", "keywords": [ "event-driven", @@ -749,7 +1151,82 @@ "stream", "writable" ], - "time": "2020-05-04T10:17:57+00:00" + "support": { + "issues": "https://github.com/reactphp/stream/issues", + "source": "https://github.com/reactphp/stream/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2021-07-11T12:37:55+00:00" + }, + { + "name": "ringcentral/psr7", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/ringcentral/psr7.git", + "reference": "360faaec4b563958b673fb52bbe94e37f14bc686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ringcentral/psr7/zipball/360faaec4b563958b673fb52bbe94e37f14bc686", + "reference": "360faaec4b563958b673fb52bbe94e37f14bc686", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "RingCentral\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "PSR-7 message implementation", + "keywords": [ + "http", + "message", + "stream", + "uri" + ], + "support": { + "source": "https://github.com/ringcentral/psr7/tree/master" + }, + "time": "2018-05-29T20:21:04+00:00" }, { "name": "symfony/deprecation-contracts", @@ -2900,5 +3377,6 @@ "php": "7.3.11", "ext-dom": "0.0.0", "ext-mbstring": "0.0.0" - } + }, + "plugin-api-version": "2.3.0" } diff --git a/server/serverReact.php b/server/serverReact.php new file mode 100644 index 0000000..d5900c1 --- /dev/null +++ b/server/serverReact.php @@ -0,0 +1,17 @@ +listen($socket); + +echo "Server running at http://127.0.0.1:8080" . PHP_EOL; \ No newline at end of file diff --git a/server/serverWh2Ws.php b/server/serverWh2Ws.php index 9411f5b..83b7784 100644 --- a/server/serverWh2Ws.php +++ b/server/serverWh2Ws.php @@ -11,6 +11,8 @@ use Ratchet\MessageComponentInterface; use Ratchet\WebSocket\WsServerInterface; use Ratchet\ConnectionInterface; +use React\Socket\Server as Reactor; + require dirname(dirname( __FILE__ )) . '/vendor/autoload.php'; class Socket implements MessageComponentInterface, WsServerInterface { @@ -102,4 +104,8 @@ public function onError(ConnectionInterface $conn, \Exception $e) { SOCKET_PORT ); +$socket = new Reactor($server->loop); +$socket->listen(8082, '0.0.0.0'); //Port 2 +$socket->on('connection', [$server, 'handleConnect']); + $server->run(); diff --git a/test.sh b/test.sh index f37000e..3e5be31 100644 --- a/test.sh +++ b/test.sh @@ -2,9 +2,9 @@ docker network create testnet docker run -d -v `pwd`:/app --network=testnet --name=pubsub --rm pubsub # docker exec -it pubsub php /install/composer.phar install --no-dev --prefer-dist # docker exec -it pubsub /bin/bash -# docker exec -it pubsub php server/server.php +docker exec -it pubsub php server/serverWh2Ws.php docker run -d --network=testnet --name=tester --rm solidtestsuite/solid-crud-tests:v7.0.5 sleep 30000 -docker exec -it tester npm install -g wscat +docker exec -it tester npm install -g wscat docker exec -it tester /bin/bash # wscat -c ws://pubsub:8080 -s "solid-0.1" # wscat -c ws://pubsub:8081 From b9fc356dee9f4d72a14ad693504f498cf22c5e70 Mon Sep 17 00:00:00 2001 From: Michiel de Jong Date: Fri, 7 Oct 2022 13:38:37 +0200 Subject: [PATCH 05/10] Add zip to make composer faster --- .gitignore | 3 ++- Dockerfile | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 7eeae68..970dbba 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ # Directories to ignore +/bin /build /vendor # Files to ignore /.env -/phpunit.xml \ No newline at end of file +/phpunit.xml diff --git a/Dockerfile b/Dockerfile index 87549d0..19abfd2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,8 @@ FROM php:7.2 RUN apt-get update && \ apt-get install -y \ git \ - zlib1g-dev + zlib1g-dev \ + zip WORKDIR /tls WORKDIR /install RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" From fd2f3884d1a36d48606718b97085701adfa72b1d Mon Sep 17 00:00:00 2001 From: Michiel de Jong Date: Fri, 7 Oct 2022 13:50:03 +0200 Subject: [PATCH 06/10] Run React http server besides Ratchet ws server --- server/serverReact.php | 18 +++++++++--------- server/serverWh2Ws.php | 11 ++++++----- test.sh | 1 + 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/server/serverReact.php b/server/serverReact.php index d5900c1..2be4279 100644 --- a/server/serverReact.php +++ b/server/serverReact.php @@ -3,15 +3,15 @@ // $ composer require react/http react/socket # install example using Composer // $ php example.php # run example on command line, requires no additional web server -require __DIR__ . '/vendor/autoload.php'; +require __DIR__ . '/../vendor/autoload.php'; -$http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { +function runWebHookServer() { + $http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { return React\Http\Message\Response::plaintext( - "Hello World!\n" + "Hello World!\n" ); -}); - -$socket = new React\Socket\SocketServer('127.0.0.1:8080'); -$http->listen($socket); - -echo "Server running at http://127.0.0.1:8080" . PHP_EOL; \ No newline at end of file + }); + $host = '0.0.0.0:8080'; + $socket = new React\Socket\SocketServer($host); + $http->listen($socket); +} \ No newline at end of file diff --git a/server/serverWh2Ws.php b/server/serverWh2Ws.php index 83b7784..5b79ea8 100644 --- a/server/serverWh2Ws.php +++ b/server/serverWh2Ws.php @@ -11,10 +11,11 @@ use Ratchet\MessageComponentInterface; use Ratchet\WebSocket\WsServerInterface; use Ratchet\ConnectionInterface; -use React\Socket\Server as Reactor; require dirname(dirname( __FILE__ )) . '/vendor/autoload.php'; +require './server/serverReact.php'; + class Socket implements MessageComponentInterface, WsServerInterface { public function __construct() { $this->clients = new \SplObjectStorage; @@ -104,8 +105,8 @@ public function onError(ConnectionInterface $conn, \Exception $e) { SOCKET_PORT ); -$socket = new Reactor($server->loop); -$socket->listen(8082, '0.0.0.0'); //Port 2 -$socket->on('connection', [$server, 'handleConnect']); - +echo "run 1"; +runWebHookServer(); +echo "run 2"; $server->run(); +echo "run 3"; diff --git a/test.sh b/test.sh index 3e5be31..950baae 100644 --- a/test.sh +++ b/test.sh @@ -1,5 +1,6 @@ docker network create testnet docker run -d -v `pwd`:/app --network=testnet --name=pubsub --rm pubsub + # docker exec -it pubsub php /install/composer.phar install --no-dev --prefer-dist # docker exec -it pubsub /bin/bash docker exec -it pubsub php server/serverWh2Ws.php From 7a61436ebf3967a5df564c18baa6c50981c0f127 Mon Sep 17 00:00:00 2001 From: Michiel de Jong Date: Fri, 7 Oct 2022 14:33:28 +0200 Subject: [PATCH 07/10] can send foo to bar --- server/serverReact.php | 17 ----------- server/serverWh2Ws.php | 61 ++++++++++++++-------------------------- server/webhookServer.php | 24 ++++++++++++++++ test.sh | 3 ++ 4 files changed, 48 insertions(+), 57 deletions(-) delete mode 100644 server/serverReact.php create mode 100644 server/webhookServer.php diff --git a/server/serverReact.php b/server/serverReact.php deleted file mode 100644 index 2be4279..0000000 --- a/server/serverReact.php +++ /dev/null @@ -1,17 +0,0 @@ -listen($socket); -} \ No newline at end of file diff --git a/server/serverWh2Ws.php b/server/serverWh2Ws.php index 5b79ea8..7a3bbd9 100644 --- a/server/serverWh2Ws.php +++ b/server/serverWh2Ws.php @@ -14,7 +14,7 @@ require dirname(dirname( __FILE__ )) . '/vendor/autoload.php'; -require './server/serverReact.php'; +require './server/webhookServer.php'; class Socket implements MessageComponentInterface, WsServerInterface { public function __construct() { @@ -30,48 +30,27 @@ public function onOpen(ConnectionInterface $conn) { // Store the new connection in $this->clients $this->clients->attach($conn); echo "New connection! ({$conn->resourceId})\n"; + $body = "bar"; + echo "Client sub for $body\n"; + if (!isset($this->subscriptions[$body])) { + $this->subscriptions[$body] = array(); + } + $this->subscriptions[$body][] = $conn; + $conn->send("ack $body"); } - public function onMessage(ConnectionInterface $from, $message) { - $messageInfo = explode(" ", $message); - $command = $messageInfo[0]; - $body = trim($messageInfo[1]); - - switch ($command) { - case "auth": - case "dpop": - // FIXME: we should check that the client is allowed to listen - break; - case "sub": - echo "Client sub for $body\n"; - if (!isset($this->subscriptions[$body])) { - $this->subscriptions[$body] = array(); - } - $this->subscriptions[$body][] = $from; - $from->send("ack $body"); - break; - case "pub": - echo "Client pub for $body\n"; - if (isset($this->subscriptions[$body])) { - foreach ( $this->subscriptions[$body] as $client ) { - $client->send("pub $body"); - } - } - break; - default: - echo "Client $from->resourceId said $message\n"; - foreach ( $this->clients as $client ) { - - if ( $from->resourceId == $client->resourceId ) { - continue; - } - - $client->send("Client $from->resourceId said $message\n"); - } - break; + public function sendUpdate($msg, $token) { + if (isset($this->subscriptions[$token])) { + foreach ( $this->subscriptions[$token] as $client ) { + $client->send($msg); + } } } + public function onMessage(ConnectionInterface $from, $message) { + echo "Client $from->resourceId said $message, ignoring\n"; + } + public function onClose(ConnectionInterface $conn) { echo "Client $conn->resourceId left\n"; foreach ($this->subscriptions as $url => $subscribers) { @@ -96,17 +75,19 @@ public function onError(ConnectionInterface $conn, \Exception $e) { } } +$socket = new Socket(); $server = IoServer::factory( new HttpServer( new WsServer( - new Socket() + $socket ) ), SOCKET_PORT ); echo "run 1"; -runWebHookServer(); +$wh = new WebHookServer($socket); +$wh->listen(); echo "run 2"; $server->run(); echo "run 3"; diff --git a/server/webhookServer.php b/server/webhookServer.php new file mode 100644 index 0000000..8429137 --- /dev/null +++ b/server/webhookServer.php @@ -0,0 +1,24 @@ +socket = $socket; + } + public function listen() { + $http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { + $this->socket->sendUpdate("foo", "bar"); + return React\Http\Message\Response::plaintext( + "Hello World!\n" + ); + } + ); + $host = '0.0.0.0:8080'; + $socket = new React\Socket\SocketServer($host); + $http->listen($socket); + } +} diff --git a/test.sh b/test.sh index 950baae..e474b82 100644 --- a/test.sh +++ b/test.sh @@ -9,3 +9,6 @@ docker exec -it tester npm install -g wscat docker exec -it tester /bin/bash # wscat -c ws://pubsub:8080 -s "solid-0.1" # wscat -c ws://pubsub:8081 + +# docker exec -it tester wscat -c ws://pubsub:8081 -s "solid-0.1" +# docker exec -it tester curl -i http://pubsub:8080 \ No newline at end of file From 51230df0aab84a926756eb85e7ac4eacc91fb34a Mon Sep 17 00:00:00 2001 From: Michiel de Jong Date: Fri, 7 Oct 2022 14:47:31 +0200 Subject: [PATCH 08/10] use http://pubsub:8082/token?msg --- server/webhookServer.php | 9 +++++++-- test.sh | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/server/webhookServer.php b/server/webhookServer.php index 8429137..9e0c606 100644 --- a/server/webhookServer.php +++ b/server/webhookServer.php @@ -11,13 +11,18 @@ public function __construct ($socket) { } public function listen() { $http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { - $this->socket->sendUpdate("foo", "bar"); + $url = $request->getRequestTarget(); + $firstQuestionMarkPos = strpos($url, "?"); + $channel = substr($url, 1, $firstQuestionMarkPos - 1); + $data = urldecode(substr($url, $firstQuestionMarkPos + 1)); + var_dump($url, $channel, $data); + $this->socket->sendUpdate($data, $channel); return React\Http\Message\Response::plaintext( "Hello World!\n" ); } ); - $host = '0.0.0.0:8080'; + $host = '0.0.0.0:8082'; $socket = new React\Socket\SocketServer($host); $http->listen($socket); } diff --git a/test.sh b/test.sh index e474b82..70fbccc 100644 --- a/test.sh +++ b/test.sh @@ -11,4 +11,4 @@ docker exec -it tester /bin/bash # wscat -c ws://pubsub:8081 # docker exec -it tester wscat -c ws://pubsub:8081 -s "solid-0.1" -# docker exec -it tester curl -i http://pubsub:8080 \ No newline at end of file +# docker exec -it tester curl -i "http://pubsub:8082/bar?\{\"a\":\"b://sx/a/vr?4>\"\}" \ No newline at end of file From 4e1c4a295bd7daf58cccb96d04bb17c595d4a009 Mon Sep 17 00:00:00 2001 From: Michiel de Jong Date: Fri, 7 Oct 2022 14:52:07 +0200 Subject: [PATCH 09/10] register client for token from url --- server/serverWh2Ws.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/server/serverWh2Ws.php b/server/serverWh2Ws.php index 7a3bbd9..43f1d7b 100644 --- a/server/serverWh2Ws.php +++ b/server/serverWh2Ws.php @@ -27,16 +27,18 @@ public function getSubProtocols() { return $this->subprotocols; } public function onOpen(ConnectionInterface $conn) { + $token = substr($conn->httpRequest->getUri()->getPath(), 1); + // Store the new connection in $this->clients $this->clients->attach($conn); echo "New connection! ({$conn->resourceId})\n"; - $body = "bar"; - echo "Client sub for $body\n"; - if (!isset($this->subscriptions[$body])) { - $this->subscriptions[$body] = array(); + + echo "Client sub for $token\n"; + if (!isset($this->subscriptions[$token])) { + $this->subscriptions[$token] = array(); } - $this->subscriptions[$body][] = $conn; - $conn->send("ack $body"); + $this->subscriptions[$token][] = $conn; + // $conn->send("ack $token"); } public function sendUpdate($msg, $token) { From da7738426cffcb5deb5497a1ff3042f93b225bf1 Mon Sep 17 00:00:00 2001 From: Michiel de Jong Date: Fri, 7 Oct 2022 16:21:12 +0200 Subject: [PATCH 10/10] Take data from webhook POST body, not GET query --- server/webhookServer.php | 5 ++--- test.sh | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/server/webhookServer.php b/server/webhookServer.php index 9e0c606..bdaa524 100644 --- a/server/webhookServer.php +++ b/server/webhookServer.php @@ -12,9 +12,8 @@ public function __construct ($socket) { public function listen() { $http = new React\Http\HttpServer(function (Psr\Http\Message\ServerRequestInterface $request) { $url = $request->getRequestTarget(); - $firstQuestionMarkPos = strpos($url, "?"); - $channel = substr($url, 1, $firstQuestionMarkPos - 1); - $data = urldecode(substr($url, $firstQuestionMarkPos + 1)); + $channel = substr($url, 1); + $data = $request->getBody()->__toString(); var_dump($url, $channel, $data); $this->socket->sendUpdate($data, $channel); return React\Http\Message\Response::plaintext( diff --git a/test.sh b/test.sh index 70fbccc..9c5fb81 100644 --- a/test.sh +++ b/test.sh @@ -11,4 +11,4 @@ docker exec -it tester /bin/bash # wscat -c ws://pubsub:8081 # docker exec -it tester wscat -c ws://pubsub:8081 -s "solid-0.1" -# docker exec -it tester curl -i "http://pubsub:8082/bar?\{\"a\":\"b://sx/a/vr?4>\"\}" \ No newline at end of file +# docker exec -it tester curl -d "\{\"a\":\"b://sx/a/vr?4>\"\}" http://pubsub:8082/bar \ No newline at end of file