0

I'm using several technologies for a web application:
nodejs for socket.io and request
nginx / PHP
server sent event
session store in a mongodb collection.

  • node/socketio/request: acts as a middleware, in place of the "old" ajax way. adding "set-cookie" in the posted header makes things work really fast, keeping session data across navigation.
  • Sessions are stored in a mongodb base, using a session_save_handler.
  • A server sent event connection is made, and here is the strange behavior:

if I don't put 'session_write_close' in top of the called file of sse, then session is lost on page refresh.
If I put it, ok seems fine, but I can't monitor any changes of the session object, which does not vary, even on user login/logout.

Here is my session Class file:

class Session {
    protected $dbSession;
    protected $maxTime;

    public function __construct() {
        $this->conn =  new Mongo('mongodb://user:passwd@hostip');
        $sitebase_app   = 'base_for_coll';

        $this->dbSession     = $this->conn->$sitebase_app->session;
        $this->maxTime = get_cfg_var("session.gc_maxlifetime");

        register_shutdown_function('session_write_close');
        session_set_save_handler(
            array($this, 'open'),
            array($this, 'close'),
            array($this, 'read'),
            array($this, 'write'),
            array($this, 'destroy'),
            array($this, 'gc')
        );

    }
    public function open() { return true; }
    public function close() { return true; }
    public function read($id) {
        $doc = $this->dbSession->findOne(array("_id" => $id), array("sessionData" => 1));
        return $doc['sessionData'];
    }
    public function write($id,$data) {
        //
        $this->dbSession->save(array("_id" => $id, "sessionData" => $data, "timeStamp" => time()));
        return true;
    }
    public function destroy($id) {
        $this->dbSession->remove(array("_id" => $id));
        return true;
    }
    public function gc() {
        $agedTime = time() - $this->maxTime;
        $this->dbSession->remove(array("timeStamp" => array('$lt' => $agedTime)));
    }
}

ini_set('session.save_handler' , 'user');
$session = new Session();

And voila my SSE php file:

include_once($_SERVER['CONF_INC']);

$APP = new App();

$APPCACHE = $APP->plug('sitebase_sockets','data_activity');
$APPCACHE->ensureIndex(['timeData_activity'=>1]);
$APPCACHE->ensureIndex(['codeData_activity'=>1]);

ini_set('output_buffering', 'off');
ini_set('zlib.output_compression', false);
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Content-Encoding: none;');

session_write_close();

flush();
ob_end_flush();
//
$time = time();
$lastmodif = filemtime(ACTIVEMODULEFILE);



function sendMsg($id , $msg) {
    ini_set('implicit_flush', true);
    ob_implicit_flush(true);
    $sessid = session_id();
    echo "id: ".uniqid() . PHP_EOL;
    echo "event: $id" . PHP_EOL;
    echo "data: {\n";
    echo "data: \"msg\": $msg  \n";
    echo "data: }\n";
    echo PHP_EOL;
    ob_flush();
    flush();
}


$notify = 1;

 


$startedAt = time();
do {

    $TEST = $APPCACHE->find(['timeData_activity'=>['$gte'=>$startedAt]]);
    if($TEST->count()!=0){
        // event : act_upd_data
        // data : json
        $startedAt = time();
         
        while($ARR = $TEST->getNext()){
            unset($ARR['_id']);
            $json = json_encode($ARR,JSON_FORCE_OBJECT);
            sendMsg($ARR['eventData_activity'] ,$json);
        }
        sleep(1);
    }
    if ((time() - $startedAt) > 360) {
        skelMdl::send_cmd('act_notify',['options'=>['sticky'=>'true']]+ array('msg'=>'DIE FOR PERIODIC TEST RELOAD'.session_id()),session_id());
        die();
    }

    usleep(250000); // 1/4 seconde

    ob_flush();
    flush();
    
    if(empty($_SESSION['idagent'])){
        $notify = 0;
        skelMdl::send_cmd('act_notify', array('msg'=>' Session agent empty'.session_id()),session_id());
        sleep(5);
    }

} while(true);

And the start of my conf.inc.php file

header('Content-Type: text/html; charset=UTF-8');
//
ini_set('display_errors', 55);
// THE SESSION_HANDLER
include_once('appclasses/ClassSession.php');
// 

if ( session_status() == PHP_SESSION_NONE ) { 
    session_start();
}

I cannot find any more ideas, any advice would be appreciated. Thanks

p.s.: socket.io instead of nature websocket, because of rooms and namespace... But of course, I would prefer using native websocket, avoiding the use of a middleware...

2
  • In fact, i would like to check for session changes in my SSE file. Of course i've checked Google, Bing and Qwant. My server settings too. But i cannot find nothing, and i don't understand why the session data is cleared if i call my SSE file without session_write_close() on top of it. Oh, and is there somme people with the same issue ? Commented Oct 26, 2015 at 8:29
  • Maybe it is not possible to monitor session changes ? Commented Nov 6, 2015 at 14:48

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.