Changeset 13439

Show
Ignore:
Timestamp:
06/08/08 06:23:24 (5 years ago)
Author:
nothingmuch
Message:

fix Standalone

Location:
lang/perl/HTTP-Engine/branches/lazy_request/lib/HTTP/Engine
Files:
2 added
7 modified

Legend:

Unmodified
Added
Removed
  • lang/perl/HTTP-Engine/branches/lazy_request/lib/HTTP/Engine/Interface/Standalone.pm

    r11845 r13439  
    33with 'HTTP::Engine::Role::Interface'; 
    44 
    5 use Errno 'EWOULDBLOCK'; 
    65use Socket qw(:all); 
    76use IO::Socket::INET (); 
     
    4645); 
    4746 
    48  
    49 use HTTP::Engine::ResponseWriter; 
    50 HTTP::Engine::RequestBuilder->meta->add_method( _read_chunk  => sub { 
    51     shift; 
    52     # support for non-blocking IO 
    53     my $rin = ''; 
    54     vec($rin, *STDIN->fileno, 1) = 1; 
    55  
    56     READ: 
    57     { 
    58         select($rin, undef, undef, undef); ## no critic. 
    59         my $rc = *STDIN->sysread(@_); 
    60         if (defined $rc) { 
    61            return $rc; 
    62        } else { 
    63             next READ if $! == EWOULDBLOCK; 
    64             return; 
    65         } 
    66     } 
    67 }); 
    68  
    69 HTTP::Engine::RequestBuilder->meta->add_before_method_modifier( _prepare_read => sub { 
    70     my $self = shift; 
    71     # Set the input handle to non-blocking 
    72     *STDIN->blocking(0); 
    73 }); 
    74  
    75 use HTTP::Engine::ResponseWriter; 
    76 my $is_keepalive; 
    77 HTTP::Engine::ResponseWriter->meta->add_before_method_modifier( finalize => sub { 
    78     my($self, $c) = @_; 
    79  
    80     $c->res->headers->date(time); 
    81     $c->res->headers->header( 
    82         Connection => $is_keepalive ? 'keep-alive' : 'close' 
    83     ); 
    84 }); 
    85  
    8647sub run { 
    87     my($self, ) = @_; 
    88  
    89     $is_keepalive = sub { $self->keepalive }; 
     48    my ( $self ) = @_; 
     49 
     50    $self->response_writer->keepalive( $self->keepalive ); 
    9051 
    9152    my $host = $self->host; 
     
    11980    my $pid    = undef; 
    12081    local $SIG{CHLD} = 'IGNORE'; 
    121     while (accept(Remote, $daemon)) { 
     82 
     83    while (my $remote = $daemon->accept) { 
    12284        # TODO (Catalyst): get while ( my $remote = $daemon->accept ) to work 
    12385        delete $self->{_sigpipe}; 
    124         select Remote; 
    125  
    126         # Request data 
    127         Remote->blocking(1); 
    128  
    129         next unless my($method, $uri, $protocol) = $self->_parse_request_line(\*Remote); 
     86 
     87        next unless my($method, $uri, $protocol) = $self->_parse_request_line($remote); 
    13088        unless (uc $method eq 'RESTART') { 
    13189            # Fork 
    13290            next if $self->fork && ($pid = fork); 
    133             $self->_handler($port, $method, $uri, $protocol); 
     91            $self->_handler($remote, $port, $method, $uri, $protocol); 
    13492            $daemon->close if defined $pid; 
    13593        } else { 
    136             my $sockdata = $self->_socket_data(\*Remote); 
     94            my $sockdata = $self->_socket_data($remote); 
    13795            my $ipaddr   = _inet_addr($sockdata->{peeraddr}); 
    13896            my $ready    = 0; 
     
    149107        exit if defined $pid; 
    150108    } continue { 
    151         close Remote; 
     109        close $remote; 
    152110    } 
    153111    $daemon->close; 
     
    163121 
    164122sub _handler { 
    165     my($self, $port, $method, $uri, $protocol) = @_; 
     123    my($self, $remote, $port, $method, $uri, $protocol) = @_; 
    166124 
    167125    # Ignore broken pipes as an HTTP server should 
    168     local $SIG{PIPE} = sub { $self->{_sigpipe} = 1; close Remote }; 
    169  
    170     local *STDIN  = \*Remote; 
    171     local *STDOUT = \*Remote; 
     126    local $SIG{PIPE} = sub { $self->{_sigpipe} = 1; close $remote }; 
    172127 
    173128    # We better be careful and just use 1.0 
    174129    $protocol = '1.0'; 
    175130 
    176     my $sockdata    = $self->_socket_data(\*Remote); 
     131    my $sockdata    = $self->_socket_data($remote); 
    177132    my %copy_of_env = %ENV; 
    178133 
    179134    my $sel = IO::Select->new; 
    180     $sel->add(\*STDIN); 
     135    $sel->add($remote); 
     136 
     137    $remote->autoflush(1); 
    181138 
    182139    while (1) { 
     140        # FIXME refactor an HTTP push parser 
    183141        my($path, $query_string) = split /\?/, $uri, 2; 
    184142 
    185         # Initialize CGI environment 
    186         local %ENV = ( 
     143        my %env = ( 
    187144            PATH_INFO       => $path         || '', 
    188145            QUERY_STRING    => $query_string || '', 
     
    193150            SERVER_PORT     => $port, 
    194151            SERVER_PROTOCOL => "HTTP/$protocol", 
    195             %copy_of_env, 
    196152        ); 
    197153 
     154        my $headers; 
     155 
    198156        # Parse headers 
     157        # taken from HTTP::Message, which is unfortunately not really reusable 
    199158        if ($protocol >= 1) { 
    200             while (1) { 
    201                 my $line = $self->_get_line(\*STDIN); 
    202                 last if $line eq ''; 
    203                 next unless my ( $name, $value ) = $line =~ m/\A(\w(?:-?\w+)*):\s(.+)\z/; 
    204  
    205                 $name = uc $name; 
    206                 $name = 'COOKIE' if $name eq 'COOKIES'; 
    207                 $name =~ tr/-/_/; 
    208                 $name = 'HTTP_' . $name unless $name =~ m/\A(?:CONTENT_(?:LENGTH|TYPE)|COOKIE)\z/; 
    209                 if (exists $ENV{$name}) { 
    210                     $ENV{$name} .= "; $value"; 
     159            my @hdr; 
     160            while ( length(my $line = $self->_get_line($remote)) ) { 
     161                if ($line =~ s/^([^\s:]+)[ \t]*: ?(.*)//) { 
     162                    push(@hdr, $1, $2); 
     163                } 
     164                elsif (@hdr && $line =~ s/^([ \t].*)//) { 
     165                    $hdr[-1] .= "\n$1"; 
    211166                } else { 
    212                     $ENV{$name} = $value; 
     167                    last; 
    213168                } 
    214169            } 
     170            $headers = HTTP::Headers->new(@hdr); 
     171        } else { 
     172            $headers = HTTP::Headers->new; 
    215173        } 
     174 
    216175        # Pass flow control to HTTP::Engine 
    217         $self->handle_request; 
    218  
    219         my $connection = lc $ENV{HTTP_CONNECTION}; 
     176        $self->handle_request( 
     177            uri            => URI::WithBase->new($uri), 
     178            headers        => $headers, 
     179            method         => $method, 
     180            address        => $sockdata->{peeraddr}, 
     181            port           => $port, 
     182            protocol       => "HTTP/$protocol", 
     183            user           => undef, 
     184            https_info     => undef, 
     185            _connection => { 
     186                handle => $remote, 
     187                env    => {},         # no more env than what we provide 
     188            }, 
     189        ); 
     190 
     191        my $connection = $headers->header("Connection"); 
     192 
    220193        last 
    221194          unless $self->keepalive 
     
    224197          && $sel->can_read(5); 
    225198 
    226         last unless ($method, $uri, $protocol) = $self->_parse_request_line(\*STDIN, 1); 
    227     } 
    228  
    229     sysread(Remote, my $buf, 4096) if $sel->can_read(0); # IE bk 
    230     close Remote; 
     199        last unless ($method, $uri, $protocol) = $self->_parse_request_line($remote, 1); 
     200    } 
     201 
     202    $self->request_builder->_io_read($remote, my $buf, 4096) if $sel->can_read(0); # IE bk 
     203    close $remote; 
    231204} 
    232205 
     
    254227 
    255228    my $data = { 
    256         peername => gethostbyaddr($iaddr, AF_INET) || "localhost", 
    257229        peeraddr => inet_ntoa($iaddr) || "127.0.0.1", 
    258         localname => gethostbyaddr($localiaddr, AF_INET) || "localhost", 
    259230        localaddr => inet_ntoa($localiaddr) || "127.0.0.1", 
    260231    }; 
     
    266237    my($self, $handle) = @_; 
    267238 
     239    # FIXME use bufferred but nonblocking IO? this is a lot of calls =( 
    268240    my $line = ''; 
    269     while (sysread($handle, my $byte, 1)) { 
     241    while ($self->request_builder->_io_read($handle, my $byte, 1)) { 
    270242        last if $byte eq "\012";    # eol 
    271243        $line .= $byte; 
    272244    } 
    273     1 while $line =~ s/\s\z//; 
     245 
     246    # strip \r, \n was already stripped 
     247    $line =~ s/\015$//s; 
    274248 
    275249    $line; 
  • lang/perl/HTTP-Engine/branches/lazy_request/lib/HTTP/Engine/Request.pm

    r13418 r13439  
    1717    } 
    1818} 
     19 
     20has _connection => ( 
     21    is => "ro", 
     22    lazy_build => 1, 
     23); 
     24 
     25sub _build__request_state { 
     26    my $self = shift; 
     27    $self->request_builder->_build_request_state($self); 
     28} 
     29 
     30has "_read_state" => ( 
     31    is => "rw", 
     32    lazy_build => 1, 
     33); 
     34 
     35sub _build__read_state { 
     36    my $self = shift; 
     37    $self->request_builder->_build_read_state($self); 
     38} 
     39 
     40 
    1941has request_builder => ( 
    2042    does => "HTTP::Engine::Role::RequestBuilder", 
     
    143165    my $self = shift; 
    144166    $self->request_builder->_build_hostname; 
    145 } 
    146  
    147 has "_read_state" => ( 
    148     is => "rw", 
    149     lazy_build => 1, 
    150 ); 
    151  
    152 sub _build__read_state { 
    153     my $self = shift; 
    154     $self->request_builder->_build_read_state($self); 
    155167} 
    156168 
  • lang/perl/HTTP-Engine/branches/lazy_request/lib/HTTP/Engine/RequestBuilder.pm

    r13418 r13439  
    1919); 
    2020 
    21 has read_length => ( 
    22     is  => 'rw', 
    23     isa => 'Int', 
    24 ); 
    25  
    26 has read_position => ( 
    27     is  => 'rw', 
    28     isa => 'Int', 
    29 ); 
    30  
    3121no Moose; 
     22 
     23sub _build_connection { 
     24    warn "Building default request state"; 
     25 
     26    return { 
     27        env    => \%ENV, 
     28        handle => \*STDIN, 
     29    } 
     30} 
    3231 
    3332sub _build_connection_info { 
    3433    my($self, $req) = @_; 
    3534 
     35    warn "building connection info"; 
     36 
     37    my $env = $self->_connection->{env}; 
     38 
    3639    return { 
    37         address    => $ENV{REMOTE_ADDR}, 
    38         protocol   => $ENV{SERVER_PROTOCOL}, 
    39         method     => $ENV{REQUEST_METHOD}, 
    40         port       => $ENV{SERVER_PORT}, 
    41         user       => $ENV{REMOTE_USER}, 
    42         https_info => $ENV{HTTPS}, 
     40        address    => $env->{REMOTE_ADDR}, 
     41        protocol   => $env->{SERVER_PROTOCOL}, 
     42        method     => $env->{REQUEST_METHOD}, 
     43        port       => $env->{SERVER_PORT}, 
     44        user       => $env->{REMOTE_USER}, 
     45        https_info => $env->{HTTPS}, 
    4346    } 
    4447} 
     
    4649sub _build_headers { 
    4750    my ($self, $req) = @_; 
     51 
     52    my $env = $req->_connection->{env}; 
    4853 
    4954    HTTP::Headers->new( 
    5055        map { 
    5156            (my $field = $_) =~ s/^HTTPS?_//; 
    52             ( $field => $ENV{$_} ); 
     57            ( $field => $env->{$_} ); 
    5358        } 
    54         grep { /^(?:HTTP|CONTENT|COOKIE)/i } keys %ENV  
     59        grep { /^(?:HTTP|CONTENT|COOKIE)/i } keys %$env 
    5560    ); 
    5661} 
     
    5863sub _build_hostname { 
    5964    my ( $self, $req ) = @_; 
    60     $ENV{REMOTE_HOST} || $self->_resolve_hostname($req); 
     65    $req->_connection->{env}{REMOTE_HOST} || $self->_resolve_hostname($req); 
    6166} 
    6267 
     
    6469    my($self, $req) = @_; 
    6570 
     71    my $env = $req->_connection->{env}; 
     72 
    6673    my $scheme = $req->secure ? 'https' : 'http'; 
    67     my $host   = $ENV{HTTP_HOST}   || $ENV{SERVER_NAME}; 
    68     my $port   = $ENV{SERVER_PORT} || ( $req->secure ? 443 : 80 ); 
     74    my $host   = $env->{HTTP_HOST}   || $env->{SERVER_NAME}; 
     75    my $port   = $env->{SERVER_PORT} || ( $req->secure ? 443 : 80 ); 
    6976 
    7077    my $base_path; 
    71     if (exists $ENV{REDIRECT_URL}) { 
    72         $base_path = $ENV{REDIRECT_URL}; 
    73         $base_path =~ s/$ENV{PATH_INFO}$//; 
     78    if (exists $env->{REDIRECT_URL}) { 
     79        $base_path = $env->{REDIRECT_URL}; 
     80        $base_path =~ s/$env->{PATH_INFO}$//; 
    7481    } else { 
    75         $base_path = $ENV{SCRIPT_NAME} || '/'; 
    76     } 
    77  
    78     my $path = $base_path . ($ENV{PATH_INFO} || ''); 
     82        $base_path = $env->{SCRIPT_NAME} || '/'; 
     83    } 
     84 
     85    my $path = $base_path . ($env->{PATH_INFO} || ''); 
    7986    $path =~ s{^/+}{}; 
    8087 
     
    8491    $uri->port($port); 
    8592    $uri->path($path); 
    86     $uri->query($ENV{QUERY_STRING}) if $ENV{QUERY_STRING}; 
     93    $uri->query($env->{QUERY_STRING}) if $env->{QUERY_STRING}; 
    8794 
    8895    # sanitize the URI 
     
    101108    my($self, $req) = @_; 
    102109 
     110    use Data::Dumper; 
     111    warn Dumper($req->headers); 
     112 
    103113    my $length = $req->header('Content-Length') || 0; 
    104114    my $type   = $req->header('Content-Type'); 
     
    107117    $body->{tmpdir} = $self->upload_tmp if $self->upload_tmp; 
    108118 
    109     return { 
    110         handle         => *STDIN, 
     119    return $self->_read_init({ 
     120        handle         => $req->_connection->{handle}, 
    111121        content_length => $length, 
    112122        read_position  => 0, 
     
    115125            http_body     => $body, 
    116126        }, 
    117     }; 
     127    }); 
    118128} 
    119129 
     
    121131    my ( $self, $req ) = @_; 
    122132 
     133    warn "constructing body"; 
    123134    $self->_read_to_end($req->_read_state); 
    124135 
     
    129140    my ( $self, $req ) = @_; 
    130141 
     142    warn "constructing raw"; 
    131143    $self->_read_to_end($req->_read_state); 
    132144 
  • lang/perl/HTTP-Engine/branches/lazy_request/lib/HTTP/Engine/RequestProcessor.pm

    r13420 r13439  
    5757my $rp; 
    5858sub handle_request { 
    59     my $self = shift; 
     59    my ( $self, @args ) = @_; 
    6060 
    6161    my $context = $self->context_class->new( 
    62         req    => $self->request_class->new( request_builder => $self->request_builder ), 
    63         res    => $self->response_class->new(), 
     62        req => $self->request_class->new( 
     63            request_builder => $self->request_builder, 
     64            @args, 
     65        ), 
     66        res => $self->response_class->new(@args), 
     67        @args, 
    6468    ); 
    6569 
     
    7377        print STDERR $e; 
    7478    } 
     79 
    7580    $self->response_writer->finalize($context); 
    7681 
  • lang/perl/HTTP-Engine/branches/lazy_request/lib/HTTP/Engine/ResponseWriter.pm

    r11743 r13439  
    2323sub finalize { 
    2424    my($self, $c) = @_; 
     25 
     26    local *STDOUT = $c->req->_connection->{handle}; 
    2527    croak "argument missing" unless $c; 
    2628 
  • lang/perl/HTTP-Engine/branches/lazy_request/lib/HTTP/Engine/Role/Interface.pm

    r13420 r13439  
    1919 
    2020sub request_processor_traits { 
    21     return; 
     21    my $self = shift; 
     22    $self->_default_trait("RequestProcessor"); 
    2223} 
    2324 
     
    4546 
    4647sub request_builder_traits { 
    47     return; 
     48    my $self = shift; 
     49    $self->_default_trait("RequestBuilder"); 
    4850} 
    4951 
     
    6668 
    6769sub response_writer_traits { 
    68     return; 
     70    my $self = shift; 
     71    $self->_default_trait("ResponseWriter"); 
    6972} 
    7073 
     
    8487 
    8588 
     89sub _default_trait { 
     90    my ( $self, $category ) = @_; 
    8691 
     92    my $name = join( "::", $self->meta->name, $category ); 
     93 
     94    my $e; 
     95 
     96    # don't overwrite external $@ 
     97    { 
     98        local $@; 
     99        if ( eval { Class::MOP::load_class($name) } ) { 
     100            return $name; 
     101        } else { 
     102            ( my $file = "$name.pm" ) =~ s{::}{/}g; 
     103            if ( $@ =~ /Can't locate \Q$file\E in \@INC/ ) { 
     104                return; 
     105            } else { 
     106                $e = $@; 
     107            } 
     108        } 
     109    } 
     110 
     111    die $e; 
     112} 
    87113 
    88114my %anon_classes; 
     
    117143    Moose::Util::apply_all_roles( $anon->name, @roles ); 
    118144 
    119     return $anon->name; 
     145    return $anon; 
    120146} 
    121147 
  • lang/perl/HTTP-Engine/branches/lazy_request/lib/HTTP/Engine/Role/RequestBuilder/ReadBody.pm

    r13418 r13439  
    77 
    88sub _read_init { 
     9    my ( $self, $read_state ) = @_; 
     10    warn "read init"; 
     11    return $read_state; 
     12} 
     13 
     14sub _read_start { 
    915    my ( $self, $state ) = @_; 
    10     $state->{initialized} = 1; 
     16    warn "read start"; 
     17    $state->{started} = 1; 
    1118} 
    1219 
     
    1522 
    1623    my $content_length = $state->{content_length}; 
     24 
     25    warn "reading to end ($content_length)"; 
    1726 
    1827    if ($content_length > 0) { 
     
    3039        } 
    3140    } 
     41 
     42    warn "finished reading"; 
    3243} 
    3344 
     
    4253sub _read { 
    4354    my ($self, $state, $maxlength) = @_; 
     55 
     56    warn "reading"; 
    4457     
    45     $self->_read_init($state) unless $state->{initialized}; 
     58    $self->_read_start($state) unless $state->{started}; 
    4659 
    4760    my ( $length, $pos ) = @{$state}{qw(content_length read_position)}; 
     
    7386    my $handle = $state->{handle}; 
    7487 
     88    $self->_io_read( $handle, @_ ); 
     89} 
     90 
     91sub _io_read { 
     92    my ( $self, $handle ) = ( shift, shift ); 
     93 
    7594    if (blessed($handle)) { 
    76         return $handle->sysread(@_); 
     95        return $handle->read(@_); 
    7796    } else { 
    78         return sysread $handle, $_[0], $_[1], $_[2]; 
     97        return read $handle, $_[0], $_[1], $_[2]; 
    7998    } 
    8099}