Cameron
Cameron

Reputation: 28853

CakePHP app in directory breaks redirects done with query string

My CakePHP 2.0 application url is: http://localhost/testapplication/

and when I do redirects on a login from a link I use a query string e.g.

localhost/testapplication/login?continue=/testapplication/admin/posts

The redirect is done using:

            if(isset($this->params['url']['continue']))
            {
                $pathtoredirect = $this->params['url']['continue'];
            }
            else
            {
                $pathtoredirect = $this->Auth->redirect();
            }

            return $this->redirect($pathtoredirect);

However when I do the redirect I will end up at a URL like:

localhost/testapplication/testapplication/admin/posts

As you can see it redirects to the passed url but because the passed url also contained the base directory it duplicates it breaking the url redirect and ending up at a 404!

Any ideas on how to get around this problem?

Just to confirm:

Upvotes: 1

Views: 667

Answers (3)

swiecki
swiecki

Reputation: 3483

It seems like you have a couple options here. If $this->params['url']['continue'] is exactly what you pass in with your query string, is it possible for you to modify your query string so it is just /admin/posts so the complete URL will be application/admin/posts?

You may not have to do this, but I'd need to see exactly what $this->params['url']['continue'] looks like. Please do a die(debug($this->params['url']['continue'])); somewhere before your redirect so we can investigate further.

Upvotes: 0

Cameron
Cameron

Reputation: 28853

Okay the fix was to do the following:

Get the full URL (as mentioned by others) here using a helper:

class LinkHelper extends AppHelper
{
    public function selfURL()
    {
        $pageURL = 'http';

        //if ($_SERVER["HTTPS"] == "on")
        if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')
        {
            $pageURL .= "s";
        }
        $pageURL .= "://";
        if ($_SERVER["SERVER_PORT"] != "80")
        {
            $pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
        } 
        else
        {
            $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
        }

        $pageURL = urlencode($pageURL);

        return $pageURL;  
    }

}

Then when using the URLs making sure to encode and decode them for use in the address bar

e.g. $pathtoredirect = urldecode($this->params['url']['continue']);

Upvotes: 0

ori
ori

Reputation: 7847

If you construct a path in either of the following ways:

$continue = Router::url(array('controller' => 'admin', 'action' => 'posts'));
$continue = Router::url('/admin/posts');

then Router::url will prepend the base path /application. Then if you call Router::url again on the resulting url (or redirect to it) Router::url will prepend it again. That's the way it works, and there's nothing you can do about it.

In reality, the url /application/admin/posts is ambiguous, but CakePHP reads it as controller=application, action=admin, and the first argument is posts.

The only ways to circumvent this are:

Use an absolute url:

$continue = Router::url(array('controller' => 'admin', 'action' => 'posts'), true);

Or make sure Router::url is only called once, e.g.:

$continue = '/admin/posts';

Or after login

$pathtoredirect = FULL_BASE_URL . $this->params['url']['continue'];

Upvotes: 1

Related Questions