You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by John ORourke <jo...@o-rourke.org> on 2008/04/23 11:47:31 UTC

server port number in requests

Hi folks,

I can't seem to find a way to retrieve the inbound port number during 
requests.

I have a server listening on multiple ports, and need to know which one 
the request came in on.  Here's the setup:

apache config:
    Listen 127.0.0.1:81
    Listen 127.0.0.1:82
    NameVirtualHost *:*
    <VirtualHost *:*>
       ......
    </VirtualHost>

The underlying reason for this is that I have a reverse proxy in front 
of it, which proxies HTTP and HTTPS requests.  The back-end needs to 
create self-referencing URLs but cannot tell if it's HTTP or HTTPS, so I 
decided to direct HTTP to port 81 and HTTPS to port 82.  I'd prefer to 
do it by adding a request header so if someone knows a way to do that 
please let me know!

cheers
John


Re: server port number in requests

Posted by Rhesa Rozendaal <rh...@cpan.org>.
John ORourke wrote:
> Hi folks,
> 
> The underlying reason for this is that I have a reverse proxy in front 
> of it, which proxies HTTP and HTTPS requests.  The back-end needs to 
> create self-referencing URLs but cannot tell if it's HTTP or HTTPS, so I 
> decided to direct HTTP to port 81 and HTTPS to port 82.  I'd prefer to 
> do it by adding a request header so if someone knows a way to do that 
> please let me know!

I stole this strategy from the Rails folks: on the frontend https, add this line:

	RequestHeader set X_FORWARDED_PROTO 'https'

On the backend, you can then test for $ENV{X_FORWARDED_PROTO}.


Rhesa

Re: server port number in requests

Posted by Clinton Gormley <cl...@traveljury.com>.
Hi John

> The underlying reason for this is that I have a reverse proxy in
> front 
> of it, which proxies HTTP and HTTPS requests.  The back-end needs to 
> create self-referencing URLs but cannot tell if it's HTTP or HTTPS, so I 
> decided to direct HTTP to port 81 and HTTPS to port 82.  I'd prefer to 
> do it by adding a request header so if someone knows a way to do that 
> please let me know!

You can do this with $request->get_server_port

