Skip to content

Instantly share code, notes, and snippets.

@motemen
Created December 2, 2010 09:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save motemen/725025 to your computer and use it in GitHub Desktop.
Save motemen/725025 to your computer and use it in GitHub Desktop.
#!/usr/bin/env perl
use strict;
use warnings;
use Plack::Runner;
use AnyEvent::Handle;
use opts;
Getopt::Long::Configure('pass_through');
opts (
my $content_type => { isa => 'Str', default => 'text/plain; charset=utf-8', comment => 'Content-Type header' },
);
my @writers;
my $bytes_left = ''; # bytes remaining when stdin destroyed
my $stdin = AnyEvent::Handle->new(
fh => \*STDIN,
on_read => sub {
writeout();
},
on_eof => sub {
$_->close for @writers;
# exit; # Can't detect when to exit
},
on_error => sub {
$bytes_left = $_[0]->rbuf;
},
);
sub writeout {
return unless @writers;
if ($stdin->destroyed) {
$_->write($bytes_left) for @writers;
} else {
$_->write($stdin->rbuf) for @writers;
$stdin->{rbuf} = '';
}
}
my $app = sub {
my $env = shift;
$env->{'psgi.streaming'} or die 'psgi.streaming not supported';
return sub {
my $respond = shift;
my $writer = $respond->([ 200, [ 'Content-Type' => $content_type ] ]);
push @writers, $writer;
writeout();
};
};
my $runner = Plack::Runner->new(app => $app);
$runner->parse_options(@ARGV);
$runner->run;
__END__
=pod
=head1 NAME
httpcat.pl - Pipe stdin via HTTP
=head1 SYNOPSIS
# All options other than --content-type are sent to plackup
% tail -f ... | httpcat.pl --content-type text/plain --port 9090
=head1 SEE ALSO
plackup
=cut
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment