D
D
devunion2014-04-03 02:08:55
Yii
devunion, 2014-04-03 02:08:55

SSO and Yii: Why doesn't a simple example work?

Good afternoon, there is a simple script that works without Yii:

<?
    header('Content-Type: text/event-stream');
    header('Cache-Control: no-cache');

    sendMsg("test message");

    function sendMsg($msg) {
        echo "data: $msg" . PHP_EOL;
        echo PHP_EOL;
        ob_flush();
        flush();
    }
?>

He is OK. The client receives messages.
Next, I try this code in a Yii controller:
function sendMsg($msg)
    {
        echo $msg . PHP_EOL;
        echo PHP_EOL;
        ob_flush();
        flush();
    }

    function actionStream()
    {
        $all = State::model()->findAll();

        if (count($all) == 0) {
            $s = new State();
            $s->update_requested = new CDbExpression('NOW()');
            $s->save();
        } else {
            $s = $all[0];
        }

        header('Content-Type: text/event-stream');
        header('Cache-Control: no-cache');

        $this->sendMsg($s->update_requested);
    }

Now the message does not reach the client:
open: [object Event]
error: undefined
open: [object Event]
error: undefined
open: [object Event]
error: undefined
The client code is standard:
var source = new EventSource(URL_EVENT_STREAM);

    source.addEventListener('message', function (e) {
        console.log('message: ' + e.data);
    }, false);

    source.addEventListener('open', function (e) {
        console.log('open: ' + e);
    }, false);

    source.addEventListener('error', function (e) {
        console.log('error: ' + e.readyState);

        if (e.readyState == EventSource.CLOSED) {
            console.log('error: ' + e);
        }
    }, false);

Tell me what's the problem. The server is the same. The response headers are the same.
I've tried all the tips I found here on the topic. Does not help...

Answer the question

In order to leave comments, you need to log in

2 answer(s)
E
evilJ0e, 2014-08-03
@devunion

Lots of mistakes man.
First, specify an empty template. Then you can send the necessary headers:
The standard says that the message should be sent as follows:
or
Rewrite your function, for example, like this:

function sendMsg($msg)
{
    echo "data: " . $msg . "\n\n";
    ob_flush();
    flush();
}

It also seems to require a mandatory actionError() in the controller.
Here is my working code for this example. Access rights remained from the previous project:
class SiteController extends Controller
{
    public $layout='//layouts/main';

    public function filters()
    {
        return array(
            'accessControl',
            'postOnly + delete',
        );
    }

     public function actions()
     {
          return array(
              'page'=>array(
                   'class'=>'CViewAction',
               ),
          );
     }

    public function accessRules() {
        return array(
            array('allow',
                'actions' => array('stream'),
                'users' => array('*'),
            ),
            array('allow',
                'actions' => array('foo'),
                'users' => array('@'),
            ),
            array('allow', 
                'actions'=>array('foo'),
                'users'=>array('admin'),
            ),
            array('deny', 
                'users'=>array('*'),
            ),
        );
    }

    public function actionError()
    {
          if($error=Yii::app()->errorHandler->error)
          {
               if(Yii::app()->request->isAjaxRequest)
                echo $error['message'];
      	else
                $this->render('error', $error);
      }
     }

    protected function sendMessage($msg)
    {
        echo "data: " . $msg . "\n\n";
        ob_flush();
        flush();
    }

    protected function sendResponse($status = 200, $body = '', $contentType = 'application/json', $cache = 'no-cache')
    {
        $statusHeader = 'HTTP/1.1 ' . $status;
        header( $statusHeader );
        header( 'Content-type: ' . $contentType );
        header( 'Cache-Control: ' . $cache );

        self::sendMessage( $body );
    }

    function actionStream()
    {
        $t = 'message';

        self::sendResponse( 200, $t, 'text/event-stream' );
    }
}

Y
Yuri Morozov, 2014-04-03
@metamorph

For starters, try putting exit right after $this->sendMsg; or Yii::app()->end();

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question