./app.psgi
package MGH_Biostat::TravEpi::TRhIP::PSGI;
use Modern::Perl;
use experimental 'switch';
use lib './lib';
use MGH_Biostat::TravEpi::TRhIP::App;
use MGH_Biostat::TravEpi::SimpleRulesBase::SimpleAuthenticator;
use MGH_Biostat::TravEpi::SimpleRulesBase::Logger;
use File::RotateLogs;
use Plack::Response;
use Plack::App::File;
use Plack::Builder;
use Plack::Middleware::EnvObject;
my $NOT_FOUND = [
404,
[ 'Content-Type' => 'text/plain; charset=utf-8' ],
[ 'Not Found' ],
];
# this is a totally stupid way to protect things, but I only want the simplest
# level of protection for a few helper destinations
my $auth = MGH_Biostat::TravEpi::SimpleRulesBase::SimpleAuthenticator->new( 'GTEN', 'xxxx', 'xxxx' );
# create a logger that rotates files
my $rotator = File::RotateLogs->new(
logfile => './logs/applog.%Y-%m-%d' . '.' . $$,
rotationtime => 60 * 60 * 24 * 7, # one week
);
my $logger = MGH_Biostat::TravEpi::SimpleRulesBase::Logger->new($rotator);
# by creating the app object externally, we can reload the object
# (and thus reload the templates) without needing to restart the server
my $app_obj = MGH_Biostat::TravEpi::TRhIP::App->new();
my $app = sub {
my $env = shift;
given ( $env->{PATH_INFO} ) {
when ( [ '/', '/index' ] ) {
return [
302,
[ 'Location' => 'trhip' ],
[]
];
}
when ( [ '/trhip' ] ) {
return $app_obj->dispatch($env);
}
when (qr|cdc-redirect/([a-z-]+)|) {
my $country = $1;
my $hash = $env->{'QUERY_STRING'}; # @WARNING: breach of data encapsulation
if ( defined($hash) and ( $hash ne '' ) ) {
$env->{'gten.logger'}->log( $env, $hash, '!na', 'redirect: ' . $country );
}
my $cdc_url = "http://wwwnc.cdc.gov/travel/destinations/traveler/none/${country}";
return [
302,
[ 'Location' => $cdc_url ],
[]
];
}
when ( [ '/dumpapp' ] ) {
if ( $auth->auth($env) ) {
use Data::Dump qw/pp/;
return [
200,
[ 'Content-Type' => 'text/plain; charset=utf-8' ],
[ pp($app_obj) ],
];
}
else {
return $auth->unauth();
}
}
when ( [ '/showrules' ] ) {
if ( $auth->auth($env) ) {
return $app_obj->showrules($env);
}
else {
return $auth->unauth();
}
}
when ( [ '/showenv' ] ) {
if ( $auth->auth($env) ) {
use Data::Dump qw/pp/;
return [
200,
[ 'Content-Type' => 'text/plain; charset=utf-8' ],
[ pp( \%ENV ) . "\n\n" . pp($env) ],
];
}
else {
return $auth->unauth();
}
}
when ( [ '/showlogs' ] ) {
if ( $auth->auth($env) ) {
return $app_obj->showlogs($env);
}
else {
return $auth->unauth();
}
}
when ( [ '/stoplogging' ] ) {
if ( $auth->auth($env) ) {
my $res = Plack::Response->new(
200,
[ 'Content-Type' => 'text/plain; charset=utf-8' ],
'Logging should be stopped for this computer and browser for 7 days. This may not work in IE.'
);
$res->cookies->{'nologging'} = {
'value' => 'stop-logging',
'domain' => 'gten.travel',
'path' => '/trhip',
'max-age' => ( 7 * 24 * 60 * 60 ),
};
return $res->finalize();
}
else {
return $auth->unauth();
}
}
when ( [ '/startlogging' ] ) {
if ( $auth->auth($env) ) {
my $res = Plack::Response->new(
200,
[ 'Content-Type' => 'text/plain; charset=utf-8' ],
'Logging should be re-enabled.'
);
$res->cookies->{'nologging'} = {
'value' => 'stop-logging',
'domain' => 'gten.travel',
'path' => '/trhip',
'max-age' => 0,
'expires' => time - 60,
};
return $res->finalize();
}
else {
return $auth->unauth();
}
}
default {
return $NOT_FOUND;
}
}
};
builder {
# inline middleware to prevent caching
# based on https://github.com/tokuhirom/Plack-Middleware-NoCache/blob/master/lib/Plack/Middleware/NoCache.pm
enable sub {
my $app = shift;
sub {
my $env = shift;
my $res = $app->($env);
push @{ $res->[ 1 ] }, 'Cache-Control' => 'no-cache, no-store', 'Pragma' => 'no-cache', 'Expires' => 0;
return $res;
};
};
enable "EnvObject", 'name' => 'gten.logger', 'object' => $logger;
mount '/css/trhip.css' => Plack::App::File->new(
file => 'public/css/trhip.css',
content_type => 'text/css'
)->to_app();
mount '/images' => Plack::App::File->new( root => 'public/images' )->to_app();
mount '/js' => Plack::App::File->new( root => 'public/js' )->to_app();
mount '/' => $app;
};