Código Completo del Servidor HTTP

pp2@nereida:~/src/perl/NET_SERVER$ cat -n httpd
  1  #!/usr/bin/perl
  2  use strict;
  3  use warnings;
  4  use base qw(Net::Server::PreFork);
  5  use MIME::Types;
  6  use HTTP::Status;
  7  use HTTP::Request;
  8
  9  ### run the server
 10  __PACKAGE__->run;
 11  exit;
 12
 13  ###----------------------------------------------------------------###
 14
 15  #my $LOG;
 16
 17  ### set up some server parameters
 18  sub configure_hook {
 19    my $self = shift;
 20
 21    my $root = $self->{server_root} = "/home/pp2/public_html";
 22
 23    $self->{server}->{port}     = '*:8080';   # port and addr to bind
 24  # $self->{server}->{user}     = 'nobody'; # user to run as
 25  # $self->{server}->{group}    = 'nobody'; # group to run as
 26  # $self->{server}->{setsid}   = 1;        # daemonize
 27  # $self->{server}->{pid_file}   = "$root/server.pid";        # pid file
 28  # $self->{server}->{log_file} = "$root/server.log";
 29
 30
 31    $self->{document_root} = "$root/";
 32  # $self->{access_log}    = "$root/access.log";
 33  # $self->{error_log}     = "$root/error.log";
 34
 35    $self->{default_index} = [ qw(index.html index.htm main.htm) ];
 36
 37  }
 38
 39  sub post_configure_hook {
 40  use vars qw{$CRLF};
 41  $CRLF = "\015\012";
 42
 43    my $self = shift;
 44
 45  # open(STDERR, ">>". $self->{error_log})  || die "Couldn't open STDERR: $!";
 46  # open($LOG, ">>". $self->{access_log}) || die "Couldn't open log file: $!";
 47  # autoflush $LOG 1;
 48  # autoflush STDERR 1;
 49  }
 50
 51  ### process the request
 52  sub process_request {
 53    my $self = shift;
 54
 55    local $/ = "$CRLF$CRLF";
 56    my $request = <STDIN>;      # read the request header
 57  # warn "header:\n$request\n";
 58
 59    my $r = HTTP::Request->parse( $request );
 60    my $method = $r->method; # GET | HEAD | ...
 61    my $url = $r->uri;
 62
 63    warn join(" ", time, $method, "$url")."\n";
 64
 65    ### do we support the type
 66    if ($method !~ /GET|HEAD/) {
 67      return $self->error(RC_BAD_REQUEST(), "Unsupported Method");
 68    }
 69
 70    ### clean up uri
 71    my $path = URI::Escape::uri_unescape($url);
 72    $path =~ s/\?.*$//;                            # ignore query
 73    $path =~ s/\#.*$//;                            # get rid of fragment
 74
 75    ### at this point the path should be ready to use
 76    $path = "$self->{document_root}$path";
 77
 78    ### see if there's an index page
 79    if (-d $path) {
 80      foreach (@{ $self->{default_index} }){
 81        if (-e "$path/$_") {
 82          return redirect("$url/$_");
 83        }
 84      }
 85    }
 86
 87    ### error 404
 88    return $self->error(RC_NOT_FOUND(), "file not found") unless -e $path;
 89
 90    ### spit it out
 91    open(my $fh, "<$path") || return $self->error(RC_INTERNAL_SERVER_ERROR(), "Can't open file [$!]");
 92    my $length = (stat($fh))[7];        # file size
 93
 94    my $mimeobj = MIME::Types->new->mimeTypeOf($path);
 95    my $type = $mimeobj->type if defined($mimeobj);
 96
 97    # print the header
 98    print STDOUT "HTTP/1.0 ".RC_OK." OK$CRLF";
 99    print STDOUT "Content-length: $length$CRLF";
100    print STDOUT "Content-type: $type; charset=utf-8";
101    print STDOUT "$CRLF$CRLF";
102
103    return unless $method eq 'GET';
104
105    # print the content
106    my $buffer;
107    while ( read($fh,$buffer,1024) ) {
108      print STDOUT $buffer;
109    }
110    close $fh;
111  }
112
113  sub error {
114    my ($self, $code, $message) = @_;
115    my $status_message = status_message($code);
116
117    print STDOUT "HTTP/1.0 $code Bad request$CRLF";
118    print STDOUT "Content-type: text/html$CRLF$CRLF";
119    print STDOUT <<"END";
120  <HTML>
121  <HEAD><TITLE>$code Bad Request</TITLE></HEAD>
122  <BODY><H1>$status_message</H1>
123  <P>$message</P>
124  </BODY>
125  </HTML>
126  END
127  }
128
129  sub redirect {
130    my ($url) = @_;
131
132    my $moved_to = "$url";
133    print STDOUT "HTTP/1.0 301 Moved permanently$CRLF";
134    print STDOUT "Location: $moved_to$CRLF";
135    print STDOUT "Content-type: text/html$CRLF$CRLF";
136    print STDOUT <<"END";
137  <HTML>
138  <HEAD><TITLE>301 Moved</TITLE></HEAD>
139  <BODY><H1>Moved</H1>
140  <P>The requested document has moved
141  <A HREF="$moved_to">here</A>.</P>
142  </BODY>
143  </HTML>
144  END
145  }
146
147  1;

