Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 19 additions & 13 deletions lib/CGI/Application.pm
Original file line number Diff line number Diff line change
Expand Up @@ -199,22 +199,16 @@ sub run {

my $return_value;
if ($self->{__IS_PSGI}) {
my ($status, $headers) = $self->_send_psgi_headers();
my ($status, $headers) = $self->send_psgi_headers();

if (ref($body) eq 'GLOB' || (Scalar::Util::blessed($body) && $body->can('getline'))) {
# body a file handle - return it
$return_value = [ $status, $headers, $body];
}
elsif (ref($body) eq 'CODE') {

# body is a subref, or an explicit callback method is set
$return_value = sub {
my $respond = shift;

my $writer = $respond->([ $status, $headers ]);

&$body($writer);
};
# body is a subref
$return_value = $body;
}
else {

Expand Down Expand Up @@ -664,7 +658,7 @@ sub _send_headers {
}

# return a 2 element array modeling the first PSGI redirect values: status code and arrayref of header pairs
sub _send_psgi_headers {
sub send_psgi_headers {
my $self = shift;
my $q = $self->query;
my $type = $self->header_type;
Expand Down Expand Up @@ -1116,14 +1110,17 @@ The PSGI Specification allows for returning a file handle or a subroutine refere

sub returning_a_subref {
my $self = shift;

$self->header_props(-type => 'text/plain');

return sub {
my $writer = shift;
my $respond = shift;
my $writer = $respond->([ $self->send_psgi_headers ]);

foreach my $i (1..10) {
#sleep 1;
$writer->write("check $i: " . time . "\n");
}
}
$writer->close;
};
}

Expand Down Expand Up @@ -2068,6 +2065,15 @@ B<Note:> The prerun_mode() method may ONLY be called in the context of
a cgiapp_prerun() method. Your application will die() if you call
prerun_mode() elsewhere, such as in setup() or a run mode method.

=head3 send_psgi_headers()

my ($http_status_code, $headers_aref) = $self->send_psgi_headers;

This method generates PSGI headers based on header_type and header_props. It is
normally called automatically for you. However, you may call it directly if you
are using the coderef return value option, and writing your own callback to
generate the headers.

=head2 Dispatching Clean URIs to run modes

Modern web frameworks dispense with cruft in URIs, providing in clean
Expand Down
9 changes: 7 additions & 2 deletions t/lib/TestApp_PSGI_Callback.pm
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,17 @@ sub callback_subref {
my $self = shift;

$self->header_props(-type => 'text/plain');

return sub {
my $writer = shift;
my $respond = shift;

#my $writer = $respond->([200, ['Content-Type' => 'text/plain']]); # this method is fine
my $writer = $respond->([ $self->send_psgi_headers ]); # using cgi-app header props
foreach my $i (1..10) {
#sleep 1;
$writer->write("check $i: " . time . "\n");
}
}
$writer->close;
};
}

Expand Down
3 changes: 1 addition & 2 deletions t/psgi_streaming_callback.t
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use Test::Requires qw(Plack::Loader LWP::UserAgent);
use Test::TCP;

use TestApp_PSGI_Callback;
use CGI::Application::PSGI;
use CGI::PSGI;

my $test_file = 't/test_file_to_stream.txt';

Expand All @@ -27,7 +27,6 @@ test_tcp(
my $env = shift;
return sub {
my $respond = shift;
use Data::Dumper;
my $w = $respond->([ 200, ['X-Foo' => 'bar', 'Content-Type' => 'text/plain'] ]);
foreach my $i (1..5) {
#sleep 1;
Expand Down