iic has asked for the wisdom of the Perl Monks concerning the following question:

I often read the a header by using <$httpsocket> for simple
HTTP tasks.
But now I find I have a severe fault:
If somebody intentionally send me a line without line-end
sign "\012",as,
print $remote "GET $document HTTP/1.0";,
then the <> statement in my script have to be hang up to
wait for "\012".It's not my expectancy.
I hope to analyze the header line by line by myself.
Is there any other approach to manage it.
Can you help me to solve the problem?Thanks.

Replies are listed 'Best First'.
Re: about read HTTP header.
by takshaka (Friar) on Jun 29, 2000 at 11:54 UTC
    Use sysread and alarm to time out the client if necesary. The example below is pretty much straight from the alarm entry in perlfunc.
    #!/usr/bin/perl -w use strict; use IO::Socket; my $server = IO::Socket::INET->new(LocalPort => 6969, Type => SOCK_STREAM, Proto => 'tcp', Reuse => 1, Listen => 10, ) or die "Can't create listener socket: $!\n"; while ( my $client = $server->accept() ) { my ($data, $buf); my $timeout = 10; eval { local $SIG{ALRM} = sub { die "alarm\n" }; alarm $timeout; while (sysread $client, $buf, 1024) { $data .= $buf; last if $data =~ /(?:\015?\012){2}/; # reset timeout if we read data alarm $timeout; } alarm 0; }; if ($@) { die unless $@ eq "alarm\n"; } # do stuff with $data print ">>$data<<\n"; }
    I imagine HTTP::Daemon would do all this stuff for you.

    Of course, a line without the \015\012 (or at least \012) terminator isn't a valid HTTP request, so you shouldn't bother looking at it.

Re: about read HTTP header.
by pemungkah (Priest) on Jun 29, 2000 at 18:54 UTC
    You may also want to look at the select() call, which will let you know when there is input on a filehandle, how much, and will also handle the wait as well.
    $my_handle = "";
    vec ($my_handle, fileno($httpsocket), 1) = 1;
    $timeout = 0.5; # half-second
    
    $nfound = select($test_handle=$my_handle, undef, undef, $timeout);
    if (vec($test_handle, fileno($httpsocket),1)) {
        sysread($hhtpsocket, $buffer, $nfound);
    }
    
    This uses a lot of messy bitmasks, but you'll need to do it this way if you're using standard filehandles. If you're using IO::Socket, you can instead use IO::Select, which handles all the ick under the covers:
    use IO::Select;
    
    $select = IO::Select->new();
    $select->add($httpsocket);  # and as many more as you like
    
    $timeout =  0.5;
    @read_from = $select->can_read($timeout);
    foreach my $socket (@read_from) {
       # Read the socket
    }
    
    It seems that there's no simple call to get the length, though. Again, as takshaka says, if there's no line terminator, it's not valid.
RE: about read HTTP header.
by merlyn (Sage) on Jun 29, 2000 at 19:29 UTC