I have a Node.js server making API calls to a Catalyst REST app and the requests are chunked. Catalyst doesn't currently handle this so I've written a quick Middleware class to de-chunk.
I've only done minimal testing so far but seems to work. I'll test much more Monday, but wanted to check on my implementation here.
Does anyone see anything below that will break? One thing I'm curious about is if I need to worry about timeouts and if so how best to handle.
I'm completely ignoring chunk-extensions and trailing entity-headers for now.
sub _prepare_env {
my ( $self, $env ) = @_;
return unless do { no warnings; lc delete $env->{HTTP_TRANSFER_ENCODING} eq 'chunked' }; ## no critic
my $read_line = sub {
my $line = '';
while ( 1 ) {
die 'Failed to read from socket'
unless sysread( $input, my $char, 1 ) == 1;
$line .= $char;
return $line if $line =~ s/\015\012$//;
}
};
my $content_length = 0;
my $buf = Plack::TempBuffer->new;
while ( 1 ) {
# Read chunked header
my $line = $read_line->();
die 'Failed to read chunked header' unless length $line;
# Grab our size and trailer
my ( $hex_size, $trailer ) = $line =~ /^([0-9a-fA-F]+)(.*)$/;
die "Failed to find hex size in chunked header [$line]" unless defined $hex_size;
my $size = hex $hex_size;
# End of chunks? Then read entity-headers
if ( $size == 0 ) {
# read to empty CRLF
1 while length $read_line->();
last;
}
my $bytes = sysread( $input, my $buffer, $size );
die "Tried to read chunksize of $size bytes but read $bytes"
unless $bytes == $size;
$content_length += $size;
$buf->print( $buffer );
die 'Failed to read CRLF after reading chunk'
if $read_line->();
}
$env->{CONTENT_LENGTH} = $content_length;
$env->{'psgi.input'} = $buf->rewind;
return;
}