Файловый менеджер - Редактировать - /var/www/html/back/storage/app/public/17/f8lo32/perl5.zip
Назад
PK ! A�g? g? HTTP/Request/Common.pmnu �[��� package HTTP::Request::Common; use strict; use warnings; our $VERSION = '6.36'; our $DYNAMIC_FILE_UPLOAD ||= 0; # make it defined (don't know why) use Exporter 5.57 'import'; our @EXPORT =qw(GET HEAD PUT PATCH POST OPTIONS); our @EXPORT_OK = qw($DYNAMIC_FILE_UPLOAD DELETE); require HTTP::Request; use Carp(); use File::Spec; my $CRLF = "\015\012"; # "\r\n" is not portable sub GET { _simple_req('GET', @_); } sub HEAD { _simple_req('HEAD', @_); } sub DELETE { _simple_req('DELETE', @_); } sub PATCH { request_type_with_data('PATCH', @_); } sub POST { request_type_with_data('POST', @_); } sub PUT { request_type_with_data('PUT', @_); } sub OPTIONS { request_type_with_data('OPTIONS', @_); } sub request_type_with_data { my $type = shift; my $url = shift; my $req = HTTP::Request->new($type => $url); my $content; $content = shift if @_ and ref $_[0]; my($k, $v); while (($k,$v) = splice(@_, 0, 2)) { if (lc($k) eq 'content') { $content = $v; } else { $req->push_header($k, $v); } } my $ct = $req->header('Content-Type'); unless ($ct) { $ct = 'application/x-www-form-urlencoded'; } elsif ($ct eq 'form-data') { $ct = 'multipart/form-data'; } if (ref $content) { if ($ct =~ m,^multipart/form-data\s*(;|$),i) { require HTTP::Headers::Util; my @v = HTTP::Headers::Util::split_header_words($ct); Carp::carp("Multiple Content-Type headers") if @v > 1; @v = @{$v[0]}; my $boundary; my $boundary_index; for (my @tmp = @v; @tmp;) { my($k, $v) = splice(@tmp, 0, 2); if ($k eq "boundary") { $boundary = $v; $boundary_index = @v - @tmp - 1; last; } } ($content, $boundary) = form_data($content, $boundary, $req); if ($boundary_index) { $v[$boundary_index] = $boundary; } else { push(@v, boundary => $boundary); } $ct = HTTP::Headers::Util::join_header_words(@v); } else { # We use a temporary URI object to format # the application/x-www-form-urlencoded content. require URI; my $url = URI->new('http:'); $url->query_form(ref($content) eq "HASH" ? %$content : @$content); $content = $url->query; # HTML/4.01 says that line breaks are represented as "CR LF" pairs (i.e., `%0D%0A') $content =~ s/(?<!%0D)%0A/%0D%0A/g if defined($content); } } $req->header('Content-Type' => $ct); # might be redundant if (defined($content)) { $req->header('Content-Length' => length($content)) unless ref($content); $req->content($content); } else { $req->header('Content-Length' => 0); } $req; } sub _simple_req { my($method, $url) = splice(@_, 0, 2); my $req = HTTP::Request->new($method => $url); my($k, $v); my $content; while (($k,$v) = splice(@_, 0, 2)) { if (lc($k) eq 'content') { $req->add_content($v); $content++; } else { $req->push_header($k, $v); } } if ($content && !defined($req->header("Content-Length"))) { $req->header("Content-Length", length(${$req->content_ref})); } $req; } sub form_data # RFC1867 { my($data, $boundary, $req) = @_; my @data = ref($data) eq "HASH" ? %$data : @$data; # copy my $fhparts; my @parts; while (my ($k,$v) = splice(@data, 0, 2)) { if (!ref($v)) { $k =~ s/([\\\"])/\\$1/g; # escape quotes and backslashes no warnings 'uninitialized'; push(@parts, qq(Content-Disposition: form-data; name="$k"$CRLF$CRLF$v)); } else { my($file, $usename, @headers) = @$v; unless (defined $usename) { $usename = $file; $usename = (File::Spec->splitpath($usename))[-1] if defined($usename); } $k =~ s/([\\\"])/\\$1/g; my $disp = qq(form-data; name="$k"); if (defined($usename) and length($usename)) { $usename =~ s/([\\\"])/\\$1/g; $disp .= qq(; filename="$usename"); } my $content = ""; my $h = HTTP::Headers->new(@headers); if ($file) { open(my $fh, "<", $file) or Carp::croak("Can't open file $file: $!"); binmode($fh); if ($DYNAMIC_FILE_UPLOAD) { # will read file later, close it now in order to # not accumulate to many open file handles close($fh); $content = \$file; } else { local($/) = undef; # slurp files $content = <$fh>; close($fh); } unless ($h->header("Content-Type")) { require LWP::MediaTypes; LWP::MediaTypes::guess_media_type($file, $h); } } if ($h->header("Content-Disposition")) { # just to get it sorted first $disp = $h->header("Content-Disposition"); $h->remove_header("Content-Disposition"); } if ($h->header("Content")) { $content = $h->header("Content"); $h->remove_header("Content"); } my $head = join($CRLF, "Content-Disposition: $disp", $h->as_string($CRLF), ""); if (ref $content) { push(@parts, [$head, $$content]); $fhparts++; } else { push(@parts, $head . $content); } } } return ("", "none") unless @parts; my $content; if ($fhparts) { $boundary = boundary(10) # hopefully enough randomness unless $boundary; # add the boundaries to the @parts array for (1..@parts-1) { splice(@parts, $_*2-1, 0, "$CRLF--$boundary$CRLF"); } unshift(@parts, "--$boundary$CRLF"); push(@parts, "$CRLF--$boundary--$CRLF"); # See if we can generate Content-Length header my $length = 0; for (@parts) { if (ref $_) { my ($head, $f) = @$_; my $file_size; unless ( -f $f && ($file_size = -s _) ) { # The file is either a dynamic file like /dev/audio # or perhaps a file in the /proc file system where # stat may return a 0 size even though reading it # will produce data. So we cannot make # a Content-Length header. undef $length; last; } $length += $file_size + length $head; } else { $length += length; } } $length && $req->header('Content-Length' => $length); # set up a closure that will return content piecemeal $content = sub { for (;;) { unless (@parts) { defined $length && $length != 0 && Carp::croak "length of data sent did not match calculated Content-Length header. Probably because uploaded file changed in size during transfer."; return; } my $p = shift @parts; unless (ref $p) { $p .= shift @parts while @parts && !ref($parts[0]); defined $length && ($length -= length $p); return $p; } my($buf, $fh) = @$p; unless (ref($fh)) { my $file = $fh; undef($fh); open($fh, "<", $file) || Carp::croak("Can't open file $file: $!"); binmode($fh); } my $buflength = length $buf; my $n = read($fh, $buf, 2048, $buflength); if ($n) { $buflength += $n; unshift(@parts, ["", $fh]); } else { close($fh); } if ($buflength) { defined $length && ($length -= $buflength); return $buf } } }; } else { $boundary = boundary() unless $boundary; my $bno = 0; CHECK_BOUNDARY: { for (@parts) { if (index($_, $boundary) >= 0) { # must have a better boundary $boundary = boundary(++$bno); redo CHECK_BOUNDARY; } } last; } $content = "--$boundary$CRLF" . join("$CRLF--$boundary$CRLF", @parts) . "$CRLF--$boundary--$CRLF"; } wantarray ? ($content, $boundary) : $content; } sub boundary { my $size = shift || return "xYzZY"; require MIME::Base64; my $b = MIME::Base64::encode(join("", map chr(rand(256)), 1..$size*3), ""); $b =~ s/[\W]/X/g; # ensure alnum only $b; } 1; =pod =encoding UTF-8 =head1 NAME HTTP::Request::Common - Construct common HTTP::Request objects =head1 VERSION version 6.36 =head1 SYNOPSIS use HTTP::Request::Common; $ua = LWP::UserAgent->new; $ua->request(GET 'http://www.sn.no/'); $ua->request(POST 'http://somewhere/foo', foo => bar, bar => foo); $ua->request(PATCH 'http://somewhere/foo', foo => bar, bar => foo); $ua->request(PUT 'http://somewhere/foo', foo => bar, bar => foo); $ua->request(OPTIONS 'http://somewhere/foo', foo => bar, bar => foo); =head1 DESCRIPTION This module provides functions that return newly created C<HTTP::Request> objects. These functions are usually more convenient to use than the standard C<HTTP::Request> constructor for the most common requests. Note that L<LWP::UserAgent> has several convenience methods, including C<get>, C<head>, C<delete>, C<post> and C<put>. The following functions are provided: =over 4 =item GET $url =item GET $url, Header => Value,... The C<GET> function returns an L<HTTP::Request> object initialized with the "GET" method and the specified URL. It is roughly equivalent to the following call HTTP::Request->new( GET => $url, HTTP::Headers->new(Header => Value,...), ) but is less cluttered. What is different is that a header named C<Content> will initialize the content part of the request instead of setting a header field. Note that GET requests should normally not have a content, so this hack makes more sense for the C<PUT>, C<PATCH> and C<POST> functions described below. The C<get(...)> method of L<LWP::UserAgent> exists as a shortcut for C<< $ua->request(GET ...) >>. =item HEAD $url =item HEAD $url, Header => Value,... Like GET() but the method in the request is "HEAD". The C<head(...)> method of L<LWP::UserAgent> exists as a shortcut for C<< $ua->request(HEAD ...) >>. =item DELETE $url =item DELETE $url, Header => Value,... Like C<GET> but the method in the request is C<DELETE>. This function is not exported by default. =item PATCH $url =item PATCH $url, Header => Value,... =item PATCH $url, $form_ref, Header => Value,... =item PATCH $url, Header => Value,..., Content => $form_ref =item PATCH $url, Header => Value,..., Content => $content The same as C<POST> below, but the method in the request is C<PATCH>. =item PUT $url =item PUT $url, Header => Value,... =item PUT $url, $form_ref, Header => Value,... =item PUT $url, Header => Value,..., Content => $form_ref =item PUT $url, Header => Value,..., Content => $content The same as C<POST> below, but the method in the request is C<PUT> =item OPTIONS $url =item OPTIONS $url, Header => Value,... =item OPTIONS $url, $form_ref, Header => Value,... =item OPTIONS $url, Header => Value,..., Content => $form_ref =item OPTIONS $url, Header => Value,..., Content => $content The same as C<POST> below, but the method in the request is C<OPTIONS> =item POST $url =item POST $url, Header => Value,... =item POST $url, $form_ref, Header => Value,... =item POST $url, Header => Value,..., Content => $form_ref =item POST $url, Header => Value,..., Content => $content C<POST>, C<PATCH> and C<PUT> all work with the same parameters. %data = ( title => 'something', body => something else' ); $ua = LWP::UserAgent->new(); $request = HTTP::Request::Common::POST( $url, [ %data ] ); $response = $ua->request($request); They take a second optional array or hash reference parameter C<$form_ref>. The content can also be specified directly using the C<Content> pseudo-header, and you may also provide the C<$form_ref> this way. The C<Content> pseudo-header steals a bit of the header field namespace as there is no way to directly specify a header that is actually called "Content". If you really need this you must update the request returned in a separate statement. The C<$form_ref> argument can be used to pass key/value pairs for the form content. By default we will initialize a request using the C<application/x-www-form-urlencoded> content type. This means that you can emulate an HTML E<lt>form> POSTing like this: POST 'http://www.perl.org/survey.cgi', [ name => 'Gisle Aas', email => 'gisle@aas.no', gender => 'M', born => '1964', perc => '3%', ]; This will create an L<HTTP::Request> object that looks like this: POST http://www.perl.org/survey.cgi Content-Length: 66 Content-Type: application/x-www-form-urlencoded name=Gisle%20Aas&email=gisle%40aas.no&gender=M&born=1964&perc=3%25 Multivalued form fields can be specified by either repeating the field name or by passing the value as an array reference. The POST method also supports the C<multipart/form-data> content used for I<Form-based File Upload> as specified in RFC 1867. You trigger this content format by specifying a content type of C<'form-data'> as one of the request headers. If one of the values in the C<$form_ref> is an array reference, then it is treated as a file part specification with the following interpretation: [ $file, $filename, Header => Value... ] [ undef, $filename, Header => Value,..., Content => $content ] The first value in the array ($file) is the name of a file to open. This file will be read and its content placed in the request. The routine will croak if the file can't be opened. Use an C<undef> as $file value if you want to specify the content directly with a C<Content> header. The $filename is the filename to report in the request. If this value is undefined, then the basename of the $file will be used. You can specify an empty string as $filename if you want to suppress sending the filename when you provide a $file value. If a $file is provided by no C<Content-Type> header, then C<Content-Type> and C<Content-Encoding> will be filled in automatically with the values returned by C<LWP::MediaTypes::guess_media_type()> Sending my F<~/.profile> to the survey used as example above can be achieved by this: POST 'http://www.perl.org/survey.cgi', Content_Type => 'form-data', Content => [ name => 'Gisle Aas', email => 'gisle@aas.no', gender => 'M', born => '1964', init => ["$ENV{HOME}/.profile"], ] This will create an L<HTTP::Request> object that almost looks this (the boundary and the content of your F<~/.profile> is likely to be different): POST http://www.perl.org/survey.cgi Content-Length: 388 Content-Type: multipart/form-data; boundary="6G+f" --6G+f Content-Disposition: form-data; name="name" Gisle Aas --6G+f Content-Disposition: form-data; name="email" gisle@aas.no --6G+f Content-Disposition: form-data; name="gender" M --6G+f Content-Disposition: form-data; name="born" 1964 --6G+f Content-Disposition: form-data; name="init"; filename=".profile" Content-Type: text/plain PATH=/local/perl/bin:$PATH export PATH --6G+f-- If you set the C<$DYNAMIC_FILE_UPLOAD> variable (exportable) to some TRUE value, then you get back a request object with a subroutine closure as the content attribute. This subroutine will read the content of any files on demand and return it in suitable chunks. This allow you to upload arbitrary big files without using lots of memory. You can even upload infinite files like F</dev/audio> if you wish; however, if the file is not a plain file, there will be no C<Content-Length> header defined for the request. Not all servers (or server applications) like this. Also, if the file(s) change in size between the time the C<Content-Length> is calculated and the time that the last chunk is delivered, the subroutine will C<Croak>. The C<post(...)> method of L<LWP::UserAgent> exists as a shortcut for C<< $ua->request(POST ...) >>. =back =head1 SEE ALSO L<HTTP::Request>, L<LWP::UserAgent> Also, there are some examples in L<HTTP::Request/"EXAMPLES"> that you might find useful. For example, batch requests are explained there. =head1 AUTHOR Gisle Aas <gisle@activestate.com> =head1 COPYRIGHT AND LICENSE This software is copyright (c) 1994 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ #ABSTRACT: Construct common HTTP::Request objects PK ! �69(B B HTTP/Response.pmnu �[��� package HTTP::Response; use strict; use warnings; our $VERSION = '6.36'; use base 'HTTP::Message'; use HTTP::Status (); sub new { my($class, $rc, $msg, $header, $content) = @_; my $self = $class->SUPER::new($header, $content); $self->code($rc); $self->message($msg); $self; } sub parse { my($class, $str) = @_; Carp::carp('Undefined argument to parse()') if $^W && ! defined $str; my $status_line; if (defined $str && $str =~ s/^(.*)\n//) { $status_line = $1; } else { $status_line = $str; $str = ""; } $status_line =~ s/\r\z// if defined $status_line; my $self = $class->SUPER::parse($str); if (defined $status_line) { my($protocol, $code, $message); if ($status_line =~ /^\d{3} /) { # Looks like a response created by HTTP::Response->new ($code, $message) = split(' ', $status_line, 2); } else { ($protocol, $code, $message) = split(' ', $status_line, 3); } $self->protocol($protocol) if $protocol; $self->code($code) if defined($code); $self->message($message) if defined($message); } $self; } sub clone { my $self = shift; my $clone = bless $self->SUPER::clone, ref($self); $clone->code($self->code); $clone->message($self->message); $clone->request($self->request->clone) if $self->request; # we don't clone previous $clone; } sub code { shift->_elem('_rc', @_); } sub message { shift->_elem('_msg', @_); } sub previous { shift->_elem('_previous',@_); } sub request { shift->_elem('_request', @_); } sub status_line { my $self = shift; my $code = $self->{'_rc'} || "000"; my $mess = $self->{'_msg'} || HTTP::Status::status_message($code) || "Unknown code"; return "$code $mess"; } sub base { my $self = shift; my $base = ( $self->header('Content-Base'), # used to be HTTP/1.1 $self->header('Content-Location'), # HTTP/1.1 $self->header('Base'), # HTTP/1.0 )[0]; if ($base && $base =~ /^$URI::scheme_re:/o) { # already absolute return $HTTP::URI_CLASS->new($base); } my $req = $self->request; if ($req) { # if $base is undef here, the return value is effectively # just a copy of $self->request->uri. return $HTTP::URI_CLASS->new_abs($base, $req->uri); } # can't find an absolute base return undef; } sub redirects { my $self = shift; my @r; my $r = $self; while (my $p = $r->previous) { push(@r, $p); $r = $p; } return @r unless wantarray; return reverse @r; } sub filename { my $self = shift; my $file; my $cd = $self->header('Content-Disposition'); if ($cd) { require HTTP::Headers::Util; if (my @cd = HTTP::Headers::Util::split_header_words($cd)) { my ($disposition, undef, %cd_param) = @{$cd[-1]}; $file = $cd_param{filename}; # RFC 2047 encoded? if ($file && $file =~ /^=\?(.+?)\?(.+?)\?(.+)\?=$/) { my $charset = $1; my $encoding = uc($2); my $encfile = $3; if ($encoding eq 'Q' || $encoding eq 'B') { local($SIG{__DIE__}); eval { if ($encoding eq 'Q') { $encfile =~ s/_/ /g; require MIME::QuotedPrint; $encfile = MIME::QuotedPrint::decode($encfile); } else { # $encoding eq 'B' require MIME::Base64; $encfile = MIME::Base64::decode($encfile); } require Encode; require Encode::Locale; Encode::from_to($encfile, $charset, "locale_fs"); }; $file = $encfile unless $@; } } } } unless (defined($file) && length($file)) { my $uri; if (my $cl = $self->header('Content-Location')) { $uri = URI->new($cl); } elsif (my $request = $self->request) { $uri = $request->uri; } if ($uri) { $file = ($uri->path_segments)[-1]; } } if ($file) { $file =~ s,.*[\\/],,; # basename } if ($file && !length($file)) { $file = undef; } $file; } sub as_string { my $self = shift; my($eol) = @_; $eol = "\n" unless defined $eol; my $status_line = $self->status_line; my $proto = $self->protocol; $status_line = "$proto $status_line" if $proto; return join($eol, $status_line, $self->SUPER::as_string(@_)); } sub dump { my $self = shift; my $status_line = $self->status_line; my $proto = $self->protocol; $status_line = "$proto $status_line" if $proto; return $self->SUPER::dump( preheader => $status_line, @_, ); } sub is_info { HTTP::Status::is_info (shift->{'_rc'}); } sub is_success { HTTP::Status::is_success (shift->{'_rc'}); } sub is_redirect { HTTP::Status::is_redirect (shift->{'_rc'}); } sub is_error { HTTP::Status::is_error (shift->{'_rc'}); } sub is_client_error { HTTP::Status::is_client_error (shift->{'_rc'}); } sub is_server_error { HTTP::Status::is_server_error (shift->{'_rc'}); } sub error_as_HTML { my $self = shift; my $title = 'An Error Occurred'; my $body = $self->status_line; $body =~ s/&/&/g; $body =~ s/</</g; return <<EOM; <html> <head><title>$title</title></head> <body> <h1>$title</h1> <p>$body</p> </body> </html> EOM } sub current_age { my $self = shift; my $time = shift; # Implementation of RFC 2616 section 13.2.3 # (age calculations) my $response_time = $self->client_date; my $date = $self->date; my $age = 0; if ($response_time && $date) { $age = $response_time - $date; # apparent_age $age = 0 if $age < 0; } my $age_v = $self->header('Age'); if ($age_v && $age_v > $age) { $age = $age_v; # corrected_received_age } if ($response_time) { my $request = $self->request; if ($request) { my $request_time = $request->date; if ($request_time && $request_time < $response_time) { # Add response_delay to age to get 'corrected_initial_age' $age += $response_time - $request_time; } } $age += ($time || time) - $response_time; } return $age; } sub freshness_lifetime { my($self, %opt) = @_; # First look for the Cache-Control: max-age=n header for my $cc ($self->header('Cache-Control')) { for my $cc_dir (split(/\s*,\s*/, $cc)) { return $1 if $cc_dir =~ /^max-age\s*=\s*(\d+)/i; } } # Next possibility is to look at the "Expires" header my $date = $self->date || $self->client_date || $opt{time} || time; if (my $expires = $self->expires) { return $expires - $date; } # Must apply heuristic expiration return undef if exists $opt{heuristic_expiry} && !$opt{heuristic_expiry}; # Default heuristic expiration parameters $opt{h_min} ||= 60; $opt{h_max} ||= 24 * 3600; $opt{h_lastmod_fraction} ||= 0.10; # 10% since last-mod suggested by RFC2616 $opt{h_default} ||= 3600; # Should give a warning if more than 24 hours according to # RFC 2616 section 13.2.4. Here we just make this the default # maximum value. if (my $last_modified = $self->last_modified) { my $h_exp = ($date - $last_modified) * $opt{h_lastmod_fraction}; return $opt{h_min} if $h_exp < $opt{h_min}; return $opt{h_max} if $h_exp > $opt{h_max}; return $h_exp; } # default when all else fails return $opt{h_min} if $opt{h_min} > $opt{h_default}; return $opt{h_default}; } sub is_fresh { my($self, %opt) = @_; $opt{time} ||= time; my $f = $self->freshness_lifetime(%opt); return undef unless defined($f); return $f > $self->current_age($opt{time}); } sub fresh_until { my($self, %opt) = @_; $opt{time} ||= time; my $f = $self->freshness_lifetime(%opt); return undef unless defined($f); return $f - $self->current_age($opt{time}) + $opt{time}; } 1; =pod =encoding UTF-8 =head1 NAME HTTP::Response - HTTP style response message =head1 VERSION version 6.36 =head1 SYNOPSIS Response objects are returned by the request() method of the C<LWP::UserAgent>: # ... $response = $ua->request($request); if ($response->is_success) { print $response->decoded_content; } else { print STDERR $response->status_line, "\n"; } =head1 DESCRIPTION The C<HTTP::Response> class encapsulates HTTP style responses. A response consists of a response line, some headers, and a content body. Note that the LWP library uses HTTP style responses even for non-HTTP protocol schemes. Instances of this class are usually created and returned by the request() method of an C<LWP::UserAgent> object. C<HTTP::Response> is a subclass of C<HTTP::Message> and therefore inherits its methods. The following additional methods are available: =over 4 =item $r = HTTP::Response->new( $code ) =item $r = HTTP::Response->new( $code, $msg ) =item $r = HTTP::Response->new( $code, $msg, $header ) =item $r = HTTP::Response->new( $code, $msg, $header, $content ) Constructs a new C<HTTP::Response> object describing a response with response code $code and optional message $msg. The optional $header argument should be a reference to an C<HTTP::Headers> object or a plain array reference of key/value pairs. The optional $content argument should be a string of bytes. The meanings of these arguments are described below. =item $r = HTTP::Response->parse( $str ) This constructs a new response object by parsing the given string. =item $r->code =item $r->code( $code ) This is used to get/set the code attribute. The code is a 3 digit number that encode the overall outcome of an HTTP response. The C<HTTP::Status> module provide constants that provide mnemonic names for the code attribute. =item $r->message =item $r->message( $message ) This is used to get/set the message attribute. The message is a short human readable single line string that explains the response code. =item $r->header( $field ) =item $r->header( $field => $value ) This is used to get/set header values and it is inherited from C<HTTP::Headers> via C<HTTP::Message>. See L<HTTP::Headers> for details and other similar methods that can be used to access the headers. =item $r->content =item $r->content( $bytes ) This is used to get/set the raw content and it is inherited from the C<HTTP::Message> base class. See L<HTTP::Message> for details and other methods that can be used to access the content. =item $r->decoded_content( %options ) This will return the content after any C<Content-Encoding> and charsets have been decoded. See L<HTTP::Message> for details. =item $r->request =item $r->request( $request ) This is used to get/set the request attribute. The request attribute is a reference to the request that caused this response. It does not have to be the same request passed to the $ua->request() method, because there might have been redirects and authorization retries in between. =item $r->previous =item $r->previous( $response ) This is used to get/set the previous attribute. The previous attribute is used to link together chains of responses. You get chains of responses if the first response is redirect or unauthorized. The value is C<undef> if this is the first response in a chain. Note that the method $r->redirects is provided as a more convenient way to access the response chain. =item $r->status_line Returns the string "E<lt>code> E<lt>message>". If the message attribute is not set then the official name of E<lt>code> (see L<HTTP::Status>) is substituted. =item $r->base Returns the base URI for this response. The return value will be a reference to a URI object. The base URI is obtained from one the following sources (in priority order): =over 4 =item 1. Embedded in the document content, for instance <BASE HREF="..."> in HTML documents. =item 2. A "Content-Base:" or a "Content-Location:" header in the response. For backwards compatibility with older HTTP implementations we will also look for the "Base:" header. =item 3. The URI used to request this response. This might not be the original URI that was passed to $ua->request() method, because we might have received some redirect responses first. =back If none of these sources provide an absolute URI, undef is returned. When the LWP protocol modules produce the HTTP::Response object, then any base URI embedded in the document (step 1) will already have initialized the "Content-Base:" header. (See L<LWP::UserAgent/parse_head>). This means that this method only performs the last 2 steps (the content is not always available either). =item $r->filename Returns a filename for this response. Note that doing sanity checks on the returned filename (eg. removing characters that cannot be used on the target filesystem where the filename would be used, and laundering it for security purposes) are the caller's responsibility; the only related thing done by this method is that it makes a simple attempt to return a plain filename with no preceding path segments. The filename is obtained from one the following sources (in priority order): =over 4 =item 1. A "Content-Disposition:" header in the response. Proper decoding of RFC 2047 encoded filenames requires the C<MIME::QuotedPrint> (for "Q" encoding), C<MIME::Base64> (for "B" encoding), and C<Encode> modules. =item 2. A "Content-Location:" header in the response. =item 3. The URI used to request this response. This might not be the original URI that was passed to $ua->request() method, because we might have received some redirect responses first. =back If a filename cannot be derived from any of these sources, undef is returned. =item $r->as_string =item $r->as_string( $eol ) Returns a textual representation of the response. =item $r->is_info =item $r->is_success =item $r->is_redirect =item $r->is_error =item $r->is_client_error =item $r->is_server_error These methods indicate if the response was informational, successful, a redirection, or an error. See L<HTTP::Status> for the meaning of these. =item $r->error_as_HTML Returns a string containing a complete HTML document indicating what error occurred. This method should only be called when $r->is_error is TRUE. =item $r->redirects Returns the list of redirect responses that lead up to this response by following the $r->previous chain. The list order is oldest first. In scalar context return the number of redirect responses leading up to this one. =item $r->current_age Calculates the "current age" of the response as specified by RFC 2616 section 13.2.3. The age of a response is the time since it was sent by the origin server. The returned value is a number representing the age in seconds. =item $r->freshness_lifetime( %opt ) Calculates the "freshness lifetime" of the response as specified by RFC 2616 section 13.2.4. The "freshness lifetime" is the length of time between the generation of a response and its expiration time. The returned value is the number of seconds until expiry. If the response does not contain an "Expires" or a "Cache-Control" header, then this function will apply some simple heuristic based on the "Last-Modified" header to determine a suitable lifetime. The following options might be passed to control the heuristics: =over =item heuristic_expiry => $bool If passed as a FALSE value, don't apply heuristics and just return C<undef> when "Expires" or "Cache-Control" is lacking. =item h_lastmod_fraction => $num This number represent the fraction of the difference since the "Last-Modified" timestamp to make the expiry time. The default is C<0.10>, the suggested typical setting of 10% in RFC 2616. =item h_min => $sec This is the lower limit of the heuristic expiry age to use. The default is C<60> (1 minute). =item h_max => $sec This is the upper limit of the heuristic expiry age to use. The default is C<86400> (24 hours). =item h_default => $sec This is the expiry age to use when nothing else applies. The default is C<3600> (1 hour) or "h_min" if greater. =back =item $r->is_fresh( %opt ) Returns TRUE if the response is fresh, based on the values of freshness_lifetime() and current_age(). If the response is no longer fresh, then it has to be re-fetched or re-validated by the origin server. Options might be passed to control expiry heuristics, see the description of freshness_lifetime(). =item $r->fresh_until( %opt ) Returns the time (seconds since epoch) when this entity is no longer fresh. Options might be passed to control expiry heuristics, see the description of freshness_lifetime(). =back =head1 SEE ALSO L<HTTP::Headers>, L<HTTP::Message>, L<HTTP::Status>, L<HTTP::Request> =head1 AUTHOR Gisle Aas <gisle@activestate.com> =head1 COPYRIGHT AND LICENSE This software is copyright (c) 1994 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ #ABSTRACT: HTTP style response message PK ! �-�Bb Bb HTTP/Headers.pmnu �[��� package HTTP::Headers; use strict; use warnings; our $VERSION = '6.36'; use Carp (); # The $TRANSLATE_UNDERSCORE variable controls whether '_' can be used # as a replacement for '-' in header field names. our $TRANSLATE_UNDERSCORE = 1 unless defined $TRANSLATE_UNDERSCORE; # "Good Practice" order of HTTP message headers: # - General-Headers # - Request-Headers # - Response-Headers # - Entity-Headers my @general_headers = qw( Cache-Control Connection Date Pragma Trailer Transfer-Encoding Upgrade Via Warning ); my @request_headers = qw( Accept Accept-Charset Accept-Encoding Accept-Language Authorization Expect From Host If-Match If-Modified-Since If-None-Match If-Range If-Unmodified-Since Max-Forwards Proxy-Authorization Range Referer TE User-Agent ); my @response_headers = qw( Accept-Ranges Age ETag Location Proxy-Authenticate Retry-After Server Vary WWW-Authenticate ); my @entity_headers = qw( Allow Content-Encoding Content-Language Content-Length Content-Location Content-MD5 Content-Range Content-Type Expires Last-Modified ); my %entity_header = map { lc($_) => 1 } @entity_headers; my @header_order = ( @general_headers, @request_headers, @response_headers, @entity_headers, ); # Make alternative representations of @header_order. This is used # for sorting and case matching. my %header_order; my %standard_case; { my $i = 0; for (@header_order) { my $lc = lc $_; $header_order{$lc} = ++$i; $standard_case{$lc} = $_; } } sub new { my($class) = shift; my $self = bless {}, $class; $self->header(@_) if @_; # set up initial headers $self; } sub header { my $self = shift; Carp::croak('Usage: $h->header($field, ...)') unless @_; my(@old); my %seen; while (@_) { my $field = shift; my $op = @_ ? ($seen{lc($field)}++ ? 'PUSH' : 'SET') : 'GET'; @old = $self->_header($field, shift, $op); } return @old if wantarray; return $old[0] if @old <= 1; join(", ", @old); } sub clear { my $self = shift; %$self = (); } sub push_header { my $self = shift; return $self->_header(@_, 'PUSH_H') if @_ == 2; while (@_) { $self->_header(splice(@_, 0, 2), 'PUSH_H'); } } sub init_header { Carp::croak('Usage: $h->init_header($field, $val)') if @_ != 3; shift->_header(@_, 'INIT'); } sub remove_header { my($self, @fields) = @_; my $field; my @values; foreach $field (@fields) { $field =~ tr/_/-/ if $field !~ /^:/ && $TRANSLATE_UNDERSCORE; my $v = delete $self->{lc $field}; push(@values, ref($v) eq 'ARRAY' ? @$v : $v) if defined $v; } return @values; } sub remove_content_headers { my $self = shift; unless (defined(wantarray)) { # fast branch that does not create return object delete @$self{grep $entity_header{$_} || /^content-/, keys %$self}; return; } my $c = ref($self)->new; for my $f (grep $entity_header{$_} || /^content-/, keys %$self) { $c->{$f} = delete $self->{$f}; } if (exists $self->{'::std_case'}) { $c->{'::std_case'} = $self->{'::std_case'}; } $c; } sub _header { my($self, $field, $val, $op) = @_; Carp::croak("Illegal field name '$field'") if rindex($field, ':') > 1 || !length($field); unless ($field =~ /^:/) { $field =~ tr/_/-/ if $TRANSLATE_UNDERSCORE; my $old = $field; $field = lc $field; unless($standard_case{$field} || $self->{'::std_case'}{$field}) { # generate a %std_case entry for this field $old =~ s/\b(\w)/\u$1/g; $self->{'::std_case'}{$field} = $old; } } $op ||= defined($val) ? 'SET' : 'GET'; if ($op eq 'PUSH_H') { # Like PUSH but where we don't care about the return value if (exists $self->{$field}) { my $h = $self->{$field}; if (ref($h) eq 'ARRAY') { push(@$h, ref($val) eq "ARRAY" ? @$val : $val); } else { $self->{$field} = [$h, ref($val) eq "ARRAY" ? @$val : $val] } return; } $self->{$field} = $val; return; } my $h = $self->{$field}; my @old = ref($h) eq 'ARRAY' ? @$h : (defined($h) ? ($h) : ()); unless ($op eq 'GET' || ($op eq 'INIT' && @old)) { if (defined($val)) { my @new = ($op eq 'PUSH') ? @old : (); if (ref($val) ne 'ARRAY') { push(@new, $val); } else { push(@new, @$val); } $self->{$field} = @new > 1 ? \@new : $new[0]; } elsif ($op ne 'PUSH') { delete $self->{$field}; } } @old; } sub _sorted_field_names { my $self = shift; return [ sort { ($header_order{$a} || 999) <=> ($header_order{$b} || 999) || $a cmp $b } grep !/^::/, keys %$self ]; } sub header_field_names { my $self = shift; return map $standard_case{$_} || $self->{'::std_case'}{$_} || $_, @{ $self->_sorted_field_names }, if wantarray; return grep !/^::/, keys %$self; } sub scan { my($self, $sub) = @_; my $key; for $key (@{ $self->_sorted_field_names }) { my $vals = $self->{$key}; if (ref($vals) eq 'ARRAY') { my $val; for $val (@$vals) { $sub->($standard_case{$key} || $self->{'::std_case'}{$key} || $key, $val); } } else { $sub->($standard_case{$key} || $self->{'::std_case'}{$key} || $key, $vals); } } } sub flatten { my($self)=@_; ( map { my $k = $_; map { ( $k => $_ ) } $self->header($_); } $self->header_field_names ); } sub as_string { my($self, $endl) = @_; $endl = "\n" unless defined $endl; my @result = (); for my $key (@{ $self->_sorted_field_names }) { next if index($key, '_') == 0; my $vals = $self->{$key}; if ( ref($vals) eq 'ARRAY' ) { for my $val (@$vals) { $val = '' if not defined $val; my $field = $standard_case{$key} || $self->{'::std_case'}{$key} || $key; $field =~ s/^://; if ( index($val, "\n") >= 0 ) { $val = _process_newline($val, $endl); } push @result, $field . ': ' . $val; } } else { $vals = '' if not defined $vals; my $field = $standard_case{$key} || $self->{'::std_case'}{$key} || $key; $field =~ s/^://; if ( index($vals, "\n") >= 0 ) { $vals = _process_newline($vals, $endl); } push @result, $field . ': ' . $vals; } } join($endl, @result, ''); } sub _process_newline { local $_ = shift; my $endl = shift; # must handle header values with embedded newlines with care s/\s+$//; # trailing newlines and space must go s/\n(\x0d?\n)+/\n/g; # no empty lines s/\n([^\040\t])/\n $1/g; # initial space for continuation s/\n/$endl/g; # substitute with requested line ending $_; } if (eval { require Clone; 1 }) { *clone = \&Clone::clone; } else { *clone = sub { my $self = shift; my $clone = HTTP::Headers->new; $self->scan(sub { $clone->push_header(@_);} ); $clone; }; } sub _date_header { require HTTP::Date; my($self, $header, $time) = @_; my($old) = $self->_header($header); if (defined $time) { $self->_header($header, HTTP::Date::time2str($time)); } $old =~ s/;.*// if defined($old); HTTP::Date::str2time($old); } sub date { shift->_date_header('Date', @_); } sub expires { shift->_date_header('Expires', @_); } sub if_modified_since { shift->_date_header('If-Modified-Since', @_); } sub if_unmodified_since { shift->_date_header('If-Unmodified-Since', @_); } sub last_modified { shift->_date_header('Last-Modified', @_); } # This is used as a private LWP extension. The Client-Date header is # added as a timestamp to a response when it has been received. sub client_date { shift->_date_header('Client-Date', @_); } # The retry_after field is dual format (can also be a expressed as # number of seconds from now), so we don't provide an easy way to # access it until we have know how both these interfaces can be # addressed. One possibility is to return a negative value for # relative seconds and a positive value for epoch based time values. #sub retry_after { shift->_date_header('Retry-After', @_); } sub content_type { my $self = shift; my $ct = $self->{'content-type'}; $self->{'content-type'} = shift if @_; $ct = $ct->[0] if ref($ct) eq 'ARRAY'; return '' unless defined($ct) && length($ct); my @ct = split(/;\s*/, $ct, 2); for ($ct[0]) { s/\s+//g; $_ = lc($_); } wantarray ? @ct : $ct[0]; } sub content_type_charset { my $self = shift; require HTTP::Headers::Util; my $h = $self->{'content-type'}; $h = $h->[0] if ref($h); $h = "" unless defined $h; my @v = HTTP::Headers::Util::split_header_words($h); if (@v) { my($ct, undef, %ct_param) = @{$v[0]}; my $charset = $ct_param{charset}; if ($ct) { $ct = lc($ct); $ct =~ s/\s+//; } if ($charset) { $charset = uc($charset); $charset =~ s/^\s+//; $charset =~ s/\s+\z//; undef($charset) if $charset eq ""; } return $ct, $charset if wantarray; return $charset; } return undef, undef if wantarray; return undef; } sub content_is_text { my $self = shift; return $self->content_type =~ m,^text/,; } sub content_is_html { my $self = shift; return $self->content_type eq 'text/html' || $self->content_is_xhtml; } sub content_is_xhtml { my $ct = shift->content_type; return $ct eq "application/xhtml+xml" || $ct eq "application/vnd.wap.xhtml+xml"; } sub content_is_xml { my $ct = shift->content_type; return 1 if $ct eq "text/xml"; return 1 if $ct eq "application/xml"; return 1 if $ct =~ /\+xml$/; return 0; } sub referer { my $self = shift; if (@_ && $_[0] =~ /#/) { # Strip fragment per RFC 2616, section 14.36. my $uri = shift; if (ref($uri)) { $uri = $uri->clone; $uri->fragment(undef); } else { $uri =~ s/\#.*//; } unshift @_, $uri; } ($self->_header('Referer', @_))[0]; } *referrer = \&referer; # on tchrist's request sub title { (shift->_header('Title', @_))[0] } sub content_encoding { (shift->_header('Content-Encoding', @_))[0] } sub content_language { (shift->_header('Content-Language', @_))[0] } sub content_length { (shift->_header('Content-Length', @_))[0] } sub user_agent { (shift->_header('User-Agent', @_))[0] } sub server { (shift->_header('Server', @_))[0] } sub from { (shift->_header('From', @_))[0] } sub warning { (shift->_header('Warning', @_))[0] } sub www_authenticate { (shift->_header('WWW-Authenticate', @_))[0] } sub authorization { (shift->_header('Authorization', @_))[0] } sub proxy_authenticate { (shift->_header('Proxy-Authenticate', @_))[0] } sub proxy_authorization { (shift->_header('Proxy-Authorization', @_))[0] } sub authorization_basic { shift->_basic_auth("Authorization", @_) } sub proxy_authorization_basic { shift->_basic_auth("Proxy-Authorization", @_) } sub _basic_auth { require MIME::Base64; my($self, $h, $user, $passwd) = @_; my($old) = $self->_header($h); if (defined $user) { Carp::croak("Basic authorization user name can't contain ':'") if $user =~ /:/; $passwd = '' unless defined $passwd; $self->_header($h => 'Basic ' . MIME::Base64::encode("$user:$passwd", '')); } if (defined $old && $old =~ s/^\s*Basic\s+//) { my $val = MIME::Base64::decode($old); return $val unless wantarray; return split(/:/, $val, 2); } return; } 1; =pod =encoding UTF-8 =head1 NAME HTTP::Headers - Class encapsulating HTTP Message headers =head1 VERSION version 6.36 =head1 SYNOPSIS require HTTP::Headers; $h = HTTP::Headers->new; $h->header('Content-Type' => 'text/plain'); # set $ct = $h->header('Content-Type'); # get $h->remove_header('Content-Type'); # delete =head1 DESCRIPTION The C<HTTP::Headers> class encapsulates HTTP-style message headers. The headers consist of attribute-value pairs also called fields, which may be repeated, and which are printed in a particular order. The field names are cases insensitive. Instances of this class are usually created as member variables of the C<HTTP::Request> and C<HTTP::Response> classes, internal to the library. The following methods are available: =over 4 =item $h = HTTP::Headers->new Constructs a new C<HTTP::Headers> object. You might pass some initial attribute-value pairs as parameters to the constructor. I<E.g.>: $h = HTTP::Headers->new( Date => 'Thu, 03 Feb 1994 00:00:00 GMT', Content_Type => 'text/html; version=3.2', Content_Base => 'http://www.perl.org/'); The constructor arguments are passed to the C<header> method which is described below. =item $h->clone Returns a copy of this C<HTTP::Headers> object. =item $h->header( $field ) =item $h->header( $field => $value ) =item $h->header( $f1 => $v1, $f2 => $v2, ... ) Get or set the value of one or more header fields. The header field name ($field) is not case sensitive. To make the life easier for perl users who wants to avoid quoting before the => operator, you can use '_' as a replacement for '-' in header names. The header() method accepts multiple ($field => $value) pairs, which means that you can update several fields with a single invocation. The $value argument may be a plain string or a reference to an array of strings for a multi-valued field. If the $value is provided as C<undef> then the field is removed. If the $value is not given, then that header field will remain unchanged. In addition to being a string, $value may be something that stringifies. The old value (or values) of the last of the header fields is returned. If no such field exists C<undef> will be returned. A multi-valued field will be returned as separate values in list context and will be concatenated with ", " as separator in scalar context. The HTTP spec (RFC 2616) promises that joining multiple values in this way will not change the semantic of a header field, but in practice there are cases like old-style Netscape cookies (see L<HTTP::Cookies>) where "," is used as part of the syntax of a single field value. Examples: $header->header(MIME_Version => '1.0', User_Agent => 'My-Web-Client/0.01'); $header->header(Accept => "text/html, text/plain, image/*"); $header->header(Accept => [qw(text/html text/plain image/*)]); @accepts = $header->header('Accept'); # get multiple values $accepts = $header->header('Accept'); # get values as a single string =item $h->push_header( $field => $value ) =item $h->push_header( $f1 => $v1, $f2 => $v2, ... ) Add a new field value for the specified header field. Previous values for the same field are retained. As for the header() method, the field name ($field) is not case sensitive and '_' can be used as a replacement for '-'. The $value argument may be a scalar or a reference to a list of scalars. $header->push_header(Accept => 'image/jpeg'); $header->push_header(Accept => [map "image/$_", qw(gif png tiff)]); =item $h->init_header( $field => $value ) Set the specified header to the given value, but only if no previous value for that field is set. The header field name ($field) is not case sensitive and '_' can be used as a replacement for '-'. The $value argument may be a scalar or a reference to a list of scalars. =item $h->remove_header( $field, ... ) This function removes the header fields with the specified names. The header field names ($field) are not case sensitive and '_' can be used as a replacement for '-'. The return value is the values of the fields removed. In scalar context the number of fields removed is returned. Note that if you pass in multiple field names then it is generally not possible to tell which of the returned values belonged to which field. =item $h->remove_content_headers This will remove all the header fields used to describe the content of a message. All header field names prefixed with C<Content-> fall into this category, as well as C<Allow>, C<Expires> and C<Last-Modified>. RFC 2616 denotes these fields as I<Entity Header Fields>. The return value is a new C<HTTP::Headers> object that contains the removed headers only. =item $h->clear This will remove all header fields. =item $h->header_field_names Returns the list of distinct names for the fields present in the header. The field names have case as suggested by HTTP spec, and the names are returned in the recommended "Good Practice" order. In scalar context return the number of distinct field names. =item $h->scan( \&process_header_field ) Apply a subroutine to each header field in turn. The callback routine is called with two parameters; the name of the field and a single value (a string). If a header field is multi-valued, then the routine is called once for each value. The field name passed to the callback routine has case as suggested by HTTP spec, and the headers will be visited in the recommended "Good Practice" order. Any return values of the callback routine are ignored. The loop can be broken by raising an exception (C<die>), but the caller of scan() would have to trap the exception itself. =item $h->flatten() Returns the list of pairs of keys and values. =item $h->as_string =item $h->as_string( $eol ) Return the header fields as a formatted MIME header. Since it internally uses the C<scan> method to build the string, the result will use case as suggested by HTTP spec, and it will follow recommended "Good Practice" of ordering the header fields. Long header values are not folded. The optional $eol parameter specifies the line ending sequence to use. The default is "\n". Embedded "\n" characters in header field values will be substituted with this line ending sequence. =back =head1 CONVENIENCE METHODS The most frequently used headers can also be accessed through the following convenience methods. Most of these methods can both be used to read and to set the value of a header. The header value is set if you pass an argument to the method. The old header value is always returned. If the given header did not exist then C<undef> is returned. Methods that deal with dates/times always convert their value to system time (seconds since Jan 1, 1970) and they also expect this kind of value when the header value is set. =over 4 =item $h->date This header represents the date and time at which the message was originated. I<E.g.>: $h->date(time); # set current date =item $h->expires This header gives the date and time after which the entity should be considered stale. =item $h->if_modified_since =item $h->if_unmodified_since These header fields are used to make a request conditional. If the requested resource has (or has not) been modified since the time specified in this field, then the server will return a C<304 Not Modified> response instead of the document itself. =item $h->last_modified This header indicates the date and time at which the resource was last modified. I<E.g.>: # check if document is more than 1 hour old if (my $last_mod = $h->last_modified) { if ($last_mod < time - 60*60) { ... } } =item $h->content_type The Content-Type header field indicates the media type of the message content. I<E.g.>: $h->content_type('text/html'); The value returned will be converted to lower case, and potential parameters will be chopped off and returned as a separate value if in an array context. If there is no such header field, then the empty string is returned. This makes it safe to do the following: if ($h->content_type eq 'text/html') { # we enter this place even if the real header value happens to # be 'TEXT/HTML; version=3.0' ... } =item $h->content_type_charset Returns the upper-cased charset specified in the Content-Type header. In list context return the lower-cased bare content type followed by the upper-cased charset. Both values will be C<undef> if not specified in the header. =item $h->content_is_text Returns TRUE if the Content-Type header field indicate that the content is textual. =item $h->content_is_html Returns TRUE if the Content-Type header field indicate that the content is some kind of HTML (including XHTML). This method can't be used to set Content-Type. =item $h->content_is_xhtml Returns TRUE if the Content-Type header field indicate that the content is XHTML. This method can't be used to set Content-Type. =item $h->content_is_xml Returns TRUE if the Content-Type header field indicate that the content is XML. This method can't be used to set Content-Type. =item $h->content_encoding The Content-Encoding header field is used as a modifier to the media type. When present, its value indicates what additional encoding mechanism has been applied to the resource. =item $h->content_length A decimal number indicating the size in bytes of the message content. =item $h->content_language The natural language(s) of the intended audience for the message content. The value is one or more language tags as defined by RFC 1766. Eg. "no" for some kind of Norwegian and "en-US" for English the way it is written in the US. =item $h->title The title of the document. In libwww-perl this header will be initialized automatically from the E<lt>TITLE>...E<lt>/TITLE> element of HTML documents. I<This header is no longer part of the HTTP standard.> =item $h->user_agent This header field is used in request messages and contains information about the user agent originating the request. I<E.g.>: $h->user_agent('Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.0)'); =item $h->server The server header field contains information about the software being used by the originating server program handling the request. =item $h->from This header should contain an Internet e-mail address for the human user who controls the requesting user agent. The address should be machine-usable, as defined by RFC822. E.g.: $h->from('King Kong <king@kong.com>'); I<This header is no longer part of the HTTP standard.> =item $h->referer Used to specify the address (URI) of the document from which the requested resource address was obtained. The "Free On-line Dictionary of Computing" as this to say about the word I<referer>: <World-Wide Web> A misspelling of "referrer" which somehow made it into the {HTTP} standard. A given {web page}'s referer (sic) is the {URL} of whatever web page contains the link that the user followed to the current page. Most browsers pass this information as part of a request. (1998-10-19) By popular demand C<referrer> exists as an alias for this method so you can avoid this misspelling in your programs and still send the right thing on the wire. When setting the referrer, this method removes the fragment from the given URI if it is present, as mandated by RFC2616. Note that the removal does I<not> happen automatically if using the header(), push_header() or init_header() methods to set the referrer. =item $h->www_authenticate This header must be included as part of a C<401 Unauthorized> response. The field value consist of a challenge that indicates the authentication scheme and parameters applicable to the requested URI. =item $h->proxy_authenticate This header must be included in a C<407 Proxy Authentication Required> response. =item $h->authorization =item $h->proxy_authorization A user agent that wishes to authenticate itself with a server or a proxy, may do so by including these headers. =item $h->authorization_basic This method is used to get or set an authorization header that use the "Basic Authentication Scheme". In array context it will return two values; the user name and the password. In scalar context it will return I<"uname:password"> as a single string value. When used to set the header value, it expects two arguments. I<E.g.>: $h->authorization_basic($uname, $password); The method will croak if the $uname contains a colon ':'. =item $h->proxy_authorization_basic Same as authorization_basic() but will set the "Proxy-Authorization" header instead. =back =head1 NON-CANONICALIZED FIELD NAMES The header field name spelling is normally canonicalized including the '_' to '-' translation. There are some application where this is not appropriate. Prefixing field names with ':' allow you to force a specific spelling. For example if you really want a header field name to show up as C<foo_bar> instead of "Foo-Bar", you might set it like this: $h->header(":foo_bar" => 1); These field names are returned with the ':' intact for $h->header_field_names and the $h->scan callback, but the colons do not show in $h->as_string. =head1 AUTHOR Gisle Aas <gisle@activestate.com> =head1 COPYRIGHT AND LICENSE This software is copyright (c) 1994 by Gisle Aas. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ #ABSTRACT: Class encapsulating HTTP Message headers PK ! ����"