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

hi all, I am trying to write a simple perl http server to polish my perl skills.
Below is my code, the first time I access to localhost:8090, it can display the page. However, when I refresh the page, nothing produces in the browser, what is the problem of my code?
use feature ':5.10'; use IO::Socket; use Carp; #use URI::Escape; use Readonly; $|++; Readonly::Scalar my $port => '8090'; my $socket = IO::Socket::INET->new( Listen => 5, LocalAddr => 'localhost', LocalPort => $port, Reuse => 1, Proto => 'tcp', ) or croak "Can not bind port: $!"; my $quit = 0; print "Server started at $port\n"; while (!$quit) { local $SIG{PIPE} = 'IGNORE'; while (my $session = $socket->accept) { my $chunk = ''; my $n = 0; my @headers; my ($method, $uri, $protocol); while (sysread($session, my $buffer, 1)) { last if $buffer eq "\n"; $chunk .= $buffer; } $_ = $chunk; m/^(\w+)\s+(\S+)(?:\s+(\S+))?\r?$/; $method = $1 || ''; $uri = $2 || ''; $protocol = $3 || ''; my $bad_request_doc = join "", <DATA>; return unless $method =~ /^(?:POST|GET|DELETE|PUT|HEAD)$/; $chunk = ''; while (sysread($session, my $buffer, 1)) { if ($buffer eq "\n") { $chunk =~ s/[\r\l\n\s]+$//; if ($chunk =~ /^([^()<>\@,;:\\"\/\[\]?={} \t]+):\s*(.* +)/i) { push @headers, $1 => $2; } last if ($chunk =~ /^$/); $chunk = ''; } else { $chunk .= $buffer; } } print $session "HTTP/1.0 200 OK\r\n"; print $session "Content-Type: text/html\r\nContent-Length: ", length($bad_request_doc), "\r\n\r\n", $bad_request_doc,"\n"; close $session; } } __DATA__ <html> <head> <title>Bad Request</title> </head> <body> <h1>Bad Request</h1> <p>Your browser sent a request which this web server could not grok.</p> </body> </html>

Replies are listed 'Best First'.
Re: Http server problem
by jethro (Monsignor) on Sep 15, 2009 at 13:25 UTC

    Please use warnings and strict, the best way to polish your perl skills ;-)

    The problem ist that you try to reread your __DATA__ section every time you get a request, but the respective "file pointer" is at EOF after the first time. I don't know if the pointer can be reset (look up the docu if you want to), but it is easier to just move the line where you initialize $bad_request_doc to somewhere before the main loop

      Thanks, jethro.
      I do use "use warnings" and "use strict", just did not paste here :).
Re: Http server problem
by eric256 (Parson) on Sep 15, 2009 at 14:38 UTC

    I'm not sure how i feel about this code. I'm all about reuse and everything and I don't think its really an issue, but you might at least want to mention HTTP::Server::Simple since you cut and paste this code directly out of it.

    It is probably also worth mentioning that you don't realy need the feature line or the read only stuff since there is no reason to make the port read only. It just makes it difficult to run this code on a production machine.

    Eric Hodges
      Sorry, I just wanted to learn how to write http-servers so I digged into the code of "HTTP::Server::Simple", I should have mentioned that.
      It is just for personal practice, not for production use, but thanks the suggestions anyway.