WebGUI.pm as subclass of Plack::Component

This commit is contained in:
Graham Knop 2010-04-16 19:30:39 -05:00
parent 5122518652
commit ff2a36026a
2 changed files with 70 additions and 88 deletions

View file

@ -20,16 +20,17 @@ our $STATUS = 'beta';
=cut =cut
use strict; use strict;
use MIME::Base64 (); use Moose;
use MooseX::NonMoose;
use WebGUI::Config; use WebGUI::Config;
use WebGUI::Pluggable; use WebGUI::Pluggable;
use WebGUI::Session;
use WebGUI::User;
use WebGUI::Session::Request;
use WebGUI::Paths; use WebGUI::Paths;
use Moose;
use Try::Tiny; use Try::Tiny;
extends 'Plack::Component';
=head1 NAME =head1 NAME
Package WebGUI Package WebGUI
@ -48,92 +49,73 @@ These subroutines are available from this package:
=cut =cut
has site => ( is => 'ro', isa => 'Str', default => 'dev.localhost.localdomain.conf' ); has config => (
has config => ( is => 'rw', isa => 'WebGUI::Config' ); is => 'rw',
isa => 'WebGUI::Config',
);
has site => (
is => 'ro',
isa => 'Str',
required => 1,
trigger => sub {
my ($self, $site) = @_;
my $config = WebGUI::Config->new( $site );
$self->config($config);
},
);
around BUILDARGS => sub { # Each web request results in a call to this sub
my $orig = shift; sub call {
my $class = shift;
# Make constructor work as:
# WebGUI->new( $site )
# In addition to the more verbose:
# WebGUI->new( root => $root, site => $site )
if (@_ eq 1) {
return $class->$orig(site => $_[0] );
} else {
return $class->$orig(@_);
}
};
sub BUILD {
my $self = shift; my $self = shift;
my $env = shift;
# Instantiate the WebGUI::Config object # Use the PSGI callback style response, which allows for nice things like
my $config = WebGUI::Config->new( $self->site ); # delayed response/streaming body (server push). For now we just use this for
$self->config($config); # unbuffered response writing
}
sub to_app {
my $self = shift;
return $self->{psgi_app} ||= $self->compile_psgi_app;
}
sub compile_psgi_app {
my $self = shift;
# WebGUI is a PSGI app is a Perl code reference. Let's create one.
# Each web request results in a call to this sub
return sub { return sub {
my $env = shift; my $responder = shift;
my $session = $env->{'webgui.session'}
# Use the PSGI callback style response, which allows for nice things like or die 'Missing WebGUI Session - check WebGUI::Middleware::Session';
# delayed response/streaming body (server push). For now we just use this for
# unbuffered response writing # Handle the request
return sub { handle($session);
my $responder = shift;
my $session = $env->{'webgui.session'} or die 'Missing WebGUI Session - check WebGUI::Middleware::Session'; # Construct the PSGI response
my $response = $session->response;
# Handle the request my $psgi_response = $response->finalize;
handle($session);
# See if the content handler is doing unbuffered response writing
# Construct the PSGI response if ( $response->streaming ) {
my $response = $session->response; try {
my $psgi_response = $response->finalize; # Ask PSGI server for a streaming writer object by returning only the first
# two elements of the array reference
# See if the content handler is doing unbuffered response writing my $writer = $responder->( [ $psgi_response->[0], $psgi_response->[1] ] );
if ( $response->streaming ) {
# Store the writer object in the WebGUI::Session::Response object
try { $response->writer($writer);
# Ask PSGI server for a streaming writer object by returning only the first
# two elements of the array reference # Now call the callback that does the streaming
my $writer = $responder->( [ $psgi_response->[0], $psgi_response->[1] ] ); $response->streamer->($session);
# Store the writer object in the WebGUI::Session::Response object # And finally, clean up
$response->writer($writer); $writer->close;
# Now call the callback that does the streaming
$response->streamer->($session);
# And finally, clean up
$writer->close;
} catch {
if ($response->writer) {
# Response has already been started, so log error and close writer
$session->request->TRACE("Error detected after streaming response started");
$response->writer->close;
} else {
$responder->( [ 500, [ 'Content-Type' => 'text/plain' ], [ "Internal Server Error" ] ] );
}
}
} else {
# Not streaming, so immediately tell the callback to return
# the response. In the future we could use an Event framework here
# to make this a non-blocking delayed response.
$responder->($psgi_response);
} }
catch {
if ($response->writer) {
# Response has already been started, so log error and close writer
$session->request->TRACE("Error detected after streaming response started");
$response->writer->close;
}
else {
$responder->( [ 500, [ 'Content-Type' => 'text/plain' ], [ "Internal Server Error" ] ] );
}
};
}
else {
# Not streaming, so immediately tell the callback to return
# the response. In the future we could use an Event framework here
# to make this a non-blocking delayed response.
$responder->($psgi_response);
} }
}; };
} }

View file

@ -45,10 +45,10 @@ builder {
# This one uses the Session object, so it comes after WebGUI::Middleware::Session # This one uses the Session object, so it comes after WebGUI::Middleware::Session
mount $config->get('uploadsURL') => builder { mount $config->get('uploadsURL') => builder {
enable '+WebGUI::Middleware::WGAccess'; enable '+WebGUI::Middleware::WGAccess';
Plack::App::File->new(root => $config->get('uploadsPath'))->to_app; Plack::App::File->new(root => $config->get('uploadsPath'));
}; };
# Return the app # Return the app
mount '/' => $wg->to_app; mount '/' => $wg;
}; };