PSGI improvements
Call to_app() explicitly rather than using Plack::Component's overload Compile the psgi sub once per app, not once per req
This commit is contained in:
parent
ad68c7bd19
commit
9621120825
6 changed files with 66 additions and 60 deletions
115
lib/WebGUI.pm
115
lib/WebGUI.pm
|
|
@ -22,11 +22,9 @@ our $STATUS = 'beta';
|
|||
use strict;
|
||||
use Moose;
|
||||
use MooseX::NonMoose;
|
||||
|
||||
use WebGUI::Config;
|
||||
use WebGUI::Pluggable;
|
||||
use WebGUI::Paths;
|
||||
|
||||
use Try::Tiny;
|
||||
|
||||
extends 'Plack::Component';
|
||||
|
|
@ -64,60 +62,71 @@ has site => (
|
|||
},
|
||||
);
|
||||
|
||||
sub prepare_app {
|
||||
my $self = shift;
|
||||
|
||||
# WebGUI is a PSGI app is a Perl code reference. Let's create one (once).
|
||||
|
||||
# Each web request results in a call to this sub
|
||||
$self->{psgi_app} = sub {
|
||||
my $env = shift;
|
||||
|
||||
# Use the PSGI callback style response, which allows for nice things like
|
||||
# delayed response/streaming body (server push). For now we just use this for
|
||||
# unbuffered response writing
|
||||
return sub {
|
||||
my $responder = shift;
|
||||
my $session = $env->{'webgui.session'}
|
||||
or die 'Missing WebGUI Session - check WebGUI::Middleware::Session';
|
||||
|
||||
# Handle the request
|
||||
handle($session);
|
||||
|
||||
# Construct the PSGI response
|
||||
my $response = $session->response;
|
||||
my $psgi_response = $response->finalize;
|
||||
|
||||
# See if the content handler is doing unbuffered response writing
|
||||
if ( $response->streaming ) {
|
||||
try {
|
||||
# Ask PSGI server for a streaming writer object by returning only the first
|
||||
# two elements of the array reference
|
||||
my $writer = $responder->( [ $psgi_response->[0], $psgi_response->[1] ] );
|
||||
|
||||
# Store the writer object in the WebGUI::Session::Response object
|
||||
$response->writer($writer);
|
||||
|
||||
# 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);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
# Each web request results in a call to this sub
|
||||
sub call {
|
||||
my $self = shift;
|
||||
my $env = shift;
|
||||
|
||||
# Use the PSGI callback style response, which allows for nice things like
|
||||
# delayed response/streaming body (server push). For now we just use this for
|
||||
# unbuffered response writing
|
||||
return sub {
|
||||
my $responder = shift;
|
||||
my $session = $env->{'webgui.session'}
|
||||
or die 'Missing WebGUI Session - check WebGUI::Middleware::Session';
|
||||
|
||||
# Handle the request
|
||||
handle($session);
|
||||
|
||||
# Construct the PSGI response
|
||||
my $response = $session->response;
|
||||
my $psgi_response = $response->finalize;
|
||||
|
||||
# See if the content handler is doing unbuffered response writing
|
||||
if ( $response->streaming ) {
|
||||
try {
|
||||
# Ask PSGI server for a streaming writer object by returning only the first
|
||||
# two elements of the array reference
|
||||
my $writer = $responder->( [ $psgi_response->[0], $psgi_response->[1] ] );
|
||||
|
||||
# Store the writer object in the WebGUI::Session::Response object
|
||||
$response->writer($writer);
|
||||
|
||||
# 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);
|
||||
}
|
||||
};
|
||||
return $self->{psgi_app}->(@_);
|
||||
}
|
||||
|
||||
sub handle {
|
||||
|
|
|
|||
|
|
@ -68,11 +68,7 @@ sub call {
|
|||
|
||||
# Close the Session
|
||||
$env->{'webgui.session'}->close();
|
||||
#memory_cycle_ok( $env->{'webgui.session'} );
|
||||
delete $env->{'webgui.session'};
|
||||
|
||||
#use Test::Memory::Cycle;
|
||||
#memory_cycle_ok( $env );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ use WebGUI::Session::Form;
|
|||
use WebGUI::Session::Http;
|
||||
use WebGUI::Session::Icon;
|
||||
use WebGUI::Session::Id;
|
||||
use WebGUI::Session::Os;
|
||||
use WebGUI::Session::Output;
|
||||
use WebGUI::Session::Privilege;
|
||||
use WebGUI::Session::Request;
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ sub AUTOLOAD {
|
|||
my @args = @_;
|
||||
our $AUTOLOAD;
|
||||
my $method = "SUPER::".(split /::/, $AUTOLOAD)[-1];
|
||||
return if $method eq 'SUPER::DESTROY';
|
||||
return $self->$method(@args);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -231,7 +231,8 @@ Returns a boolean value indicating whether the current page will redirect to som
|
|||
|
||||
sub isRedirect {
|
||||
my $self = shift;
|
||||
return isIn($self->getStatus(), qw(302 301));
|
||||
my $status = $self->getStatus;
|
||||
return $status == 302 || $status == 301;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,6 @@ builder {
|
|||
};
|
||||
|
||||
# Return the app
|
||||
mount '/' => $wg;
|
||||
mount '/' => $wg->to_app;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue