RT::Interface::Web::Redirect() broken (for 3.6) in split front/back proxying setup

RT::Interface::Web::Redirect() is broken for a split front-end proxy /
back-end RT setup.

I’m running multiple instances of RT spread over several backend servers.
They’re all accessible through a single set of front-end proxies that use
a combination of different ports and paths (though for these purposes they
could also use different hostnames) to direct access to the correct
backend.

As an example, the url https://rt-front.domain:8888/rt99/ might proxy
through to https://rt-back.otherdoman:8080/rt-customer-x/

I’m finding that some times when Redirect() is called, it is sending a
redirect back out to the client trying to redirect to the back-end
hostname and port.

Redirect looks like this:

sub Redirect {
my $redir_to = shift;
untie $HTML::Mason::Commands::session;
my $uri = URI->new($redir_to);
my $server_uri = URI->new($RT::WebURL);

 # If the user is coming in via a non-canonical
 # hostname, don't redirect them to the canonical host,
 # it will just upset them (and invalidate their credentials)
 if ($uri->host  eq $server_uri->host &&
     $uri->port eq $server_uri->port) {
         $uri->host($ENV{'HTTP_HOST'});
         $uri->port($ENV{'SERVER_PORT'});
     }

 $HTML::Mason::Commands::m->redirect($uri->canonical);
 $HTML::Mason::Commands::m->abort;

}

If I comment out the calls to $uri->host() and $uri->port() everything
works fine. I’m using 3.6.1 as shipped with Debian stable. Based on at
least one comment in the archives from back in April or May, it sounds
like this also happens with 3.6.3. I have not looked at 3.6.4 release
candidates to see if the same code exists.

Can the code block be changed to refer to set variables in
RT_SiteConfig.pm instead of the environment hash? Or to check for
something that was set intentionally? Or to check if the redirect should
always be to the canonical name?

-Chris

RT::Interface::Web::Redirect() is broken for a split front-end
proxy / back-end RT setup.

I’m running multiple instances of RT spread over several backend
servers. They’re all accessible through a single set of front-end
proxies that use a combination of different ports and paths (though
for these purposes they could also use different hostnames) to
direct access to the correct backend.

As an example, the url https://rt-front.domain:8888/rt99/ might
proxy through to https://rt-back.otherdoman:8080/rt-customer-x/

I’m finding that some times when Redirect() is called, it is
sending a redirect back out to the client trying to redirect to the
back-end hostname and port.

Redirect looks like this:

sub Redirect {
my $redir_to = shift;
untie $HTML::Mason::Commands::session;
my $uri = URI->new($redir_to);
my $server_uri = URI->new($RT::WebURL);

# If the user is coming in via a non-canonical
# hostname, don't redirect them to the canonical host,
# it will just upset them (and invalidate their credentials)
if ($uri->host  eq $server_uri->host &&
    $uri->port eq $server_uri->port) {
        $uri->host($ENV{'HTTP_HOST'});
        $uri->port($ENV{'SERVER_PORT'});
    }

$HTML::Mason::Commands::m->redirect($uri->canonical);
$HTML::Mason::Commands::m->abort;

}

If I comment out the calls to $uri->host() and $uri->port()
everything works fine. I’m using 3.6.1 as shipped with Debian
stable. Based on at least one comment in the archives from back in
April or May, it sounds like this also happens with 3.6.3. I have
not looked at 3.6.4 release candidates to see if the same code exists.

The behaviour is the same with 3.6.4. (And we’re too late to change
it now. We’re only looking at things that are regressions from 3.6.3
at this point.

I agree that the current behaviour is broken for split frontend/
backend setups. That’s not ever been something we’ve explicitly
supported, but it’s not something I want to not support. That is to
say “I want it to work right for everybody.”

So, let’s get a solution worked out.

The current code has a special case of "If we are redirecting to a
URL that appears to be a ‘canonical’ RT URL and hit RT through
something that appears to be non-canonical, for the love of god,
don’t redirect them. (When we do, they get asked to log in again
because their cookie is for another domain) Unfortunately, that
directly conflicts with the backend-server case, where RT is running
on a server and port that shouldn’t be advertised.

Can the code block be changed to refer to set variables in
RT_SiteConfig.pm instead of the environment hash? Or to check for
something that was set intentionally? Or to check if the redirect
should always be to the canonical name?

So yeah, I think that a config file flag for “always canonicalize on
redirct” would be a welcome patch for 3.6.5. Is that something you
can whip up?

Best,
Jesse

PGP.sig (186 Bytes)

Can the code block be changed to refer to set variables in
RT_SiteConfig.pm instead of the environment hash? Or to check for
something that was set intentionally? Or to check if the redirect
should always be to the canonical name?

So yeah, I think that a config file flag for “always canonicalize on
redirct” would be a welcome patch for 3.6.5. Is that something you can
whip up?

Nothing fancy, but I’ve added a call in RT_SiteConfig.pm to:

 Set($CanonicalRedirect, 1);

and then modified Redirect() with a one-liner to this:

 sub Redirect {
     my $redir_to = shift;
     untie $HTML::Mason::Commands::session;
     my $uri = URI->new($redir_to);
     my $server_uri = URI->new($RT::WebURL);

     # If the user is coming in via a non-canonical
     # hostname, don't redirect them to the canonical host,
     # it will just upset them (and invalidate their credentials)
     if ((!defined $RT::CanonicalRedirect || $RT::CanonicalRedirect == 0) &&
         $uri->host  eq $server_uri->host &&
         $uri->port eq $server_uri->port) {
             $uri->host($ENV{'HTTP_HOST'});
             $uri->port($ENV{'SERVER_PORT'});
         }

     $HTML::Mason::Commands::m->redirect($uri->canonical);
     $HTML::Mason::Commands::m->abort;
 }

That preserves the current behavior by default, only doing a canonical
redirect if CanonicalRedirect is set to some non-zero value.

-Chris

I’ve forwarded this to rt-bugs so we can address it for 3.6.5. ThanksOn Jun 19, 2007, at 1:15 PM, Chris Stromsoe wrote:

On Mon, 18 Jun 2007, Jesse Vincent wrote:

On Jun 15, 2007, at 4:20 PM, Chris Stromsoe wrote:

Can the code block be changed to refer to set variables in
RT_SiteConfig.pm instead of the environment hash? Or to check
for something that was set intentionally? Or to check if the
redirect should always be to the canonical name?
So yeah, I think that a config file flag for “always canonicalize
on redirct” would be a welcome patch for 3.6.5. Is that something
you can whip up?

Nothing fancy, but I’ve added a call in RT_SiteConfig.pm to:

Set($CanonicalRedirect, 1);

and then modified Redirect() with a one-liner to this:

sub Redirect {
    my $redir_to = shift;
    untie $HTML::Mason::Commands::session;
    my $uri = URI->new($redir_to);
    my $server_uri = URI->new($RT::WebURL);

    # If the user is coming in via a non-canonical
    # hostname, don't redirect them to the canonical host,
    # it will just upset them (and invalidate their credentials)
    if ((!defined $RT::CanonicalRedirect ||  

$RT::CanonicalRedirect == 0) &&
$uri->host eq $server_uri->host &&
$uri->port eq $server_uri->port) {
$uri->host($ENV{‘HTTP_HOST’});
$uri->port($ENV{‘SERVER_PORT’});
}

    $HTML::Mason::Commands::m->redirect($uri->canonical);
    $HTML::Mason::Commands::m->abort;
}

That preserves the current behavior by default, only doing a
canonical redirect if CanonicalRedirect is set to some non-zero value.

-Chris

PGP.sig (186 Bytes)