Redirection messes up output

I’m new to Yii. Right now I am using version 1.1.4 for a company project. Started to flesh an application from the skeleton the framework tool generates and borrowed some code from the “Blogs” demo, specifically the log-in page.

I defined my own CWebApplication-derived class, lets call it MyWebApp, located in /protected/MyWebApp.php; and then hooked it in on the index.php file at the application root. The purpose of extending CWebApplication is for redirecting any non-logged-in user, trying to access actions other than "site/login" or "site/error", to the log-in page.

Here’s the thing, if I type the address “http://localhost/mysite/” in the browser (Firefox 3.6.9) I get some strange behavior, inspected by the use of FireBug:

First, I get one 302 HTTP status with a response text "Failed to load source for: http://localhost/mysite/" with a Location header pointing to "http://localhost/mysite/index.php/site/login".

This is (kind of) expected, but the problem is that the next request to that redirection address, although it gets a 200 HTTP status, the page HTML code is returned twice from the server, i.e: the page starts with <html>, then comes the <head> and <body>, then the page ends with </html> and then it repeats all over again.

I checked the layouts, the view, the controller to see if there could be a duplicate call to $this->render(), but everything seems to be fine. And strange enough, once logged-in, when I click the "log-out" link, the process generates two redirections and the HTML output gets repeated thrice. Once again, the redirections are expected because this is the logic implemented: the "site/logout" action executes and redirects to the Yii::app()->homeUrl, MyWebApp hooks the beforeControllerAction method and redirects to "site/login".

I’ve got my head crack-open and bumped for two days now and haven’t had any luck. Anyone shedding some light or insight of why this could be happening, please speak up. Any ideas are quite welcome.

Thanks.

Hard to tell what’s happening without seeing what you’re doing in the extension of CWebApplication. Can’t really tell why it’s being called twice, but the location of the header is pointing to is wrong (unless your config file or other does url rewriting)… the location should be http://localhost/mysite/index.php?r=site/login. The way I did this was to extend the controller beforeAction, but I did have to fix the returnUrl for the user.

Thank you very much for your reply, I really appreciate it.

Fair enough; here’s the code for the CWebApplication-derived class:


// File: protected/MyWebApp.php

final class MyWebApp extends CWebApplication

{

	public function beforeControllerAction(CController $controller, CAction $action)

	{

		if (Yii::app()->user->isGuest && $controller->id !== 'site')

		{

			Yii::app()->user->loginRequired();


        	// this is no necessary as the previous line ends

        	// the script execution, but just for sure.

			return false;

		}


		return true;

	}

}

and in the [font=“Courier New”]index.php[/font] file I just [font=“Courier New”]require_once(dirname(FILE).’/protected/[/font]MyWebApp[font=“Courier New”].php’)[/font] and call:


Yii::createApplication('MyWebApp', $config)->run();

I also made some changes in the [font=“Courier New”]protected/config/main.php[/font] file and set the [font=“Courier New”]urlFormat[/font] property of the [font=“Courier New”]urlManager[/font] component to be “path”, and that’s why the addresses look like [font=“Courier New”]index.php/controller/action[/font] instead of [font=“Courier New”]index.php?r=controller/action[/font], it’s defined like this:


'urlManager'=> array

(

    'urlFormat' => 'path',

    'rules'=> array

    (

        '<controller:\w+>/<id:\d+>'=>'<controller>/view',

        '<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',

        '<controller:\w+>/<action:\w+>'=>'<controller>/<action>',

    ),

),

and the [font="Courier New"]user[/font] component as:


'user'=> array

(

    'loginUrl'=> array('site/login'),


    // enable cookie-based authentication

    'allowAutoLogin'=> true,

),

Perhaps this gives you enough context, or maybe not, just let me know. In case it is necessary, and you have the time to review, I could generate a small app that reproduces this odd behavior and post it here.

Or maybe you could post the way you did it and explain what you meant by "had to fix the returlUrl". Fix it in what way, I wonder.

Again, thank you.

Oh so sorry I never noticed that you posted a response… did you ever get this working?

Don’t worry, it’s OK.

I haven’t fixed it yet. As it turns out that the browsers render the page well even if the output repeats, and it only happens after the login action, I decided that it’s not of utter importance and moved on to other task with higher priority in the implementation.

So this fix is for now on hold.

Thank you very much for your help, if I break through any possible solution I will post it here for sure.

OK cool. I’ll just show what I did by overriding the controller. In site/protected/components I edited the Controller.php file and extended the beforeAction function. It’s similar to what you have and I removed a few parts where we do RBAC but here it is:


protected function beforeAction($action)

{

    if($action->controller->id === "site" && ($action->id === "login" || $action->id === "logout"))

        return true;


    if(Yii::app()->user->isGuest)

        $this->redirect(array('site/login'));


    return true;

}

We have multiple actions on the site but it looks like you don’t so you could even make that simpler for your site.

Oh and we had to mess with the returnUrl because we let people visit the site and login while they are browsing so we needed to keep the url parameters in tact… which Yii does not keep store the any params of the previous url, shouldn’t affect you.