1 package LWP::Protocol::http10;
6 require HTTP::Response;
11 use vars qw(@ISA @EXTRA_SOCK_OPTS);
13 require LWP::Protocol;
14 @ISA = qw(LWP::Protocol);
16 my $CRLF = "\015\012"; # how lines should be terminated;
17 # "\r\n" is not correct on all systems, for
18 # instance MacPerl defines it to "\012\015"
22 my($self, $host, $port, $timeout) = @_;
24 local($^W) = 0; # IO::Socket::INET can be noisy
25 my $sock = IO::Socket::INET->new(PeerAddr => $host,
29 $self->_extra_sock_opts($host, $port),
32 # IO::Socket::INET leaves additional error messages in $@
34 die "Can't connect to $host:$port ($@)";
39 sub _extra_sock_opts # to be overridden by subclass
41 return @EXTRA_SOCK_OPTS;
47 #my($self, $req, $sock) = @_;
52 my($self, $res, $sock) = @_;
53 if (defined(my $peerhost = $sock->peerhost)) {
54 $res->header("Client-Peer" => "$peerhost:" . $sock->peerport);
60 my($self, $h, $url, $proxy) = @_;
62 $h->remove_header('Connection'); # need support here to be useful
64 # HTTP/1.1 will require us to send the 'Host' header, so we might
66 my $hhost = $url->authority;
67 if ($hhost =~ s/^([^\@]*)\@//) { # get rid of potential "user:pass@"
68 # add authorization header if we need them. HTTP URLs do
69 # not really support specification of user and password, but
71 if (defined($1) && not $h->header('Authorization')) {
73 $h->authorization_basic(map URI::Escape::uri_unescape($_),
77 $h->init_header('Host' => $hhost);
80 # Check the proxy URI's userinfo() for proxy credentials
81 # export http_proxy="http://proxyuser:proxypass@proxyhost:port"
82 my $p_auth = $proxy->userinfo();
85 $h->proxy_authorization_basic(map URI::Escape::uri_unescape($_),
86 split(":", $p_auth, 2))
94 my($self, $request, $proxy, $arg, $size, $timeout) = @_;
95 LWP::Debug::trace('()');
100 my $method = $request->method;
101 unless ($method =~ /^[A-Za-z0-9_!\#\$%&\'*+\-.^\`|~]+$/) { # HTTP token
102 return new HTTP::Response &HTTP::Status::RC_BAD_REQUEST,
103 'Library does not allow method ' .
104 "$method for 'http:' URLs";
107 my $url = $request->url;
108 my($host, $port, $fullpath);
110 # Check if we're proxy'ing
111 if (defined $proxy) {
112 # $proxy is an URL to an HTTP server which will proxy this request
113 $host = $proxy->host;
114 $port = $proxy->port;
115 $fullpath = $method eq "CONNECT" ?
116 ($url->host . ":" . $url->port) :
122 $fullpath = $url->path_query;
123 $fullpath = "/" unless length $fullpath;
126 # connect to remote site
127 my $socket = $self->_new_socket($host, $port, $timeout);
128 $self->_check_sock($request, $socket);
130 my $sel = IO::Select->new($socket) if $timeout;
132 my $request_line = "$method $fullpath HTTP/1.0$CRLF";
134 my $h = $request->headers->clone;
135 my $cont_ref = $request->content_ref;
136 $cont_ref = $$cont_ref if ref($$cont_ref);
137 my $ctype = ref($cont_ref);
139 # If we're sending content we *have* to specify a content length
140 # otherwise the server won't know a messagebody is coming.
141 if ($ctype eq 'CODE') {
142 die 'No Content-Length header for request with dynamic content'
143 unless defined($h->header('Content-Length')) ||
144 $h->content_type =~ /^multipart\//;
145 # For HTTP/1.1 we could have used chunked transfer encoding...
148 $h->header('Content-Length' => length $$cont_ref)
149 if defined($$cont_ref) && length($$cont_ref);
152 $self->_fixup_header($h, $url, $proxy);
154 my $buf = $request_line . $h->as_string($CRLF) . $CRLF;
155 my $n; # used for return value from syswrite/sysread
160 $length = length($buf);
162 while ( $offset < $length ) {
163 die "write timeout" if $timeout && !$sel->can_write($timeout);
164 $n = $socket->syswrite($buf, $length-$offset, $offset );
165 die $! unless defined($n);
168 LWP::Debug::conns($buf);
170 if ($ctype eq 'CODE') {
171 while ( ($buf = &$cont_ref()), defined($buf) && length($buf)) {
173 $length = length($buf);
175 while ( $offset < $length ) {
176 die "write timeout" if $timeout && !$sel->can_write($timeout);
177 $n = $socket->syswrite($buf, $length-$offset, $offset );
178 die $! unless defined($n);
181 LWP::Debug::conns($buf);
184 elsif (defined($$cont_ref) && length($$cont_ref)) {
185 # syswrite $$cont_ref
186 $length = length($$cont_ref);
188 while ( $offset < $length ) {
189 die "write timeout" if $timeout && !$sel->can_write($timeout);
190 $n = $socket->syswrite($$cont_ref, $length-$offset, $offset );
191 die $! unless defined($n);
194 LWP::Debug::conns($$cont_ref);
197 # read response line from server
198 LWP::Debug::debug('reading response');
203 # Inside this loop we will read the response line and all headers
204 # found in the response.
206 die "read timeout" if $timeout && !$sel->can_read($timeout);
207 $n = $socket->sysread($buf, $size, length($buf));
208 die $! unless defined($n);
209 die "unexpected EOF before status line seen" unless $n;
210 LWP::Debug::conns($buf);
212 if ($buf =~ s/^(HTTP\/\d+\.\d+)[ \t]+(\d+)[ \t]*([^\012]*)\012//) {
213 # HTTP/1.0 response or better
214 my($ver,$code,$msg) = ($1, $2, $3);
216 LWP::Debug::debug("$ver $code $msg");
217 $response = HTTP::Response->new($code, $msg);
218 $response->protocol($ver);
220 # ensure that we have read all headers. The headers will be
221 # terminated by two blank lines
222 until ($buf =~ /^\015?\012/ || $buf =~ /\015?\012\015?\012/) {
223 # must read more if we can...
224 LWP::Debug::debug("need more header data");
225 die "read timeout" if $timeout && !$sel->can_read($timeout);
226 my $old_len = length($buf);
227 $n = $socket->sysread($buf, $size, $old_len);
228 die $! unless defined($n);
229 die "unexpected EOF before all headers seen" unless $n;
230 LWP::Debug::conns(substr($buf, $old_len));
233 # now we start parsing the headers. The strategy is to
234 # remove one line at a time from the beginning of the header
237 while ($buf =~ s/([^\012]*)\012//) {
240 # if we need to restore as content when illegal headers
242 my $save = "$line\012";
245 last unless length $line;
247 if ($line =~ /^([a-zA-Z0-9_\-.]+)\s*:\s*(.*)/) {
248 $response->push_header($key, $val) if $key;
249 ($key, $val) = ($1, $2);
251 elsif ($line =~ /^\s+(.*)/ && $key) {
255 $response->push_header("Client-Bad-Header-Line" => $line);
258 $response->push_header($key, $val) if $key;
262 elsif ((length($buf) >= 5 and $buf !~ /^HTTP\//) or
265 LWP::Debug::debug("HTTP/0.9 assume OK");
266 $response = HTTP::Response->new(&HTTP::Status::RC_OK, "OK");
267 $response->protocol('HTTP/0.9');
273 LWP::Debug::debug("need more status line data");
276 $response->request($request);
277 $self->_get_sock_info($response, $socket);
279 if ($method eq "CONNECT") {
280 $response->{client_socket} = $socket; # so it can be picked up
281 $response->content($buf); # in case we read more than the headers
285 my $usebuf = length($buf) > 0;
286 $response = $self->collect($arg, $response, sub {
291 die "read timeout" if $timeout && !$sel->can_read($timeout);
292 my $n = $socket->sysread($buf, $size);
293 die $! unless defined($n);
294 #LWP::Debug::conns($buf);