home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / perl_ste.zip / LWP / Protocol / http.pm < prev    next >
Text File  |  1997-08-05  |  5KB  |  196 lines

  1. #
  2. # $Id: http.pm,v 1.32 1997/08/05 14:24:21 aas Exp $
  3.  
  4. package LWP::Protocol::http;
  5.  
  6. require LWP::Debug;
  7. require LWP::Protocol;
  8. require LWP::Socket;
  9. require HTTP::Request;
  10. require HTTP::Response;
  11. require HTTP::Status;
  12.  
  13. use Carp ();
  14.  
  15. @ISA = qw(LWP::Protocol);
  16.  
  17. use strict;
  18.  
  19. my $httpversion  = 'HTTP/1.0';     # for requests
  20. my $endl         = "\015\012";     # how lines should be terminated;
  21.                    # "\r\n" is not correct on all systems, for
  22.                    # instance MacPerl defines it to "\012\015"
  23.  
  24. sub _new_socket
  25. {
  26.     LWP::Socket->new;
  27. }
  28.  
  29. sub request
  30. {
  31.     my($self, $request, $proxy, $arg, $size, $timeout) = @_;
  32.     LWP::Debug::trace('()');
  33.  
  34.     $size ||= 4096;
  35.  
  36.     # check method
  37.     my $method = $request->method;
  38.     unless ($method =~ /^[A-Za-z0-9_!#\$%&'*+\-.^`|~]+$/) {     # HTTP token
  39.     return new HTTP::Response &HTTP::Status::RC_BAD_REQUEST,
  40.                   'Library does not allow method ' .
  41.                   "$method for 'http:' URLs";
  42.     }
  43.  
  44.     my $url = $request->url;
  45.     my($host, $port, $fullpath);
  46.  
  47.     # Check if we're proxy'ing
  48.     if (defined $proxy) {
  49.     # $proxy is an URL to an HTTP server which will proxy this request
  50.     $host = $proxy->host;
  51.     $port = $proxy->port;
  52.     $fullpath = $url->as_string;
  53.     }
  54.     else {
  55.     $host = $url->host;
  56.     $port = $url->port;
  57.     $fullpath = $url->full_path;
  58.     }
  59.  
  60.     alarm($timeout) if $self->use_alarm and $timeout;
  61.  
  62.     # connect to remote site
  63.     my $socket = $self->_new_socket();
  64.     $socket->connect($host, $port);
  65.  
  66.     my $request_line = "$method $fullpath $httpversion$endl";
  67.  
  68.     # If we're sending content we *have* to specify a content length
  69.     # otherwise the server won't know a messagebody is coming.
  70.  
  71.     my $content = $request->content;
  72.  
  73.     # All this mess because we want to support content as both scalar,
  74.     # ref to scalar and ref to code.
  75.     my $contRef;
  76.     if (defined $content){
  77.     $contRef = ref($content) ? $content : \$content;
  78.     if (ref($contRef) eq 'SCALAR') {
  79.         $request->header('Content-Length', length $$contRef)
  80.           if length $$contRef;
  81.     } elsif (ref($contRef) eq 'CODE') {
  82.         Carp::croak('No Content-Length header for request with content')
  83.           unless $request->header('Content-Length');
  84.     } else {
  85.         Carp::croak("Illegal content in request ($content)");
  86.     }
  87.     }
  88.  
  89.     # HTTP/1.1 will require us to send the 'Host' header, so we might
  90.     # as well start now.
  91.     $request->header('Host', $url->netloc);
  92.  
  93.     $socket->write($request_line . $request->headers_as_string($endl) . $endl);
  94.     if (defined $content) {
  95.     if (ref($contRef) eq 'CODE') {
  96.         $socket->write($contRef, $timeout);
  97.     } else {
  98.         $socket->write($$contRef, $timeout);
  99.     }
  100.     }
  101.  
  102.     # read response line from server
  103.     LWP::Debug::debug('reading response');
  104.  
  105.     my $res = "";
  106.     my $buf = "";
  107.     my $response;
  108.  
  109.     # Inside this loop we will read the response line and all headers
  110.     # found in the response.
  111.     while ($socket->read(\$buf, undef, $timeout)) {
  112.     $res .= $buf;
  113.     if ($res =~ s/^(HTTP\/\d+\.\d+)[ \t]+(\d+)[ \t]*([^\012]*)\012//) {
  114.         # HTTP/1.0 response or better
  115.         my($ver,$code,$msg) = ($1, $2, $3);
  116.         $msg =~ s/\015$//;
  117.         LWP::Debug::debug("$ver $code $msg");
  118.         $response = HTTP::Response->new($code, $msg);
  119.         $response->protocol($ver);
  120.  
  121.         # ensure that we have read all headers.  The headers will be
  122.         # terminated by two blank lines
  123.         while ($res !~ /\015?\012\015?\012/) {
  124.         # must read more if we can...
  125.         LWP::Debug::debug("need more data for headers");
  126.         last unless $socket->read(\$buf, undef, $timeout);
  127.         $res .= $buf;
  128.         }
  129.  
  130.         # now we start parsing the headers.  The strategy is to
  131.         # remove one line at a time from the beginning of the header
  132.         # buffer ($res).
  133.         my($key, $val);
  134.         while ($res =~ s/([^\012]*)\012//) {
  135.         my $line = $1;
  136.  
  137.         # if we need to restore as content when illegal headers
  138.         # are found.
  139.         my $save = "$line\012"; 
  140.  
  141.         $line =~ s/\015$//;
  142.         last unless length $line;
  143.  
  144.         if ($line =~ /^([a-zA-Z0-9_\-]+)\s*:\s*(.*)/) {
  145.             $response->push_header($key, $val) if $key;
  146.             ($key, $val) = ($1, $2);
  147.         } elsif ($line =~ /^\s+(.*)/) {
  148.             unless ($key) {
  149.             LWP::Debug::debug("Illegal continuation header");
  150.             $res = "$save$res";
  151.             last;
  152.             }
  153.             $val .= " $1";
  154.         } else {
  155.             LWP::Debug::debug("Illegal header '$line'");
  156.             $res = "$save$res";
  157.             last;
  158.         }
  159.         }
  160.         $response->push_header($key, $val) if $key;
  161.         last;
  162.  
  163.     } elsif ((length($res) >= 5 and $res !~ /^HTTP\//) or
  164.          $res =~ /\012/ ) {
  165.         # HTTP/0.9 or worse
  166.         LWP::Debug::debug("HTTP/0.9 assume OK");
  167.         $response = HTTP::Response->new(&HTTP::Status::RC_OK, "OK");
  168.         $response->protocol('HTTP/0.9');
  169.         last;
  170.  
  171.     } else {
  172.         # need more data
  173.         LWP::Debug::debug("need more data to know which protocol");
  174.     }
  175.     };
  176.     die "Unexpected EOF" unless $response;
  177.  
  178.     $socket->pushback($res) if length $res;
  179.     $response->request($request);
  180.  
  181.     # need to read content
  182.     alarm($timeout) if $self->use_alarm and $timeout;
  183.  
  184.     $response = $self->collect($arg, $response, sub {
  185.     LWP::Debug::debug('Collecting');
  186.     my $content = '';
  187.     my $result = $socket->read(\$content, $size, $timeout);
  188.     return \$content;
  189.     } );
  190.     $socket = undef;  # close it
  191.  
  192.     $response;
  193. }
  194.  
  195. 1;
  196.