Plack-Handler-AnyEvent-HTTPD

 view release on metacpan or  search on metacpan

lib/Plack/Handler/AnyEvent/HTTPD.pm  view on Meta::CPAN

    $self->{_httpd} = $httpd;
}

sub run {
    my $self = shift;
    $self->register_service(@_);

    $self->{_httpd}->run;
}

package Plack::Handler::AnyEvent::HTTPD::Server;
use parent qw(AnyEvent::HTTPD::HTTPServer);

sub new {
    my $class = shift;
    my $self  = $class->SUPER::new(
        connection_class => 'Plack::Handler::AnyEvent::HTTPD::Connection',
        @_,
    );
    $self->reg_cb(
        connect => sub {
            my($self, $con) = @_;
            Scalar::Util::weaken($self);
            $self->{conns}->{$con} = $con->reg_cb(
                request => sub {
                    my($con, $meth, $url, $hdr, $cont) = @_;
                    $self->handle_psgi_request($con, $meth, $url, $hdr, $cont);
                },
            );
        },
        disconnect => sub {
            my($self, $con) = @_;
            $con->unreg_cb(delete $self->{conns}->{$con});
        },
    );

    $self->{state} ||= {};

    $self;
}

sub handle_psgi_request {
    my($self, $con, $meth, $url, $hdr, $cont) = @_;

    my($path_info, $query) = split /\?/, $url, 2;

    my $env = {
        REMOTE_ADDR         => $con->{host},
        SERVER_PORT         => $self->port,
        SERVER_NAME         => $self->host,
        SCRIPT_NAME         => '',
        REQUEST_METHOD      => $meth,
        PATH_INFO           => URI::Escape::uri_unescape($path_info),
        REQUEST_URI         => $url,
        QUERY_STRING        => $query,
        SERVER_PROTOCOL     => 'HTTP/1.0', # no way to get this from HTTPConnection
        'psgi.version'      => [ 1, 1 ],
        'psgi.errors'       => *STDERR,
        'psgi.url_scheme'   => 'http',
        'psgi.nonblocking'  => Plack::Util::TRUE,
        'psgi.streaming'    => Plack::Util::TRUE,
        'psgi.run_once'     => Plack::Util::FALSE,
        'psgi.multithread'  => Plack::Util::FALSE,
        'psgi.multiprocess' => Plack::Util::FALSE,
        'psgi.input'        => do {
            open my $input, "<", \(ref $cont ? '' : $cont);
            $input;
        },
        'psgix.io'          => $con->{fh},
    };

    $env->{CONTENT_TYPE}   = delete $hdr->{'content-type'};
    $env->{CONTENT_LENGTH} = delete $hdr->{'content-length'};

    while (my($key, $val) = each %$hdr) {
        $key =~ tr/-/_/;
        $env->{"HTTP_" . uc $key} = $val;
    }

    my $res = Plack::Util::run_app($self->{app}, $env);

    Scalar::Util::weaken($con);
    my $respond = sub {
        my $res = shift;

        my %headers;
        while ( my($key, $val) = splice @{$res->[1]}, 0, 2) {
            $headers{$key} = exists $headers{$key} ? "$headers{$key}, $val" : $val;
        }
        my @res = ($res->[0], HTTP::Status::status_message($res->[0]), \%headers);

        if (defined $res->[2]) {
            my $content;
            Plack::Util::foreach($res->[2], sub { $content .= $_[0] });

            # Work around AnyEvent::HTTPD bugs that it sets
            # Content-Length even when it's not necessary
            if (!$content && Plack::Util::status_with_no_entity_body($res->[0])) {
                $content = sub { $_[0]->(undef) if $_[0] };
            }

            $con->response(@res, $content) if $con;

            return;
        } else {
            # Probably unnecessary, but in case ->write is
            # called before the poll callback is execute.
            my @buf;
            my $data_cb = sub { push @buf, $_[0] };
            $con->response(@res, sub {
                # TODO $data_cb = undef -> Client Disconnect
                $data_cb = shift;
                if ($data_cb && @buf) {
                    $data_cb->($_) for @buf;
                    @buf = ()
                }
            }) if $con;

            return Plack::Util::inline_object
                write => sub { $data_cb->($_[0]) if $data_cb },
                close => sub { $data_cb->(undef) if $data_cb };



( run in 1.220 second using v1.01-cache-2.11-cpan-5b529ec07f3 )