[Rt-commit] rt branch, 4.4/migrate-cgi-env, created. rt-4.2.9-109-g7b1e70a

? sunnavy sunnavy at bestpractical.com
Fri Jan 9 13:22:25 EST 2015


The branch, 4.4/migrate-cgi-env has been created
        at  7b1e70ab9a50e10a667f117ce1bb049fbf777c85 (commit)

- Log -----------------------------------------------------------------
commit a12a6942027878d0db50196fd19187376687fb7b
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Thu Oct 9 01:50:57 2014 +0800

    abstract usage of cgi env variables

diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index 00588f7..c104856 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -222,12 +222,12 @@ sub EscapeJS {
 
 Different web servers set different environmental varibles. This
 function must return something suitable for REMOTE_USER. By default,
-just downcase $ENV{'REMOTE_USER'}
+just downcase REMOTE_USER env
 
 =cut
 
 sub WebCanonicalizeInfo {
-    return $ENV{'REMOTE_USER'} ? lc $ENV{'REMOTE_USER'} : $ENV{'REMOTE_USER'};
+    return RequestENV('REMOTE_USER') ? lc RequestENV('REMOTE_USER') : RequestENV('REMOTE_USER');
 }
 
 
@@ -524,8 +524,8 @@ sub IntuitNextPage {
 
     # This includes any query parameters.  Redirect will take care of making
     # it an absolute URL.
-    if ($ENV{'REQUEST_URI'}) {
-        $req_uri = $ENV{'REQUEST_URI'};
+    if (RequestENV('REQUEST_URI')) {
+        $req_uri = RequestENV('REQUEST_URI');
 
         # collapse multiple leading slashes so the first part doesn't look like
         # a hostname of a schema-less URI
@@ -806,13 +806,14 @@ sub AttemptPasswordAuthentication {
 
     my $m = $HTML::Mason::Commands::m;
 
+    my $remote_addr = RequestENV('REMOTE_ADDR');
     unless ( $user_obj->id && $user_obj->IsPassword( $ARGS->{pass} ) ) {
-        $RT::Logger->error("FAILED LOGIN for @{[$ARGS->{user}]} from $ENV{'REMOTE_ADDR'}");
+        $RT::Logger->error("FAILED LOGIN for @{[$ARGS->{user}]} from $remote_addr");
         $m->callback( %$ARGS, CallbackName => 'FailedLogin', CallbackPage => '/autohandler' );
         return (0, HTML::Mason::Commands::loc('Your username or password is incorrect'));
     }
     else {
-        $RT::Logger->info("Successful login for @{[$ARGS->{user}]} from $ENV{'REMOTE_ADDR'}");
+        $RT::Logger->info("Successful login for @{[$ARGS->{user}]} from $remote_addr");
 
         # It's important to nab the next page from the session before we blow
         # the session away
@@ -846,7 +847,7 @@ Load or setup a session cookie for the current user.
 
 sub _SessionCookieName {
     my $cookiename = "RT_SID_" . RT->Config->Get('rtname');
-    $cookiename .= "." . $ENV{'SERVER_PORT'} if $ENV{'SERVER_PORT'};
+    $cookiename .= "." . RequestENV('SERVER_PORT') if RequestENV('SERVER_PORT');
     return $cookiename;
 }
 
@@ -901,7 +902,7 @@ sub GetWebURLFromRequest {
 
     my $uri = URI->new( RT->Config->Get('WebURL') );
 
-    if ( defined $ENV{HTTPS} and $ENV{'HTTPS'} eq 'on' ) {
+    if ( defined RequestENV('HTTPS') and RequestENV('HTTPS') eq 'on' ) {
         $uri->scheme('https');
     }
     else {
@@ -909,8 +910,8 @@ sub GetWebURLFromRequest {
     }
 
     # [rt3.fsck.com #12716] Apache recommends use of $SERVER_HOST
-    $uri->host( $ENV{'SERVER_HOST'} || $ENV{'HTTP_HOST'} || $ENV{'SERVER_NAME'} );
-    $uri->port( $ENV{'SERVER_PORT'} );
+    $uri->host( RequestENV('SERVER_HOST') || RequestENV('HTTP_HOST') || RequestENV('SERVER_NAME') );
+    $uri->port( RequestENV('SERVER_PORT') );
     return "$uri"; # stringify to be consistent with WebURL in config
 }
 
@@ -1144,7 +1145,7 @@ sub MobileClient {
     my $self = shift;
 
 
-if (($ENV{'HTTP_USER_AGENT'} || '') =~ /(?:hiptop|Blazer|Novarra|Vagabond|SonyEricsson|Symbian|NetFront|UP.Browser|UP.Link|Windows CE|MIDP|J2ME|DoCoMo|J-PHONE|PalmOS|PalmSource|iPhone|iPod|AvantGo|Nokia|Android|WebOS|S60|Mobile)/io && !$HTML::Mason::Commands::session{'NotMobile'})  {
+if ((RequestENV('HTTP_USER_AGENT') || '') =~ /(?:hiptop|Blazer|Novarra|Vagabond|SonyEricsson|Symbian|NetFront|UP.Browser|UP.Link|Windows CE|MIDP|J2ME|DoCoMo|J-PHONE|PalmOS|PalmSource|iPhone|iPod|AvantGo|Nokia|Android|WebOS|S60|Mobile)/io && !$HTML::Mason::Commands::session{'NotMobile'})  {
     return 1;
 } else {
     return undef;
@@ -1299,12 +1300,12 @@ sub ValidateWebConfig {
     return if $_has_validated_web_config;
     $_has_validated_web_config = 1;
 
-    my $port = $ENV{SERVER_PORT};
-    my $host = $ENV{HTTP_X_FORWARDED_HOST} || $ENV{HTTP_X_FORWARDED_SERVER}
-            || $ENV{HTTP_HOST}             || $ENV{SERVER_NAME};
+    my $port = RequestENV('SERVER_PORT');
+    my $host = RequestENV('HTTP_X_FORWARDED_HOST') || RequestENV('HTTP_X_FORWARDED_SERVER')
+            || RequestENV('HTTP_HOST')             || RequestENV('SERVER_NAME');
     ($host, $port) = ($1, $2) if $host =~ /^(.*?):(\d+)$/;
 
-    if ( $port != RT->Config->Get('WebPort') and not $ENV{'rt.explicit_port'}) {
+    if ( $port != RT->Config->Get('WebPort') and not RequestENV('rt.explicit_port')) {
         $RT::Logger->warn("The requested port ($port) does NOT match the configured WebPort ($RT::WebPort).  "
                          ."Perhaps you should Set(\$WebPort, $port); in RT_SiteConfig.pm, "
                          ."otherwise your internal links may be broken.");
@@ -1319,10 +1320,10 @@ sub ValidateWebConfig {
     # Unfortunately, there is no reliable way to get the _path_ that was
     # requested at the proxy level; simply disable this warning if we're
     # proxied and there's a mismatch.
-    my $proxied = $ENV{HTTP_X_FORWARDED_HOST} || $ENV{HTTP_X_FORWARDED_SERVER};
-    if ($ENV{SCRIPT_NAME} ne RT->Config->Get('WebPath') and not $proxied) {
-        $RT::Logger->warn("The requested path ($ENV{SCRIPT_NAME}) does NOT match the configured WebPath ($RT::WebPath).  "
-                         ."Perhaps you should Set(\$WebPath, '$ENV{SCRIPT_NAME}'); in RT_SiteConfig.pm, "
+    my $proxied = RequestENV('HTTP_X_FORWARDED_HOST') || RequestENV('HTTP_X_FORWARDED_SERVER');
+    if (RequestENV('SCRIPT_NAME') ne RT->Config->Get('WebPath') and not $proxied) {
+        $RT::Logger->warn("The requested path ('" . RequestENV('SCRIPT_NAME') . "') does NOT match the configured WebPath ($RT::WebPath).  "
+                         ."Perhaps you should Set(\$WebPath, '" .  RequestENV('SCRIPT_NAME') . "' in RT_SiteConfig.pm, "
                          ."otherwise your internal links may be broken.");
     }
 }
@@ -1509,9 +1510,9 @@ EOT
     # if there is no Referer header then assume the worst
     return (1,
             "your browser did not supply a Referrer header", # loc
-        ) if !$ENV{HTTP_REFERER};
+        ) if !RequestENV('HTTP_REFERER');
 
-    my ($whitelisted, $browser, $configs) = IsRefererCSRFWhitelisted($ENV{HTTP_REFERER});
+    my ($whitelisted, $browser, $configs) = IsRefererCSRFWhitelisted(RequestENV('HTTP_REFERER'));
     return 0 if $whitelisted;
 
     if ( @$configs > 1 ) {
@@ -1800,6 +1801,11 @@ sub GetCustomFieldInputNamePrefix {
     return $prefix;
 }
 
+sub RequestENV {
+    my $name = shift;
+    return $name ? $ENV{$name} : \%ENV;
+}
+
 package HTML::Mason::Commands;
 
 use vars qw/$r $m %session/;
@@ -2033,7 +2039,7 @@ sub MaybeRedirectToApproval {
         @_
     );
 
-    return unless $ENV{REQUEST_METHOD} eq 'GET';
+    return unless RT::Interface::Web::RequestENV('REQUEST_METHOD') eq 'GET';
 
     my $id = $args{ARGSRef}->{id};
 

commit afd7e4152372bad03c1ed4ecac87b469b1d8f67a
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Thu Oct 16 00:04:46 2014 +0800

    use psgi env directly
    
    sadly we still need to keep the following env vars:
    
    * PATH
    
      mod_fastcgi starts with an empty %ENV, we need to update PATH to reflect the
      value set in Apache so we can find local installed commands like "dot".
    
    * QUERY_STRING
    
      HTML::Mason::Utils::cgi_request_args uses it to determine if to call
      url_param or not for a weird case(see inline comments there).
      (t/web/dashboards-in-menu.t fails without this because we make POST requests
      to urls with query string like /Admin/Users/DashboardsInMenu.html?id=12)
    
    Fixes: I#30427

diff --git a/lib/RT/CurrentUser.pm b/lib/RT/CurrentUser.pm
index 491c958..17eb52d 100644
--- a/lib/RT/CurrentUser.pm
+++ b/lib/RT/CurrentUser.pm
@@ -220,6 +220,12 @@ sub LanguageHandle {
         elsif ( $self->id && ($self->id == (RT->SystemUser->id||0) || $self->id == (RT->Nobody->id||0)) ) {
             # don't use ENV magic for system users
             push @_, 'en';
+        } elsif ($HTML::Mason::Commands::m) {
+            # Detect from the HTTP header.
+            require I18N::LangTags::Detect;
+            push @_, I18N::LangTags::Detect->http_accept_langs(
+                RT::Interface::Web::RequestENV('HTTP_ACCEPT_LANGUAGE')
+            );
         }
 
         $self->{'LangHandle'} = RT::I18N->get_handle(@_);
diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index c104856..a918ceb 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -853,7 +853,7 @@ sub _SessionCookieName {
 
 sub LoadSessionFromCookie {
 
-    my %cookies       = CGI::Cookie->fetch;
+    my %cookies       = CGI::Cookie->parse(RequestENV('HTTP_COOKIE'));
     my $cookiename    = _SessionCookieName();
     my $SessionCookie = ( $cookies{$cookiename} ? $cookies{$cookiename}->value : undef );
     tie %HTML::Mason::Commands::session, 'RT::Interface::Web::Session', $SessionCookie;
@@ -902,12 +902,7 @@ sub GetWebURLFromRequest {
 
     my $uri = URI->new( RT->Config->Get('WebURL') );
 
-    if ( defined RequestENV('HTTPS') and RequestENV('HTTPS') eq 'on' ) {
-        $uri->scheme('https');
-    }
-    else {
-        $uri->scheme('http');
-    }
+    $uri->scheme(RequestENV('psgi.url_scheme') || 'http');
 
     # [rt3.fsck.com #12716] Apache recommends use of $SERVER_HOST
     $uri->host( RequestENV('SERVER_HOST') || RequestENV('HTTP_HOST') || RequestENV('SERVER_NAME') );
@@ -1803,7 +1798,8 @@ sub GetCustomFieldInputNamePrefix {
 
 sub RequestENV {
     my $name = shift;
-    return $name ? $ENV{$name} : \%ENV;
+    my $env = $HTML::Mason::Commands::m->cgi_object->env;
+    return $name ? $env->{$name} : $env;
 }
 
 package HTML::Mason::Commands;
diff --git a/lib/RT/Interface/Web/Handler.pm b/lib/RT/Interface/Web/Handler.pm
index f0842b7..73176a0 100644
--- a/lib/RT/Interface/Web/Handler.pm
+++ b/lib/RT/Interface/Web/Handler.pm
@@ -266,6 +266,15 @@ sub PSGIApp {
     my $mason = sub {
         my $env = shift;
 
+        # mod_fastcgi starts with an empty %ENV, but provides it on each
+        # request.  Pick it up and cache it during the first request.
+        $ENV{PATH} //= $env->{PATH};
+
+        # HTML::Mason::Utils::cgi_request_args uses $ENV{QUERY_STRING} to
+        # determine if to call url_param or not
+        # (see comments in HTML::Mason::Utils::cgi_request_args)
+        $ENV{QUERY_STRING} = $env->{QUERY_STRING};
+
         {
             my $res = $self->CheckModPerlHandler($env);
             return $self->_psgi_response_cb( $res->finalize ) if $res;
@@ -292,29 +301,7 @@ sub PSGIApp {
         }
         $env->{PATH_INFO} = $self->_mason_dir_index( $h->interp, $req->path_info);
 
-        my $ret;
-        {
-            # XXX: until we get rid of all $ENV stuff.
-            local %ENV = (%ENV, CGI::Emulate::PSGI->emulate_environment($env));
-
-            $ret = $h->handle_psgi($env);
-        }
-
-        $RT::Logger->crit($@) if $@ && $RT::Logger;
-        warn $@ if $@ && !$RT::Logger;
-        if (ref($ret) eq 'CODE') {
-            my $orig_ret = $ret;
-            $ret = sub {
-                my $respond = shift;
-                local %ENV = (%ENV, CGI::Emulate::PSGI->emulate_environment($env));
-                $orig_ret->($respond);
-            };
-        }
-
-        return $self->_psgi_response_cb($ret,
-                                        sub {
-                                            $self->CleanupRequest()
-                                        });
+        return $self->_psgi_response_cb($h->handle_psgi($env), sub { $self->CleanupRequest() });
     };
 
     my $app = $self->StaticWrap($mason);

commit 7b1e70ab9a50e10a667f117ce1bb049fbf777c85
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Thu Oct 16 00:05:41 2014 +0800

    update the mock of $m to reflect the cgi env migration

diff --git a/t/web/redirect.t b/t/web/redirect.t
index d909d8d..4edf785 100644
--- a/t/web/redirect.t
+++ b/t/web/redirect.t
@@ -2,9 +2,9 @@ use strict;
 use warnings;
 
 use RT::Test tests => 13;
-
+use CGI::PSGI;
 my $r = $HTML::Mason::Commands::r = bless {}, 'R';
-my $m = $HTML::Mason::Commands::m = bless {}, 'M';
+my $m = $HTML::Mason::Commands::m = bless { cgi_object => CGI::PSGI->new( {} ) }, 'M';
 
 set_config(
     CanonicalizeRedirectURLs => 0,
@@ -39,11 +39,11 @@ is( RT->Config->Get('WebURL'), 'https://localhost/' );
 
 redirect_ok(
     'https://localhost/Ticket/', 'https://localhost/Ticket/',
-    { SERVER_NAME => 'localhost', SERVER_PORT => 443, HTTPS => 'on' },
+    { SERVER_NAME => 'localhost', SERVER_PORT => 443, 'psgi.url_scheme' => 'https' },
 );
 redirect_ok(
     '/Ticket/', 'https://localhost/Ticket/',
-    { SERVER_NAME => 'localhost', SERVER_PORT => 443, HTTPS => 'on' },
+    { SERVER_NAME => 'localhost', SERVER_PORT => 443, 'psgi.url_scheme' => 'https' },
 );
 redirect_ok(
     'https://localhost/Ticket/', 'http://localhost/Ticket/',
@@ -59,7 +59,7 @@ redirect_ok(
 );
 redirect_ok(
     'https://localhost/Ticket/', 'https://example.com/Ticket/',
-    { SERVER_NAME => 'example.com', SERVER_PORT => 443, HTTPS => 'on' },
+    { SERVER_NAME => 'example.com', SERVER_PORT => 443, 'psgi.url_scheme' => 'https' },
 );
 
 sub set_config {
@@ -87,10 +87,7 @@ sub set_config {
 sub redirect_ok {
     my ($to, $expected, $env, $details) = @_;
 
-    local %ENV = %ENV;
-    while ( my ($k, $v) = each %{ $env || {} } ) {
-        $ENV{ $k } = $v;
-    }
+    %{$m->cgi_object->env} = %$env;
     RT::Interface::Web::Redirect( $to );
     is($m->redirect, $expected, $details || "correct for '$to'");
 }
@@ -101,4 +98,5 @@ sub status {};
 package M;
 sub redirect { $_[0]{'last'} = $_[1] if @_ > 1; return $_[0]{'last'} }
 sub abort {}
+sub cgi_object { $_[0]{'cgi_object'} }
 

-----------------------------------------------------------------------


More information about the rt-commit mailing list