Ejercicio 14.3.1  

Casiano Rodríguez León
2010-03-22
es/">ullpcgull
Sig: Como Escribir un Servidor Sup: El Módulo Net::Server Ant: Código Completo del Servidor
Casiano Rodríguez León
2010-05-05
$fh; 26 return $pid = $$; 27 } 28 29 sub become_daemon { 30 chdir '/'; # change working directory 31 umask(0); # forget file mode creation mask 32 $ENV{PATH} = '/bin:/sbin:/usr/bin:/usr/sbin'; 33 $SIG{CHLD} = \&reap_child; 34 return $$; 35 } 36 37 sub getpidfilename { 38 my $basename = basename($0,'.pl'); 39 return PIDPATH . "/$basename.pid"; 40 } 41 42 sub open_pid_file { 43 my $file = shift; 44 if (-e $file) { # oops. pid file already exists 45 my $fh = IO::File->new($file) || return; 46 my $pid = <$fh>; 47 if ($pid && $pid =~ /^\d+$/) { 48 croak "Server already running with PID $pid" if kill 0 => $pid; 49 } 50 else { 51 $pid = "unknown"; 52 } 53 cluck "Removing PID file for defunct server process $pid.\n"; 54 croak"Can't unlink PID file $file" unless -w $file && unlink $file; 55 } 56 return IO::File->new($file,O_WRONLY|O_CREAT|O_EXCL,0644) 57 or die "Can't create $file: $!\n"; 58 } 59 60 sub reap_child { 61 do { } while waitpid(-1,WNOHANG) > 0; 62 } 63 64 sub launch_child { 65 my $callback = shift; 66 my $home = shift; 67 my $signals = POSIX::SigSet->new(SIGINT,SIGCHLD,SIGTERM,SIGHUP); 68 sigprocmask(SIG_BLOCK,$signals); # block inconvenient signals 69 die("Can't fork: $!") unless defined (my $child = fork()); 70 if ($child) { 71 $CHILDREN{$child} = $callback || 1; 72 } else { 73 $SIG{HUP} = $SIG{INT} = $SIG{CHLD} = $SIG{TERM} = 'DEFAULT'; 74 prepare_child($home); 75 } 76 sigprocmask(SIG_UNBLOCK,$signals); # unblock signals 77 return $child; 78 } 79 80 sub prepare_child { 81 my $home = shift; 82 if ($home) { 83 chdir $home || croak "chdir(): $!"; 84 } 85 } 86 87 88 sub kill_children { 89 my $n = kill TERM => keys %CHILDREN; 90 # wait until all the children die 91 wait for 1..$n 92 } 93 94 95 END { unlink $pidfile if defined $pid and $$ == $pid } 96 97 1;



Subsecciones
Casiano Rodríguez León
2011-03-22
cciones
Casiano Rodríguez León
2011-06-03