However, what I'm doing is running a single server on my backend
machines, and then on my proxy (I'm using Pound), I have this config:

ListenHTTP
    Address      x.x.x.x
    Port         80
    HeadRemove   "X-Forwarded-For"
    HeadRemove   "X-HTTPS"
    RewriteLocation 0
End

ListenHTTPS
    Address      x.x.x.x
    Port         443
    Cert         "/path/to/cert.pem"
    HeadRemove   "X-Forwarded-For"
    AddHeader    "X-HTTPS: 1"
    RewriteLocation 0
End

Clint




Re: server port number in requests

Posted by André Warnier <aw...@ice-sa.com>.

André Warnier wrote:
> 
> André Warnier wrote:
>>
>>
>> John ORourke wrote:
>>> Hi folks,
>>>
>>> I can't seem to find a way to retrieve the inbound port number during 
>>> requests.
>>>
>>> I have a server listening on multiple ports, and need to know which 
>>> one the request came in on.  Here's the setup:
>>>
>>> apache config:
>>>    Listen 127.0.0.1:81
>>>    Listen 127.0.0.1:82
>>>    NameVirtualHost *:*
>>>    <VirtualHost *:*>
>>>       ......
>>>    </VirtualHost>
>>>
>> I believe you could resolve this as follows (although it is really a 
>> "brute force" method) :
>> Instead of one <VirtualHost *:*>, you could define 2 sections, 
>> entirely copy of eachother except for :
>>
>> <VirtualHost *:81>
>>   PerlSetVar ConnType "HTTP"
>>   ....
>> </VirtualHost>
>>
>> <VirtualHost *:82>
>>   PerlSetVar ConnType "HTTPS"
>>   ....
>> </VirtualHost>
>>
>> and then in your script/handler get the ConnType config value to tell 
>> the difference.
>>
> 
> Addendum :
> Apart from he brute force method above, I believe there must be numerous 
> other ways to achieve best what you really need.
> For instance, I would have a look at the Apache SetEnvIf configuration 
> directive, which may be used to set an environment variable later 
> retrieved by your script/module.
> I would also imagine that a HTTPS request already includes some specific 
> HTTP headers which a HTTP request does not have, and you could test for 
> that (either in the script/module or with SetEnvIf).
> Which method really works best in your case, and which is the most 
> efficient, is left as an exercise to the reader.
> 

Addendum # 2 :

Here is a more mod_perl-ish solution :

   use Apache2::RequestRec ();
   use Apache2::Connection ();
   use APR::SockAddr ();

sub handler {

my $r = shift;
my $c = $r->connection;
my $serverport = $c->local_addr->port;

# ...  and now you know

}

Refs :
http://perl.apache.org/docs/2.0/api/Apache2/RequestRec.html#C_connection_
http://perl.apache.org/docs/2.0/api/Apache2/Connection.html#C_local_addr_
http://perl.apache.org/docs/2.0/api/APR/SockAddr.html

Note : I am deriving this purely from the documentation, and haven't 
tried it myself yet.

Re: server port number in requests

Posted by André Warnier <aw...@ice-sa.com>.
André Warnier wrote:
> 
> 
> John ORourke wrote:
>> Hi folks,
>>
>> I can't seem to find a way to retrieve the inbound port number during 
>> requests.
>>
>> I have a server listening on multiple ports, and need to know which 
>> one the request came in on.  Here's the setup:
>>
>> apache config:
>>    Listen 127.0.0.1:81
>>    Listen 127.0.0.1:82
>>    NameVirtualHost *:*
>>    <VirtualHost *:*>
>>       ......
>>    </VirtualHost>
>>
> I believe you could resolve this as follows (although it is really a 
> "brute force" method) :
> Instead of one <VirtualHost *:*>, you could define 2 sections, entirely 
> copy of eachother except for :
> 
> <VirtualHost *:81>
>   PerlSetVar ConnType "HTTP"
>   ....
> </VirtualHost>
> 
> <VirtualHost *:82>
>   PerlSetVar ConnType "HTTPS"
>   ....
> </VirtualHost>
> 
> and then in your script/handler get the ConnType config value to tell 
> the difference.
> 

Addendum :
Apart from he brute force method above, I believe there must be numerous 
other ways to achieve best what you really need.
For instance, I would have a look at the Apache SetEnvIf configuration 
directive, which may be used to set an environment variable later 
retrieved by your script/module.
I would also imagine that a HTTPS request already includes some specific 
HTTP headers which a HTTP request does not have, and you could test for 
that (either in the script/module or with SetEnvIf).
Which method really works best in your case, and which is the most 
efficient, is left as an exercise to the reader.

Re: server port number in requests

Posted by André Warnier <aw...@ice-sa.com>.

John ORourke wrote:
> Hi folks,
> 
> I can't seem to find a way to retrieve the inbound port number during 
> requests.
> 
> I have a server listening on multiple ports, and need to know which one 
> the request came in on.  Here's the setup:
> 
> apache config:
>    Listen 127.0.0.1:81
>    Listen 127.0.0.1:82
>    NameVirtualHost *:*
>    <VirtualHost *:*>
>       ......
>    </VirtualHost>
> 
I believe you could resolve this as follows (although it is really a 
"brute force" method) :
Instead of one <VirtualHost *:*>, you could define 2 sections, entirely 
copy of eachother except for :

<VirtualHost *:81>
   PerlSetVar ConnType "HTTP"
   ....
</VirtualHost>

<VirtualHost *:82>
   PerlSetVar ConnType "HTTPS"
   ....
</VirtualHost>

and then in your script/handler get the ConnType config value to tell 
the difference.

AW



Re: server port number in requests

Posted by John ORourke <jo...@versatilia.com>.
Many, many thanks for the input everyone - naturally it turned out to be 
a case of RTFM but here's a summary of the simplest ways to do it.  I've 
no idea how I missed these in the docs, though I am at the 
bang-head-on-wall stage of development.

(I'm going on the assumption that the proxy may not be running mod_perl 
to keep memory footprint down)

1 - RequestHeader directive in the HTTPS proxy - avoids listening on 2 
ports but runs late in the request (fixup) - fine for proxying.

2 - $r->connection()->local_addr()->port();  (I missed that in the docs 
by assuming local_addr returned an IP address string, not an 
APR::Socket).  It's a clean way but differing by port number is not a 
flexible way to set up the application, makes it less portable.

I've just spent half an hour creating this (Apache) config snippet which 
can be included in both the HTTP and HTTPS proxies:

        SetEnv SCHEME http
        SetEnv HOST localhost
        RewriteEngine on
        RewriteCond %{HTTPS} on
        RewriteRule ^(.*) $1 [E=SCHEME:https]
        RewriteCond %{HTTP_HOST} ^(.*)$
        RewriteRule ^(.*) $1 [PT,E=HOST:%1]          <--------- note the 
PT flag, allows mod_proxy to work!
        RequestHeader set X-Absolute-URI %{SCHEME}e://%{HOST}e

and make the app allow the absolute URI to be overridden by that header.

This leaves one small security hole - any server this app is installed 
on must prevent browsers from setting that header, otherwise Bad 
Things(tm) may happen.

cheers
John


Re: server port number in requests

Posted by Torsten Foertsch <to...@gmx.net>.
On Wed 23 Apr 2008, John ORourke wrote:
> The underlying reason for this is that I have a reverse proxy in front
> of it, which proxies HTTP and HTTPS requests.  The back-end needs to
> create self-referencing URLs but cannot tell if it's HTTP or HTTPS, so I
> decided to direct HTTP to port 81 and HTTPS to port 82.  I'd prefer to
> do it by adding a request header so if someone knows a way to do that
> please let me know!

If mod_perl is enabled on the proxy you can simply add something to 
$r->headers_in prior to the response phase. It will be transmitted to the 
backend.

Otherwise if you have mod_headers you can use the RequestHeader directive. The 
SSL enabled vhost sets a custom header to one value the other vhost to 
another. You must set it in both cases or someone can send that header to the 
proxy and it will be forwarded to the backend.

Torsten 

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