getting $r and env to reflect external ports

getting $r and env to reflect external ports

am 15.08.2009 00:15:41 von Jonathan Swartz

We've got a bunch of legacy code that uses $ENV{SCRIPT_URI},
$ENV{SERVER_PORT}, $r->server->port and the like to generate external
redirects.

This has worked fine til now, but now we are moving to a system where
our external port != our internal port - the load balancer is going to
forward ports 80 and ports 443 to non-secure ports 8080 and 8443 (so
that we can run httpd as a non-root user.) Unfortunately, the code
mentioned above will then use the wrong (internal) ports in the
redirects. If I were using Apache reverse proxy, ProxyPassReverse
would take care of this, but I'm not.

The legacy code is scattered in many files and will be difficult to
change. Thus I'm wondering if there's an easy way to get %ENV and $r
to reflect the external ports, without going through and changing each
port-related $ENV and $r value by hand.

e.g. In the Apache code I see that the ENV vars are populated via
ap_get_server_port - is there a way for me to hook in early enough
that I can change this?

Thanks
Jon

Re: getting $r and env to reflect external ports

am 15.08.2009 00:32:49 von aw

Jonathan Swartz wrote:
> We've got a bunch of legacy code that uses $ENV{SCRIPT_URI},
> $ENV{SERVER_PORT}, $r->server->port and the like to generate external
> redirects.
>
If these are really external redirects, they must happen through a
"Location:" response header, no ?
In that case, what about leaving your code alone and use an output
filter modifying these Location headers ?

Re: getting $r and env to reflect external ports

am 15.08.2009 01:12:11 von Jonathan Swartz

> > We've got a bunch of legacy code that uses $ENV{SCRIPT_URI},
> > $ENV{SERVER_PORT}, $r->server->port and the like to generate
> external
> > redirects.
> >
> If these are really external redirects, they must happen through a
> "Location:" response header, no ?
> In that case, what about leaving your code alone and use an output
> filter modifying these Location headers ?

Good question. That could work for redirects. But some of the code
also examines the values of these ports in conditionals, e.g.

if ($ENV{SERVER_PORT} == 80) { ... }

It isn't pretty, but it's old code and I don't want to be the one to
break it. :) Ideally I want the code to see the environment as it was
before the port switch. Maybe this is asking too much though...

Jon

Re: getting $r and env to reflect external ports

am 15.08.2009 19:04:25 von torsten.foertsch

--Boundary-01=_ZquhK5HLehMGHh2
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

On Sat 15 Aug 2009, Jonathan Swartz wrote:
> We've got a bunch of legacy code that uses $ENV{SCRIPT_URI}, =A0
> $ENV{SERVER_PORT}, $r->server->port and the like to generate external
> =A0 redirects.
>
> This has worked fine til now, but now we are moving to a system where
> =A0 our external port !=3D our internal port - the load balancer is going
> to forward ports 80 and ports 443 to non-secure ports 8080 and 8443
> (so that we can run httpd as a non-root user.) Unfortunately, the
> code mentioned above will then use the wrong (internal) ports in the
> redirects. If I were using Apache reverse proxy, ProxyPassReverse
> would take care of this, but I'm not.
>
> The legacy code is scattered in many files and will be difficult to =A0
> change. Thus I'm wondering if there's an easy way to get %ENV and $r
> =A0 to reflect the external ports, without going through and changing
> each port-related $ENV and $r value by hand.
>
> e.g. In the Apache code I see that the ENV vars are populated via =A0
> ap_get_server_port - is there a way for me to hook in early enough =A0
> that I can change this?

According to the docs the server port can also be set. But I think this is =
not a good idea.

The $r->server->port part can possibly be circumvented by reassigning a new=
function to the Apache2::ServerRec::port symbol at startup time. Try this =
in your startup.pl:

use Apache2::ServerRec ();
BEGIN {
my $old=3D\&Apache2::ServerRec::port;
*Apache2::ServerRec::port=3Dsub {
if( @_==1 ) { # read access
my $port=3D$old->(@_);
if( $port==8080 ) {
return 80;
} elsif(...) {
...
} else {
return $port;
}
} else {
return $old->(@_);
}
};
}

As for the %ENV part this approach may work. Call $r->subprocess_env in voi=
d context without parameters somewhere before the response phase, e.g. fixu=
p. This initializes the CGI variables in %ENV or rather $r->subprocess_env.=
Then use $r->subprocess_env to change what you need. The subsequent perl-s=
cript handler will know that the CGI variables are already set up and won't=
do it again. So your script should see the overridden values. That's the t=
heory.

Torsten

=2D-=20
Need professional mod_perl support?
Just hire me: torsten.foertsch@gmx.net

--Boundary-01=_ZquhK5HLehMGHh2
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

font-size:8pt;font-family:DejaVu Sans Mono">

On Sat 15 Aug 2009, Jonathan Swartz wrote:


> We've got a bunch of legacy code that=
uses $ENV{SCRIPT_URI}, =A0


> $ENV{SERVER_PORT}, $r->server->=
port and the like to generate external


> =A0 redirects.


>


> This has worked fine til now, but now=
we are moving to a system where


> =A0 our external port !=3D our intern=
al port - the load balancer is going


> to forward ports 80 and ports 443 to =
non-secure ports 8080 and 8443


> (so that we can run httpd as a non-ro=
ot user.) Unfortunately, the


> code mentioned above will then use th=
e wrong (internal) ports in the


> redirects. If I were using Apache rev=
erse proxy, ProxyPassReverse


> would take care of this, but I'm not.=


>


> The legacy code is scattered in many =
files and will be difficult to =A0


> change. Thus I'm wondering if there's=
an easy way to get %ENV and $r


> =A0 to reflect the external ports, wi=
thout going through and changing


> each port-related $ENV and $r value b=
y hand.


>


> e.g. In the Apache code I see that th=
e ENV vars are populated via =A0


> ap_get_server_port - is there a way f=
or me to hook in early enough =A0


> that I can change this?



According to the docs the server port can also be set. But I think this =
is not a good idea.



The $r->server->port part can possibly be circumvented by reassign=
ing a new function to the Apache2::ServerRec::port symbol at startup time. =
Try this in your startup.pl:



use Apache2::ServerRec ();


BEGIN {


my $old=3D\&Apache2::ServerRec::port;


*Apache2::ServerRec::port=3Dsub {


if( @_==1 ) { # read access


my $port=3D$old->(@_);


if( $port==8080 ) {


return 80;


} elsif(...) {


...


} else {


return $port;


}


} else {


return $old->(@_);


}


};


}



As for the %ENV part this approach may work. Call $r->subprocess_env =
in void context without parameters somewhere before the response phase, e.g=
fixup. This initializes the CGI variables in %ENV or rather $r->subp=
rocess_env. Then use $r->subprocess_env to change what you need. The sub=
sequent perl-script handler will know that the CGI variables are already se=
t up and won't do it again. So your script should see the overridden values=
That's the theory.



Torsten



--


Need professional mod_perl support?=


Just hire me: torsten. =3D"color:#ff0000">foertsch@gmx=
net




--Boundary-01=_ZquhK5HLehMGHh2--