subtype
'HTTP::Engine::Middleware::ReverseProxy::Regexp'
=> as
'Regexp'
;
coerce
'HTTP::Engine::Middleware::ReverseProxy::Regexp'
=> from
'Str'
=> via {
qr/\A$_[0]\z/
;
};
has
'allowed_remote'
=> (
is
=>
'rw'
,
isa
=>
'HTTP::Engine::Middleware::ReverseProxy::Regexp'
,
default
=>
'127\.0\.0\.1'
,
coerce
=> 1,
);
before_handle {
my
(
$c
,
$self
,
$req
) =
@_
;
return
$req
unless
$req
->address =~
$self
->allowed_remote;
my
$env
=
$req
->_connection->{env} || {};
$env
->{HTTPS} =
$req
->headers->{
'x-forwarded-https'
}
if
$req
->headers->{
'x-forwarded-https'
};
$env
->{HTTPS} =
'ON'
if
$req
->headers->{
'x-forwarded-proto'
};
my
$secure
= 0;
if
(
my
$https
=
$env
->{HTTPS} ) {
$secure
= 1
if
$https
=~ /\AON\z/i;
}
$req
->secure(
$secure
);
my
$default_port
=
$req
->secure ? 443 : 80;
if
(
$req
->headers->{
'x-forwarded-for'
} ) {
my
(
$ip
, ) =
$req
->headers->{
'x-forwarded-for'
} =~ /([^,\s]+)$/;
$req
->address(
$ip
);
}
if
(
$req
->headers->{
'x-forwarded-host'
} ) {
my
(
$host
, ) =
$req
->headers->{
'x-forwarded-host'
} =~ /([^,\s]+)$/;
if
(
$host
=~ /^(.+):(\d+)$/ ) {
$host
= $1;
$env
->{SERVER_PORT} = $2;
}
elsif
(
$req
->headers->{
'x-forwarded-port'
} ) {
$env
->{SERVER_PORT} =
$req
->headers->{
'x-forwarded-port'
};
}
else
{
$env
->{SERVER_PORT} =
$default_port
;
}
$env
->{HTTP_HOST} =
$host
;
$req
->headers->header(
'Host'
=>
$env
->{HTTP_HOST} );
}
elsif
(
$req
->headers->{
'host'
}) {
my
$host
=
$req
->headers->{
'host'
};
if
(
$host
=~ /^(.+):(\d+)$/ ) {
$env
->{HTTP_HOST} = $1;
$env
->{SERVER_PORT} = $2;
}
elsif
(
$host
=~ /^(.+)$/ ) {
$env
->{HTTP_HOST} = $1;
$env
->{SERVER_PORT} =
$default_port
;
}
}
else
{
$env
->{HTTP_HOST} =
$req
->uri->host;
$env
->{SERVER_PORT} =
$req
->uri->port ||
$default_port
;
}
$req
->_connection->{env} =
$env
;
for
my
$attr
(
qw/uri base/
) {
my
$scheme
=
$secure
?
'https'
:
'http'
;
my
$host
=
$env
->{HTTP_HOST} ||
$env
->{SERVER_NAME};
my
$port
=
$env
->{SERVER_PORT} ||
undef
;
$req
->
$attr
->scheme(
$scheme
);
$req
->
$attr
->host(
$host
);
if
((
$port
||
''
) eq
$default_port
) {
$req
->
$attr
->port(
undef
);
}
else
{
$req
->
$attr
->port(
$port
);
}
}
$req
;
};
__MIDDLEWARE__