package Plack::Server::ReverseHTTP; use strict; use 5.008_001; our $VERSION = '0.02'; use AnyEvent::ReverseHTTP; use HTTP::Message::PSGI; use HTTP::Response; use Plack::Util; sub new { my($class, %args) = @_; bless \%args, $class; } sub register_service { my($self, $app) = @_; $self->{guard} = reverse_http $self->{host}, $self->{token}, sub { my $req = shift; my $env = $req->to_psgi; if (my $client = delete $env->{HTTP_REQUESTING_CLIENT}) { @{$env}{qw( REMOTE_ADDR REMOTE_PORT )} = split /:/, $client, 2; } $env->{'psgi.nonblocking'} = Plack::Util::TRUE; $env->{'psgi.streaming'} = Plack::Util::TRUE; $env->{'psgi.multithread'} = Plack::Util::FALSE; $env->{'psgi.multiprocess'} = Plack::Util::FALSE; $env->{'psgi.run_once'} = Plack::Util::FALSE; my $r = $app->($env); if (ref $r eq 'ARRAY') { return HTTP::Response->from_psgi($r); } elsif (ref $r eq 'CODE') { my $cv = AE::cv; $r->(sub { my $r = shift; if (defined $r->[2]) { my $res = HTTP::Response->from_psgi($r); $cv->send($res); } else { my $res = HTTP::Response->from_psgi([ $r->[0], $r->[1], [] ]); # dummy my @body; return Plack::Util::inline_object write => sub { push @body, $_[0] }, close => sub { $res->content(join '', @body); $cv->send($res) }; } }); return $cv; } else { die "Bad response: $r"; } }; } sub run { my $self = shift; $self->register_service(@_); AE::cv->recv; } 1; __END__ =head1 NAME Plack::Server::ReverseHTTP - reversehttp gateway for PSGI application =head1 SYNOPSIS > plackup --server ReverseHTTP --host rhttplabel --token your-token =head1 DESCRIPTION Plack::Server::ReverseHTTP is a PSGI implementation that uses ReverseHTTP gateway to access your PSGI application on your desktop or behind the firewall from the internet. Just like Ruby's hookout does with Rack applications. =head1 AUTHOR Tatsuhiko Miyagawa Emiyagawa@bulknews.netE =head1 LICENSE This module is licensed under the same terms as Perl itself. =head1 SEE ALSO L L L =cut