diff --git a/etc/dev.localhost.localdomain.psgi b/etc/dev.localhost.localdomain.psgi index 144af28db..2ffcee8a4 100644 --- a/etc/dev.localhost.localdomain.psgi +++ b/etc/dev.localhost.localdomain.psgi @@ -1,7 +1,4 @@ -use Plack::Builder; use lib '/data/WebGUI/lib'; use WebGUI; -my $wg = WebGUI->new( root => '/data/WebGUI', site => 'dev.localhost.localdomain.conf' ); - -$wg->psgi_app; \ No newline at end of file +my $app = WebGUI->new( root => '/data/WebGUI', site => 'dev.localhost.localdomain.conf' )->psgi_app; \ No newline at end of file diff --git a/lib/WebGUI.pm b/lib/WebGUI.pm index 6fd8f6409..d0a934ed1 100644 --- a/lib/WebGUI.pm +++ b/lib/WebGUI.pm @@ -76,112 +76,6 @@ sub BUILD { $self->config( $config ); } -#------------------------------------------------------------------- - -=head2 authen ( requestObject, [ user, pass ]) - -HTTP Basic auth for WebGUI. - -=head3 requestObject - -The Plack::Request object instantiated from the PSGI env hash - -=head3 user - -The username to authenticate with. Will pull from the request object if not specified. - -=head3 pass - -The password to authenticate with. Will pull from the request object if not specified. - -=cut - -sub authen { - my ($self, $request, $username, $password) = @_; - -# # set username and password if it's an auth handler -# if ($username eq "") { -# if ($request->auth_type eq "Basic") { -## ($status, $password) = $request->get_basic_auth_pw; # TODO - don't think this is supported by Plack::Request -# $username = $request->user; -# } -# else { -# $response->status( 401 ); # HTTP_UNAUTHORIZED; -# return; -# } -# } - - my $config = $self->config; - - # determine session id - my $sessionId = $request->cookies->{$config->getCookieName}; - - # Instantiate the session object - my $session = $self->session( WebGUI::Session->open($self->root, $config, $request, $sessionId) ); - my $log = $session->log; -# $request->pnotes(wgSession => $session); # TODO - no more pnotes - - if (defined $sessionId && $session->user->isRegistered) { # got a session id passed in or from a cookie - $log->info("BASIC AUTH: using cookie"); - $session->response->status( 200 ); # OK - return; - } - # TODO - put this back in once we figure out get_basic_auth_pw -# elsif ($status != 200) { # prompt the user for their username and password -# $log->info("BASIC AUTH: prompt for user/pass"); -# return $status; -# } - elsif (defined $username && $username ne "") { # no session cookie, let's try to do basic auth - $log->info("BASIC AUTH: using user/pass"); - my $user = WebGUI::User->newByUsername($session, $username); - if (defined $user) { - my $authMethod = $user->authMethod; - if ($authMethod) { # we have an auth method, let's try to instantiate - my $auth = eval { WebGUI::Pluggable::instanciate("WebGUI::Auth::".$authMethod, "new", [ $session, $authMethod ] ) }; - if ($@) { # got an error - $log->error($@); - $session->response->status( 500 ); # SERVER_ERROR - return; - } - elsif ($auth->authenticate($username, $password)) { # lets try to authenticate - $log->info("BASIC AUTH: authenticated successfully"); - $sessionId = $session->db->quickScalar("select sessionId from userSession where userId=?",[$user->userId]); - unless (defined $sessionId) { # no existing session found - $log->info("BASIC AUTH: creating new session"); - $sessionId = $session->id->generate; - $auth->_logLogin($user->userId, "success (HTTP Basic)"); - } - $session->{_var} = WebGUI::Session::Var->new($session, $sessionId); - $session->user({user=>$user}); - $session->response->status( 200 ); # OK - return; - } - } - } - $log->security($username." failed to login using HTTP Basic Authentication"); - $request->note_basic_auth_failure; - $session->response->status( 401 ); # HTTP_UNAUTHORIZED - return; - } - $log->info("BASIC AUTH: skipping"); - $session->response->status( 401 ); # HTTP_UNAUTHORIZED - return; -} - -sub to_app { - my ( $self, $env ) = @_; - - # immediately starts the response and stream the content - return sub { - my $respond = shift; - my $writer = $respond->( [ 200, [ 'Content-Type', 'application/json' ] ] ); - - # IO bound delayed response - $writer->write( "hi there\n" ); - $writer->close; - }; -} - sub psgi_app { my $self = shift; return $self->{psgi_app} ||= $self->compile_psgi_app; @@ -189,13 +83,11 @@ sub psgi_app { sub compile_psgi_app { my $self = shift; - + my $app = sub { my $env = shift; - - my $request = Plack::Request->new( $env ); - my $response = $self->handle($request); - + my $request = Plack::Request->new($env); # This could also be WebGUI::Request + my $response = $self->dispatch($request); return $response; }; @@ -215,79 +107,64 @@ sub compile_psgi_app { my $uploadsPath = $config->get('uploadsPath'); $app = Plack::Middleware::Static->wrap($app, path => sub { s{^$uploadsURL/}{} }, - root => "$uploadsPath/", + root => "$uploadsPath/", ); return $app; } -#------------------------------------------------------------------- - -=head2 handle ( request ) - -Primary http init/response handler for WebGUI. This method decides whether to hand off the request to contentHandler() or uploadsHandler() - -=head3 request - -The Plack::Request object - -=cut - -sub handle { - my ($self, $request) = @_; +sub dispatch { + my ( $self, $request ) = @_; - my $config = $self->config; - my $gateway = $config->get("gateway"); - my $matchUri = $request->uri; - $matchUri =~ s{^$gateway}{/}; + my $config = $self->config; + + # determine session id + my $sessionId = $request->cookies->{$config->getCookieName}; - # handle basic auth - my $auth = $request->header('Authorization'); - if ($auth && $auth =~ m/^Basic/) { # machine oriented - # Get username and password and hand over to authen - $auth =~ s/Basic //; - $self->authen($request, split(":", MIME::Base64::decode_base64($auth), 2)); - } - else { # realm oriented - # TODO - what to do here? Should we check response status after call to authen? -# $request->push_handlers(PerlAuthenHandler => sub { return WebGUI::authen($request, undef, undef, $config)}); - $self->authen($request); - } - - # url handlers - # TODO - rip out urlHandler API - convert all to middleware - # all remaining url handlers (probably just Asset which might get converted to something else) should - # set $repsonse->body (e.g. so they can set it to IO) -- they no longer return $output - my $error = ""; - my $gotMatch = 0; - my $response = $self->session->response; - - # TODO - would now be a time to fix the WEBGUI_FATAL label black magic? - WEBGUI_FATAL: foreach my $handler (@{$config->get("urlHandlers")}) { - my ($regex) = keys %{$handler}; - if ($matchUri =~ m{$regex}i) { - eval { WebGUI::Pluggable::run($handler->{$regex}, "handler", [$request, $self->session]) }; - if ($@) { - $error = $@; + # Instantiate the session object + my $session = $self->session( WebGUI::Session->open($self->root, $config, $request, $sessionId) ); + + for my $handler (@{$config->get("contentHandlers")}) { + my $output = eval { WebGUI::Pluggable::run($handler, "handler", [ $session ] )}; + if ( my $e = WebGUI::Error->caught ) { + $session->errorHandler->error($e->package.":".$e->line." - ".$e->error); + $session->errorHandler->debug($e->package.":".$e->line." - ".$e->trace); + } + elsif ( $@ ) { + $session->errorHandler->error( $@ ); + } + else { + # We decide what to do next depending on what the contentHandler returned + + # "chunked" or "empty" means it took care of its own output needs + if (defined $output && ( $output eq "chunked" || $output eq "empty" )) { + if ($session->errorHandler->canShowDebug()) { + $session->output->print($session->errorHandler->showDebug(),1); + } last; } - else { - # Record that at least one url handler ran successfully - $gotMatch = 1; - - # But only return response if body was set - if (defined $response->body ) { # or maybe get a smarter way for url handlers to flag success - b/c this may break delayed IO - return $response->finalize; - } + # non-empty output should be used as the response body + elsif (defined $output && $output ne "") { + # Auto-set the headers + $session->http->sendHeader; # TODO: should be renamed setHeader + + # Use contentHandler's return value as the output + $session->output->print($output); + if ($session->errorHandler->canShowDebug()) { + $session->output->print($session->errorHandler->showDebug(),1); + } + last; + } + # Keep processing for success codes + elsif ($session->http->getStatus < 200 || $session->http->getStatus > 299) { + $session->http->sendHeader; + last; } } - } - - if ( !$gotMatch ) { - # can't handle the url due to error or misconfiguration - $response->body( "This server is unable to handle the url '".$request->uri."' that you requested. ".$error ); } - return $response->finalize; + $session->close; + + return $session->response->finalize; } 1; diff --git a/lib/WebGUI/Asset/Template.pm b/lib/WebGUI/Asset/Template.pm index 646cd8571..21e4144be 100644 --- a/lib/WebGUI/Asset/Template.pm +++ b/lib/WebGUI/Asset/Template.pm @@ -589,7 +589,7 @@ sub process { } # Return a JSONinfied version of vars if JSON is the only requested content type. - if ( defined $session->request && $session->request->headers_in->{Accept} eq 'application/json' ) { + if ( defined $session->request && $session->request->header('Accept') eq 'application/json' ) { $session->http->setMimeType( 'application/json' ); return to_json( $vars ); } diff --git a/lib/WebGUI/Content/Asset.pm b/lib/WebGUI/Content/Asset.pm index 2eb9074dc..6ea455947 100644 --- a/lib/WebGUI/Content/Asset.pm +++ b/lib/WebGUI/Content/Asset.pm @@ -20,8 +20,6 @@ use Time::HiRes; use WebGUI::Asset; use WebGUI::PassiveAnalytics::Logging; -use Apache2::Const -compile => qw(OK); - =head1 NAME Package WebGUI::Content::MyHandler @@ -131,7 +129,7 @@ sub handler { my $oldContentType = $request->content_type($ct); if ($request->sendfile($filename) ) { $session->close; - return Apache2::Const::OK; + return; # TODO - what should we return to indicate streaming? } else { $request->content_type($oldContentType); diff --git a/lib/WebGUI/Session/Output.pm b/lib/WebGUI/Session/Output.pm index 84424690a..89640757f 100644 --- a/lib/WebGUI/Session/Output.pm +++ b/lib/WebGUI/Session/Output.pm @@ -96,8 +96,7 @@ sub print { } elsif ($self->session->request) { # TODO - put in IO bound delayed response - warn "content: $content"; -# $self->session->request->body([]) unless $self->session->request->body(); + $self->session->response->body( $self->session->response->body() . $content ); # if (ref $self->session->request->body eq 'ARRAY') { # push @{$self->session->request->body}, $content; # } else { diff --git a/lib/WebGUI/Session/Url.pm b/lib/WebGUI/Session/Url.pm index fe6a2daf1..1f5e470e9 100644 --- a/lib/WebGUI/Session/Url.pm +++ b/lib/WebGUI/Session/Url.pm @@ -322,7 +322,7 @@ sub getRequestedUrl { my $self = shift; return undef unless ($self->session->request); unless ($self->{_requestedUrl}) { - $self->{_requestedUrl} = $self->session->request->uri; + $self->{_requestedUrl} = $self->session->request->path_info; # TODO - is path_info right? my $gateway = $self->session->config->get("gateway"); $self->{_requestedUrl} =~ s/^$gateway([^?]*)\??.*$/$1/; } diff --git a/lib/WebGUI/URL/Content.pm b/lib/WebGUI/URL/Content.pm index 6d870f5ae..14a2d8fd4 100644 --- a/lib/WebGUI/URL/Content.pm +++ b/lib/WebGUI/URL/Content.pm @@ -15,6 +15,7 @@ package WebGUI::URL::Content; =cut use strict; +use Apache2::Const -compile => qw(OK DECLINED); use WebGUI::Affiliate; use WebGUI::Exception; use WebGUI::Pluggable; @@ -41,7 +42,7 @@ These subroutines are available from this package: #------------------------------------------------------------------- -=head2 handler ( request, session ) +=head2 handler ( request, server, config ) The Apache request handler for this package. @@ -60,55 +61,55 @@ to the user, instead of displaying the Page Not Found page. =cut sub handler { - my ($request, $session) = @_; - my $config = $session->config; -# my $session = $request->pnotes('wgSession'); # TODO - no more pnotes -# unless (defined $session) { - # TODO - fix this - server is gone -# $session = WebGUI::Session->open($server->dir_config('WebguiRoot'), $config->getFilename, $request, $server); -# } - WEBGUI_FATAL: foreach my $handler (@{$config->get("contentHandlers")}) { - my $output = eval { WebGUI::Pluggable::run($handler, "handler", [ $session ] )}; - if ( my $e = WebGUI::Error->caught ) { - $session->errorHandler->error($e->package.":".$e->line." - ".$e->error); - $session->errorHandler->debug($e->package.":".$e->line." - ".$e->trace); + my ($request, $server, $config) = @_; + $request->push_handlers(PerlResponseHandler => sub { + my $session = $request->pnotes('wgSession'); + unless (defined $session) { + $session = WebGUI::Session->open($server->dir_config('WebguiRoot'), $config->getFilename, $request, $server); } - elsif ( $@ ) { - $session->errorHandler->error( $@ ); - } - else { - if (defined $output) { - $session->response->body($output); - return; + WEBGUI_FATAL: foreach my $handler (@{$config->get("contentHandlers")}) { + my $output = eval { WebGUI::Pluggable::run($handler, "handler", [ $session ] )}; + if ( my $e = WebGUI::Error->caught ) { + $session->errorHandler->error($e->package.":".$e->line." - ".$e->error); + $session->errorHandler->debug($e->package.":".$e->line." - ".$e->trace); } - if ($output eq "chunked") { - if ($session->errorHandler->canShowDebug()) { - $session->output->print($session->errorHandler->showDebug(),1); + elsif ( $@ ) { + $session->errorHandler->error( $@ ); + } + else { + if ($output eq "chunked") { + if ($session->errorHandler->canShowDebug()) { + $session->output->print($session->errorHandler->showDebug(),1); + } + last; } - last; - } - if ($output eq "empty") { - if ($session->errorHandler->canShowDebug()) { - $session->output->print($session->errorHandler->showDebug(),1); + if ($output eq "empty") { + if ($session->errorHandler->canShowDebug()) { + $session->output->print($session->errorHandler->showDebug(),1); + } + last; } - last; - } - elsif (defined $output && $output ne "") { - $session->http->sendHeader; - $session->output->print($output); - if ($session->errorHandler->canShowDebug()) { - $session->output->print($session->errorHandler->showDebug(),1); + elsif (defined $output && $output ne "") { + $session->http->sendHeader; + $session->output->print($output); + if ($session->errorHandler->canShowDebug()) { + $session->output->print($session->errorHandler->showDebug(),1); + } + last; + } + # Keep processing for success codes + elsif ($session->http->getStatus < 200 || $session->http->getStatus > 299) { + $session->http->sendHeader; + last; } - last; - } - # Keep processing for success codes - elsif ($session->http->getStatus < 200 || $session->http->getStatus > 299) { - $session->http->sendHeader; - last; } } - } - $session->close; + $session->close; + return Apache2::Const::OK; + }); + $request->push_handlers(PerlMapToStorageHandler => sub { return Apache2::Const::OK }); + $request->push_handlers(PerlTransHandler => sub { return Apache2::Const::OK }); + return Apache2::Const::OK; } 1; diff --git a/t/Asset/Template.t b/t/Asset/Template.t index e4bc81e23..4ee633ec4 100644 --- a/t/Asset/Template.t +++ b/t/Asset/Template.t @@ -49,7 +49,7 @@ ok($output =~ m/true/, "process() - conditionals"); ok($output =~ m/\b(?:XY){5}\b/, "process() - loops"); # See if template listens the Accept header -$session->request->headers_in->{Accept} = 'application/json'; +$session->request->header('Accept' => 'application/json'); my $json = $template->process(\%var); my $andNowItsAPerlHashRef = eval { from_json( $json ) };