Thruway
PHP Client and Router Library for Autobahn and WAMP (Web Application Messaging Protocol) for Real-Time Application Messaging
I'm using AutobahnJS and Thruway on my website and everything works fine using a nonencrypted connection:
var connection = new autobahn.Connection({
url: 'ws://www.example.com:9090',
realm: 'restricted_realm'
});
connection.onopen = function (session) {
alert('yay');
};
connection.open();
However, I am unable to use a secure connection. Changing ws://www.mysite.com:9090
to wss://www.example.com:9090
results in this error in the console:
WebSocket connection to 'wss://www.example.com:9090/' failed: Error in connection establishment: net::ERR_TIMED_OUT
I have an SSL certificate on my server and can access my site via https://www.example.com
.
What do I need to do to make secure websockets work?
Source: (StackOverflow)
I build an app with Thruway and Autobahn.js This is the first time I use these tech, and I am a little lost with Thruway code. I read in a stackoverflow thread that :
“All application specific code should reside in WAMP application components, not in the router itself.”
But put these specific code where, how ?
For example, if a client subscribe to a chatroom, and the app need to log some thing, write in DB, manage sessions, (usual things)...
In facts, for each of type of message hello, error, subscribe, publish, etc...
If any of you have any code, it will be great. For me and for others dev, as I found no example in the ex. directory of Thruway.
Thanks
Source: (StackOverflow)
I'm learning WAMP (Web Application Messaging Protocol ). I'm trying to figure out the difference between these methods in AutobahnJS.
( and PHP Client with Thruway - https://github.com/voryx/Thruway)
- register/subscribe
- call/publish
But I can't get the difference between them, any tips?
Thanks :)
Source: (StackOverflow)
I need to realize kind of WAMP-CRA authorization for Crossabr.io based on PHP/Thruway. oberstet mentioned within Thruway's github issue (50968620, 50992007) that it can be done by configuring Thruway based component as Crossbar.io router component, which is not documented anywhere.
Can anyone help me with any example (at least Crossbar.io configuration) if it's really possible?
Thx.
Source: (StackOverflow)
there is WAMP - The Web Application Messaging Protocol (https_github.com/tavendo/WAMP/blob/master/spec/basic.md)
for back-end I use https_github.com/voryx/Thruway
for a front http_autobahn.ws/js/
OS - Ubuntu 12 without GUI set up by vagrant
there is - PHP 5.5.9-1 and composer for it.
I'm trying to use standart functionality of Subscribing and Unsubscribing
I get "Unsubscribe ERROR" when trying to perform Unsubscribe
My subscribing is looks like:
this.subscribe = function(r,clientId){
if (!chat.searchSub("loc.wampchat.room.message." + self.room_id)) {
chat.transport.session.subscribe('loc.wampchat.room.message.' + self.room_id, function (args, kwargs, details) {
self.addMessage(kwargs.message, kwargs.author_id, kwargs.create_time);
}).done(function(subscription){
self.subscriber['loc.wampchat.room.message.' + self.room_id] = subscription;
});
}
if (!chat.searchSub("loc.wampchat.join.room." + self.room_id)) {
chat.transport.session.subscribe('loc.wampchat.join.room.' + self.room_id, function (args, kwargs, details) {
self.addUser(chat.connections[kwargs.user_id].user);
if(kwargs.user_id == clientId){
r.add(clientId);
}
}).done(function(subscription){
self.subscriber['loc.wampchat.join.room.' + self.room_id] = subscription;
});
}
if (!chat.searchSub("loc.wampchat.leave.room." + self.room_id)) {
chat.transport.session.subscribe('loc.wampchat.leave.room.' + self.room_id, function (args, kwargs, details) {
self.deleteUser(kwargs.user_id);
}).done(function(subscription){
self.subscriber['loc.wampchat.leave.room.' + self.room_id] = subscription;
});
}
};
the final topic ("loc.wampchat.room.message." + self.room_id) looks like "loc.wampchat.room.message.1125"
Its strange error because it's appears only for topic loc.wampchat.room.message.... and for all other topics (which are almost the same) all good!
Unsubscribing looks like:
for(var key in self.subscriber){
chat.transport.session.unsubscribe(self.subscriber[key]);
}
chat.transport.session - it's a simple global object where WAMP session is stored
Here what console (in browser, Chrome-latest) shows to me:
1. WebSocket transport receive
[8,34,6196960130236416,{},"wamp.error.no_such_subscription"]
2. (autobahn.js:791) failing transport due to protocol violation:
UNSUBSCRIBE-ERROR received for non-pending request ID
6196960130236416
3. (autobahn.js:4480) Uncaught InvalidAccessError: Failed to execute
'close' on 'WebSocket': The code must be either 1000, or between
3000 and 4999. 1002 is neither.
(autobahn.js:3010) transport.close
(autobahn.js:3129) self._protocol_violation
(autobahn.js:3648) self._process_UNSUBSCRIBE_ERROR
(autobahn.js:4451) self._socket.onmessage websocket.onmessage
And the main misunderstanding that when this error appears server no react at all - simply continue to work!
I do not see any problems in server log.
So the main question is : how critical is this error? Can I just forgot about it and continue my work or I MUST somehow fix it?
Source: (StackOverflow)
I'm trying to build a notification messaging system. Im using the SimpleWsServer.php server example. I want to push a notification to the user's browser when a task has completed on the server. This needs to be done using PHP and i cant find a tutorial where this is shown. All the tutorials seems to be showing tavendo/AutobahnJS scripts to send and receive while the PHP server runs as a manager.
Is it possible to send a message using a php script to the subscribers ? what am i missing here.Thanks
Source: (StackOverflow)
chat application example.
Mr A (07-Aug-2017 15:01) : hello all
Mr B (07-Aug-2017 15:20) : hello Mr A
The Server Date Time (dd-mmm-yyyy hh:mm) is inserted by Server. Which I can easy done in Ratchet.
Ratchet.Wamp.WampServerInterface api document
Inside the OnPublish, Where I can amend the message before really publish out.
Can Thruway do the same ? I cannot find any Thruway doc, and I see the examples but not found what I want.Thruway Examples
Source: (StackOverflow)
I need to publish messages from php script, I can publish a single message fine. But now I need to publish different messages in loop, can't find proper way how to do it, here is what I tried:
$counter = 0;
$closure = function (\Thruway\ClientSession $session) use ($connection, &$counter) {
//$counter will be always 5
$session->publish('com.example.hello', ['Hello, world from PHP!!! '.$counter], [], ["acknowledge" => true])->then(
function () use ($connection) {
$connection->close(); //You must close the connection or this will hang
echo "Publish Acknowledged!\n";
},
function ($error) {
// publish failed
echo "Publish Error {$error}\n";
}
);
};
while($counter<5){
$connection->on('open', $closure);
$counter++;
}
$connection->open();
Here I want to publish $counter value to subscribers but the value is always 5, 1.Is there a way that I open connection before loop and then in loop I publish messages
2.How to access to $session->publish() from loop ?
Thanks!
Source: (StackOverflow)
I'm using Crossbar to create a webscoket component form my existing system. The component itself is written in PHP and I'm having trouble opening PHP Sessions originally created by tradicional PHP pages on my legacy system.
The component is a Thruway Client (Authentication Provider) that runs as a PHP-CLI script "inside" Crossbar.
Now, I know PHP Sessions are'n supposed to work under CLI, but when using Crossbar, there's an actual request involved:
- The user's page opens a websocket connection
- This connection get to Crossbar (proxied by NGiNX server)
- Crossbar router calls my Component, passing the request's headers (specifically Cookie header)
- in my custom component, I can retrive the Session cookie, but can't access session at all.
Here's the code:
public function authSomeone($args = array()){
$realm = array_shift($args);
$authid = array_shift($args);
$details = array_shift($args);
$cookieHeader = $details->transport->http_headers_received->cookie;
$cookieObj = new Cookie($cookieHeader);
$cookie = $cookieObj->getCookies();
$sessionID = $cookie[\SESSION_NAME]; //My Session name is defined previously
//Set save path to the same path my legacy system uses
session_save_path("/var/lib/php/session");
session_name(\SESSION_NAME);
session_id($sessionID);
session_start();
var_dump($_SESSION);
}
This is the output:
PHP Warning: session_start(): Cannot send session cookie - headers already sent [...]
PHP Warning: session_start(): Cannot send session cache limiter - headers already sent [...]
array(0) {}
Crossbar and PHP-CLI are running under the root user, but don't worry, this is test scenario on a virtual machine. The final production environment will run in a dedicated user.
While the Warnings are expected (since PHP is's handling the request here), The $_SESSION array is supposed to be populated with the legacy system's data. Isn't it? This script has the session name and id, AND it can access the session files.
What am i doing wrong?
Source: (StackOverflow)
I am working on a sample for Internal Client + Authentication model like the one below.
Now I need to retrieve a list of connected sessions and intercept the close event of a session from Internal Client.
I want to ask if there's any method to archive that task? I was thinking about saving that list in redis, but it means I would have to re-write Thruway\Peer\Router
classes, because the needed variables are now private, we don't have access to them to extends.
File server.php
<?php
/**
* server.php
*/
require "../bootstrap.php";
require 'InternalClient.php';
require 'SimpleAuthProviderClient.php';
use Thruway\Peer\Router;
use Thruway\Transport\RatchetTransportProvider;
use React\EventLoop\Factory;
use Thruway\Manager\ManagerClient;
use Thruway\Transport\InternalClientTransportProvider;
$manager = new ManagerClient();
$loop = Factory::create();
$router = new Router($loop, $manager);
$router->addTransportProvider(new InternalClientTransportProvider($manager));
$internalTransportProvider = new InternalClientTransportProvider(new \InternalClient());
$router->addTransportProvider($internalTransportProvider);
$authMgr = new \Thruway\Authentication\AuthenticationManager();
$router->setAuthenticationManager($authMgr);
$router->addTransportProvider(new InternalClientTransportProvider($authMgr));
//Provide authentication for the realm: 'somerealm'
$authProvClient = new SimpleAuthProviderClient(["somerealm"]);
$router->addTransportProvider(new InternalClientTransportProvider($authProvClient));
$transportProvider = new RatchetTransportProvider("127.0.0.1", 9090);
$router->addTransportProvider($transportProvider);
$router->start();
File SimpleAuthProviderClient.php
<?php
/**
* SimpleAuthProviderClient.php
*/
require "../bootstrap.php";
/**
* Class SimpleAuthProviderClient
*/
class SimpleAuthProviderClient extends \Thruway\Authentication\AbstractAuthProviderClient
{
/**
* @return string
*/
public function getMethodName()
{
return 'simplysimple';
}
/**
* @param mixed $signature
* @param null $extra
* @return array
*/
public function processAuthenticate($signature, $extra = null)
{
if ($signature == "letMeIn") {
return ["SUCCESS"];
} else {
return ["FAILURE"];
}
}
}
File InternalClient.php
<?php
/**
* InternalClient.php
*/
require "../bootstrap.php";
/**
* Class InternalClient
*/
class InternalClient extends Thruway\Peer\Client
{
function __construct()
{
parent::__construct("realm1");
}
/**
* @param \Thruway\AbstractSession $session
* @param \Thruway\Transport\TransportInterface $transport
*/
public function onSessionStart($session, $transport)
{
echo "--------------- Hello from InternalClient ------------";
$this->getCallee()->register($this->session, 'com.example.getphpversion', [$this, 'getPhpVersion']);
}
function start()
{
}
/**
* @return array
*/
function getPhpVersion()
{
return [phpversion()];
}
}
Source: (StackOverflow)
I'm trying out Thruway and am having trouble getting the demo code to work.
Javascript code:
<script src="https://autobahn.s3.amazonaws.com/autobahnjs/latest/autobahn.js"></script>
<script>
// var autobahn = require('autobahn');
var connection = new autobahn.Connection({url: 'ws://dev.mysite.com:9090/', realm: 'realm1'});
connection.onopen = function (session) {
// 1) subscribe to a topic
function onevent(args) {
console.log("Event:", args[0]);
}
session.subscribe('com.myapp.hello', onevent);
// 2) publish an event
session.publish('com.myapp.hello', ['Hello, world!']);
};
connection.open();
</script>
I have SimpleWsServer.php
running:
<?php
require 'bootstrap.php';
use Thruway\Peer\Router;
use Thruway\Transport\RatchetTransportProvider;
$router = new Router();
$transportProvider = new RatchetTransportProvider("127.0.0.1", 9090);
$router->addTransportProvider($transportProvider);
$router->start();
I have SimpleClient.php
running (I removed the RPC code since I only want to push messages from server to clients):
<?php
require 'bootstrap.php';
use Thruway\ClientSession;
use Thruway\Connection;
$onClose = function ($msg) {
echo $msg;
};
$connection = new Connection(
[
"realm" => 'realm1',
"onClose" => $onClose,
"url" => 'ws://127.0.0.1:9090',
]
);
$connection->on(
'open',
function (ClientSession $session) {
// 1) subscribe to a topic
$onevent = function ($args) {
echo "Event {$args[0]}\n";
};
$session->subscribe('com.myapp.hello', $onevent);
// 2) publish an event
$session->publish('com.myapp.hello', ['Hello, world from PHP!!!'], [], ["acknowledge" => true])->then(
function () {
echo "Publish Acknowledged!\n";
},
function ($error) {
// publish failed
echo "Publish Error {$error}\n";
}
);
// // 3) register a procedure for remoting
// $add2 = function ($args) {
// return $args[0] + $args[1];
// };
// $session->register('com.myapp.add2', $add2);
//
// // 4) call a remote procedure
// $session->call('com.myapp.add2', [2, 3])->then(
// function ($res) {
// echo "Result: {$res}\n";
// },
// function ($error) {
// echo "Call Error: {$error}\n";
// }
// );
}
);
$connection->open();
It looks to me like the demo code sends the message Hello, world from PHP!!!
to the client after it subscribes, but I'm not seeing a message in my browser's console.
I know the client is connecting to the server because SimpleClient.php
outputs the following to the terminal:
2015-03-02T19:47:24.5464800 debug [Thruway\Transport\PawlTransportProvider 13800] Received: [36,1574620859,33562629,{},["Hello, world!"]]
2015-03-02T19:47:24.5470880 debug [Thruway\Peer\Client 13800] Client onMessage: [Thruway\Message\EventMessage]
Event Hello, world!
Am I missing something, or should Hello, world from PHP!!!
have been printed out in the browser console?
Source: (StackOverflow)
I'm going around in circles trying to get this to work...
Here's the situation:
I have a PHP web app which makes remote procedure calls (RPCs) to several microservices via a Crossbar.io router using Thruway. Anonymous calls are working perfectly, but now I want to add authentication.
Here is the Crossbar configuration:
{
"controller": {
},
"workers": [
{
"type": "router",
"realms": [
{
"name": "dashboard",
"roles": [
{
"name": "microservice",
"permissions": [
{
"uri": "*",
"publish": true,
"subscribe": true,
"call": true,
"register": true
}
]
}
]
}
],
"transports": [
{
"type": "websocket",
"endpoint": {
"type": "tcp",
"port": 80
},
"auth": {
"wampcra": {
"type": "static",
"users": {
"client1": {
"secret": "secret1",
"role": "microservice"
}
}
}
}
}
]
}
]
}
The Crossbar server is (I hope) set up as a router only. All clients/workers are on other servers. I've been following this example for the Crossbar config - specifically, this configuration file. There are a couple of important differences between the example and my config: the example server is configured as both a router and also serves static web pages (which mine does not) and the example server includes a Python component which (if I'm reading it correctly) is not material to the authentication process.
In my development environment I'm trying to get authentication to work for one client. Here's the client code:
<?php
// include the autoloader
//
require __DIR__ . '/vendor/autoload.php';
use Thruway\ClientSession;
use Thruway\Peer\Client;
use Thruway\Transport\PawlTransportProvider;
use Thruway\Authentication\ClientWampCraAuthenticator;
// create the WAMP client
//
$client = new Client('dashboard');
$auth = new ClientWampCraAuthenticator("client1", "secret1");
$client->addClientAuthenticator($auth);
// add the WAMP transport provider
//
$client->addTransportProvider(
new PawlTransportProvider('ws://192.168.1.10/')
);
// handle the "open" (connect) event
//
$client->on('open', function (ClientSession $session) {
// register the getImageData procedure
//
$session->register('service.client1.get', function ($data) {
return (new Client)->get();
});
});
// start the client
//
$client->start();
The problem is that the "challenge" message is never sent by the server. When the client attempts to connect, I get the following debug message:
2015-07-07T13:58:17.7451860 debug [Thruway\Transport\PawlTransportProvider 204] Received: [3,{"message":"no user with authid 'anonymous' in user database"},"wamp.error.not_authorized"]
Can anyone explain what additional configuration I need to do to get the server to challenge the client?
Source: (StackOverflow)