AJAX PUSH (aka Comet) Applications. In the latest revisions on github there is
even the use of HTML5´s Websockets implemented, which makes the
standard way of implementing Comet by using a "hanging iframe" obsolete
(for browsers with websocket support). Also the APE server can be scripted by
using JavaScript which makes it very easy to extend it´s features (at least for
developers with JS knowledge). The default framework used is mootools, but any
other or plain JS could do the same.
One of APE´s nice features is to invoke messages to the client
by a script or application on the server side or even on a different
server. This is very usefull when you want to broadcast certain server
events or messages from other applications to the Clients connected to APE.
They way how to do this is is register a certain server command, which then
excutes the appropriate logic. The command then can be called by the invoking
script through HTTP (Depending on your needs a socket connection would also be
possible). In APE´s demo section an example for such a feature can be found in
the "Controller" Demo using a simple PHP script. (If you need an OOP style Client Library
to connect to APE through PHP you may want to check my APE_PHP on github)
However in the Controller demo every message sent by the external script is
broadcasted to every user connected to the certain channel. While this is usefull
for a lot of cases, there might be the need to send a message to only one
specific user on the channel. There is a simple solution for this problem:
One could use a different channel per user and send the message through it.
But this approach has (at least) two drawbacks. One is scalability, the other is
security. Since the way this is done could be easily found out on the server side
a "bad user" could connect to the other user´s channel and receive all of his
private messages. This post has been inspired by a discussion on APE´s mailing
list on how to implement such feature in a secure way.
In this scenario we assume that there is some kind of server side authentification
process (It wouldn`t make much sense otherwise anymway) . So when the user
is authenticated a secret key is generated or the session key or simething else is
used. This key will be send to the client with the page where the APE connection
will be established.
On the server side we create a hook for the "connect" command and register
the key as a private property on the user object.
- Ape.registerHookCmd("connect", function(params, cmd) {
- // this makes the key a private property on the user object
- cmd.user.key = params.key
- return 1;
- });
Now we create our custom APE command to be called from the script:
- Ape.registerCmd("securepush", false, function(params, infos) {
- if (params.password == "foobar") {
- if ($defined(params.channel) && $defined(params.key)){
- var channel = Ape.getChannelByName(params.channel);
- if (!$defined(channel)) return ["401", "UNKNOWN_CHANNEL"];
- var sent = false;
- channel.userslist.each(function(user){
- if(user.key == params.key){
- user.pipe.sendRaw(params.raw, params.data);
- sent = true;
- }
- });
- return sent ? {"name":"pushed","data":{"value":"ok"}} : ["400", "USER_NOT_FOUND"];
- }
- return ["400", "BAD_KEY"];
- } else {
- return ["400", "BAD_PASSWORD"];
- }
- });
- var client = new APE.Client();
- client.load();
- client.addEvent('load', function() {
- client.core.start({"name": 'UserName', "key":"secretKey"});
- client.addEvent('ready', function() {
- client.core.join('SecureChannel');
- }
- });
user and only he will receive our message (Example in PHP):
- $APEserver = 'http://ape.example.com:6969/?';
- $APEPassword = 'foobar';
- 'cmd' => 'securepush',
- 'password' => $APEPassword,
- 'raw' => 'postmsg',
- 'channel' => 'SecureChannel',
- 'key' => 'secretKey',
- 'message' => 'You have a new message!'
- )
- )
- ));
- if ($res->data->value == 'ok') {
- echo '<br />Message sent! result: ';
- } else {
- echo 'Error sending message, server response is : ';
- }
This is the most simple solution on how to do secure pushs to APE. However it
still has (atleast) one drawback, that it uses "channel.userslist.each(function(user){[...]});"
which doesn´t scale with a lot of users. I hope I will have the time to post a solution
using a proper registry and a way to reconnect with usernames (the default would response
with "NICK_USED" if a client would refresh the page).


The above post was good insight in server side authentication.
I also have a similar requirement as yours where I have to send messages only to a particular user from an external application. I have gone through your various posts on Google groups for APE and also the above one.
Wht i have done is to tweak the inlinepush.js to send user.pipe.sendRaw directly with the help of the pubid which Im passing in my Php. I will be storing this PubId alongwith the username and when the external Php is triggered with the appropriate PubId will be picked up and the message will besent to the user.
Can you share some insights if this will give rise to any problems. Im also trying to put some authentication checks in my JSSS code.
Regards,
Sudeep Sunthankar