Search code examples
javascriptphpjquerypollingserver-sent-events

How to fully implement server-sent events for message polling


I am trying to communicate with a server using an API.

to make it easier I wrote a script that will communicate the API using a php script.

My goal is to make a query to the API every second to see if there is new message in their queue.

I was advised to use server-sent events method and have the server send a respond to the client only when it has something new.

Here is my php script

<?php

    // Register autoloader function
    spl_autoload_register('apiAutoloader');
    header("Content-Type: text/event-stream\n\n");

    $config = array('host' => 'server:IP',              //REQUIRED - Server Name
                    'port' => 8018,                     //REQUIRED - Server Port
                    'userID' => 'user',                 //REQUIRED - UserID to login with
                    'password' => '123456',             //REQUIRED - password for the UserID to login with
                    );

    try {

        //create a new instance of icws
        $icws = new API\ICWS($config); 

        //create a new session
        $icws->createSession(true);     

        while(1){

            $result = $icws->processMessage();
            echo json_encode($result);  

            ob_flush();
            flush();
            sleep(1);

        }

    } catch(Exception $e){
        echo $e->getMessage();
    }

    function apiAutoloader($className)
    {
        $className = ltrim($className, '\\');
        $fileName  = '';
        $namespace = '';

        if ($lastNsPos = strripos($className, '\\')) 
        {
            $namespace = substr($className, 0, $lastNsPos);
            $className = substr($className, $lastNsPos + 1);
            $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
        }

        $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';

        $toLoad = dirname(__FILE__).'/'.$fileName;

        if (is_file($toLoad) === true)
        {
            include $toLoad;
        }
    }
?>

When a user visit my page this is the code the I run

<script>

    $(function(){

        function isset(a, b){

            if(typeof a !== "undefined" && a){
                return a
            }

            return b;
        }


        var evtSource = new EventSource("poll.php");

        evtSource.onmessage = function(e) {

            $.each(e.data.calls, function(i, item){

                $.each(item, function(z, c){

                    var interactionId = isset(c.interactionId, 0);
                    var Eic_CallDirection = isset(c.Eic_CallDirection, '');
                    var Eic_State = isset(c.Eic_State, '');
                    var AccoRDI_mid = isset(c.AccoRDI_mid, '');
                    var Eic_RemoteAddress = isset(c.Eic_RemoteAddress, '');

                    if(Eic_State == '' || Eic_CallDirection == ''){
                        return;
                    }

                    //incoming call that is not answered
                    if( Eic_CallDirection == 'I' && Eic_State == 'A'){
                        console.log('Incomming Call From ' + Eic_RemoteAddress + ' MID: ' + AccoRDI_mid );
                        return;
                    }

                    //on hold
                    if( Eic_State == 'H'){
                        console.log('Phone number ' + Eic_RemoteAddress + ' is on hold' );
                        return;
                    }

                    //voicemail
                    if( Eic_State == 'M'){
                        console.log('Phone number ' + Eic_RemoteAddress + ' is on leaving a voicemail' );
                        return;
                    }

                    //connected call
                    if(Eic_State == 'C'){
                        console.log('Live Call With ' + Eic_RemoteAddress );
                        return;
                    }

                    //Dialling call
                    if(Eic_State == 'O'){
                        console.log('Dialling ' + Eic_RemoteAddress );
                        return;
                    }

                    //Dialling call
                    if(Eic_State == 'R'){
                        console.log('Outbound call is rining and waiting for answer ' );
                        return;
                    }

                    //Call Disconnected
                    if(Eic_State == 'I' || Eic_State == 'E' ){
                        console.log('Hungup with ' + Eic_RemoteAddress );
                        return;
                    }

                });
            });
        }
    });
</script>

my code above is not working.

I don't get anything in my console. but this error Firefox can't establish a connection to the server at /icws/poll.php

How can I get it to work? Is the way I implemented by PHP script correct?


Solution

  • What is the status code on the browser request for you event source php file ? Try to use firebug to make sure its not 404.

    Also regarding php code.

    According to Mozilla source you included in your question. Proper response from server should be named and separated by newlines

    header("Content-Type: text/event-stream\n\n");     
    while (1) {     
      echo "event: ping\n"; //event name
      echo 'data: '.json(); //event data
      Echo "\n\n"; //required  
    
      ob_flush(); flush(); sleep(1);    
     }
    

    Event example

    event: userconnect
    data: {"username": "bobby", "time": "02:33:48"} 
    
    event: usermessage
    data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."}