Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fix IO::Handle response via PSGI streaming

  • Loading branch information...
commit 540700a39c5b850c41a0351735740c5d99f023c9 1 parent 12e413e
@stash authored
View
1  Changes
@@ -5,6 +5,7 @@ Revision history for Perl extension Feersum
Add missing JSON::XS test-dep.
Fix: write() prototype was incorrect.
Fix: writer not flushing on DESTROY.
+ Fix: IO::Handle in PSGI streaming response.
0.971 Wed Oct 6 16:21:00 2010 -0700
Fix the feersum script.
View
27 Feersum.xs
@@ -134,7 +134,9 @@ static HV* feersum_env(pTHX_ struct feer_conn *c);
static void feersum_start_response
(pTHX_ struct feer_conn *c, SV *message, AV *headers, int streaming);
static int feersum_write_whole_body (pTHX_ struct feer_conn *c, SV *body);
-static void feersum_handle_psgi_response(pTHX_ struct feer_conn *c, SV *ret);
+static void feersum_handle_psgi_response(
+ pTHX_ struct feer_conn *c, SV *ret, bool can_recurse);
+static void feersum_psgi_triplet(pTHX_ struct feer_conn *c, AV *psgi_triplet);
static int feersum_close_handle(pTHX_ struct feer_conn *c, bool is_writer);
static void start_read_watcher(struct feer_conn *c);
@@ -1637,7 +1639,8 @@ feersum_start_psgi_streaming(pTHX_ struct feer_conn *c, SV *streamer)
}
static void
-feersum_handle_psgi_response(pTHX_ struct feer_conn *c, SV *ret)
+feersum_handle_psgi_response(
+ pTHX_ struct feer_conn *c, SV *ret, bool can_recurse)
{
if (c->made_raw) { // psgix.io was invoked
if (IsArrayRef(ret) && av_len((AV*)SvRV(ret))+1 > 0) {
@@ -1658,8 +1661,14 @@ feersum_handle_psgi_response(pTHX_ struct feer_conn *c, SV *ret)
}
if (SvOK(ret) && !IsArrayRef(ret)) {
- trace("PSGI response non-array, c=%p ret=%p\n", c, ret);
- feersum_start_psgi_streaming(aTHX_ c, ret);
+ if (can_recurse) {
+ trace("PSGI response non-array, c=%p ret=%p\n", c, ret);
+ feersum_start_psgi_streaming(aTHX_ c, ret);
+ }
+ else {
+ sv_setpvs(ERRSV, "PSGI attempt to recurse in a streaming callback");
+ call_died(aTHX_ c, "PSGI request");
+ }
return;
}
@@ -1801,7 +1810,7 @@ call_request_callback (struct feer_conn *c)
LEAVE;
if (request_cb_is_psgi && returned >= 1) {
- feersum_handle_psgi_response(aTHX_ c, psgi_response);
+ feersum_handle_psgi_response(aTHX_ c, psgi_response, 1); // can_recurse
SvREFCNT_dec(psgi_response);
}
@@ -2352,6 +2361,14 @@ send_response (struct feer_conn *c, SV* message, AV *headers, SV *body)
RETVAL
void
+_send_psgi_response (struct feer_conn *c, SV *psgi_triplet)
+ PROTOTYPE: $$
+ PPCODE:
+ if (c->made_raw)
+ croak("psgix.io mode is active; can't send this response");
+ feersum_handle_psgi_response(aTHX_ c, psgi_triplet, 0); // no recurse
+
+void
force_http10 (struct feer_conn *c)
PROTOTYPE: $
ALIAS:
View
2  lib/Feersum/Connection.pm
@@ -32,7 +32,7 @@ sub _initiate_streaming_psgi {
@_ = (sub {
my $strm = shift;
if ($#$strm == 2) {
- $self->send_response($strm->[0],$strm->[1],$strm->[2]);
+ $self->_send_psgi_response($strm);
}
elsif ($#$strm == 1) {
return $self->start_streaming($strm->[0],$strm->[1]);
View
36 t/52-psgi-iohandle.t
@@ -1,7 +1,7 @@
#!perl
use warnings;
use strict;
-use Test::More tests => 34;
+use Test::More tests => 41;
use lib 't'; use Utils;
use File::Temp qw/tempfile/;
use Encode qw/decode_utf8/;
@@ -165,3 +165,37 @@ returning_perlio_layer: {
}
pass "all done app 4";
+
+my $APP5 = <<'EOAPP';
+ my $app5 = sub {
+ my $env = shift;
+ Test::More::pass "called app5";
+ return sub {
+ my $responder = shift;
+ open my $io, '<:encoding(UTF-16LE)',$tempname;
+ $responder->([
+ 200,['Content-Type'=>'text/plain; charset=UTF-8'],$io
+ ]);
+ };
+ };
+EOAPP
+
+my $app5 = eval $APP5;
+ok $app5, 'got app 5' || diag $@;
+$evh->psgi_request_handler($app5);
+
+returning_perlio_layer_from_stream: {
+ my $cv = AE::cv;
+ $cv->begin;
+ my $h; $h = simple_client GET => '/', sub {
+ my ($body, $headers) = @_;
+ is $headers->{'Status'}, 200, "Response OK";
+ is $headers->{'content-type'}, 'text/plain; charset=UTF-8', "C-T";
+ is decode_utf8($body), qq(\x{2603}\n), "utf8 body from streamer";
+ $cv->end;
+ undef $h;
+ };
+ $cv->recv;
+}
+
+pass "all done app 5";
Please sign in to comment.
Something went wrong with that request. Please try again.