| Filename | /usr/share/perl5/HTTP/Headers.pm |
| Statements | Executed 224 statements in 4.01ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 2 | 1 | 1 | 84µs | 89µs | HTTP::Headers::_header |
| 2 | 1 | 1 | 73µs | 162µs | HTTP::Headers::header |
| 1 | 1 | 1 | 31µs | 31µs | HTTP::Headers::new |
| 1 | 1 | 1 | 23µs | 29µs | HTTP::Headers::BEGIN@3 |
| 1 | 1 | 1 | 13µs | 86µs | HTTP::Headers::BEGIN@6 |
| 1 | 1 | 1 | 5µs | 5µs | HTTP::Headers::BEGIN@4 |
| 2 | 1 | 1 | 5µs | 5µs | HTTP::Headers::CORE:match (opcode) |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::__ANON__[:288] |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::__ANON__[:290] |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::_basic_auth |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::_date_header |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::_process_newline |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::_sorted_field_names |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::as_string |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::authorization |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::authorization_basic |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::clear |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::client_date |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::content_encoding |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::content_is_html |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::content_is_text |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::content_is_xhtml |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::content_is_xml |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::content_language |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::content_length |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::content_type |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::content_type_charset |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::date |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::expires |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::from |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::header_field_names |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::if_modified_since |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::if_unmodified_since |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::init_header |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::last_modified |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::proxy_authenticate |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::proxy_authorization |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::proxy_authorization_basic |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::push_header |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::referer |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::remove_content_headers |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::remove_header |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::scan |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::server |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::title |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::user_agent |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::warning |
| 0 | 0 | 0 | 0s | 0s | HTTP::Headers::www_authenticate |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package HTTP::Headers; | ||||
| 2 | |||||
| 3 | 3 | 32µs | 2 | 34µs | # spent 29µs (23+6) within HTTP::Headers::BEGIN@3 which was called:
# once (23µs+6µs) by LWP::UserAgent::BEGIN@10 at line 3 # spent 29µs making 1 call to HTTP::Headers::BEGIN@3
# spent 6µs making 1 call to strict::import |
| 4 | 3 | 28µs | 1 | 5µs | # spent 5µs within HTTP::Headers::BEGIN@4 which was called:
# once (5µs+0s) by LWP::UserAgent::BEGIN@10 at line 4 # spent 5µs making 1 call to HTTP::Headers::BEGIN@4 |
| 5 | |||||
| 6 | 3 | 3.48ms | 2 | 160µs | # spent 86µs (13+74) within HTTP::Headers::BEGIN@6 which was called:
# once (13µs+74µs) by LWP::UserAgent::BEGIN@10 at line 6 # spent 86µs making 1 call to HTTP::Headers::BEGIN@6
# spent 74µs making 1 call to vars::import |
| 7 | 1 | 2µs | $VERSION = "5.835"; | ||
| 8 | |||||
| 9 | # The $TRANSLATE_UNDERSCORE variable controls whether '_' can be used | ||||
| 10 | # as a replacement for '-' in header field names. | ||||
| 11 | 1 | 2µs | $TRANSLATE_UNDERSCORE = 1 unless defined $TRANSLATE_UNDERSCORE; | ||
| 12 | |||||
| 13 | # "Good Practice" order of HTTP message headers: | ||||
| 14 | # - General-Headers | ||||
| 15 | # - Request-Headers | ||||
| 16 | # - Response-Headers | ||||
| 17 | # - Entity-Headers | ||||
| 18 | |||||
| 19 | 1 | 5µs | my @general_headers = qw( | ||
| 20 | Cache-Control Connection Date Pragma Trailer Transfer-Encoding Upgrade | ||||
| 21 | Via Warning | ||||
| 22 | ); | ||||
| 23 | |||||
| 24 | 1 | 6µs | my @request_headers = qw( | ||
| 25 | Accept Accept-Charset Accept-Encoding Accept-Language | ||||
| 26 | Authorization Expect From Host | ||||
| 27 | If-Match If-Modified-Since If-None-Match If-Range If-Unmodified-Since | ||||
| 28 | Max-Forwards Proxy-Authorization Range Referer TE User-Agent | ||||
| 29 | ); | ||||
| 30 | |||||
| 31 | 1 | 3µs | my @response_headers = qw( | ||
| 32 | Accept-Ranges Age ETag Location Proxy-Authenticate Retry-After Server | ||||
| 33 | Vary WWW-Authenticate | ||||
| 34 | ); | ||||
| 35 | |||||
| 36 | 1 | 3µs | my @entity_headers = qw( | ||
| 37 | Allow Content-Encoding Content-Language Content-Length Content-Location | ||||
| 38 | Content-MD5 Content-Range Content-Type Expires Last-Modified | ||||
| 39 | ); | ||||
| 40 | |||||
| 41 | 1 | 20µs | my %entity_header = map { lc($_) => 1 } @entity_headers; | ||
| 42 | |||||
| 43 | 1 | 18µs | my @header_order = ( | ||
| 44 | @general_headers, | ||||
| 45 | @request_headers, | ||||
| 46 | @response_headers, | ||||
| 47 | @entity_headers, | ||||
| 48 | ); | ||||
| 49 | |||||
| 50 | # Make alternative representations of @header_order. This is used | ||||
| 51 | # for sorting and case matching. | ||||
| 52 | 1 | 300ns | my %header_order; | ||
| 53 | 1 | 300ns | my %standard_case; | ||
| 54 | |||||
| 55 | { | ||||
| 56 | 2 | 2µs | my $i = 0; | ||
| 57 | 1 | 3µs | for (@header_order) { | ||
| 58 | 47 | 24µs | my $lc = lc $_; | ||
| 59 | 47 | 50µs | $header_order{$lc} = ++$i; | ||
| 60 | 47 | 75µs | $standard_case{$lc} = $_; | ||
| 61 | } | ||||
| 62 | } | ||||
| 63 | |||||
| - - | |||||
| 66 | sub new | ||||
| 67 | # spent 31µs within HTTP::Headers::new which was called:
# once (31µs+0s) by LWP::UserAgent::default_headers at line 643 of LWP/UserAgent.pm | ||||
| 68 | 4 | 37µs | my($class) = shift; | ||
| 69 | my $self = bless {}, $class; | ||||
| 70 | $self->header(@_) if @_; # set up initial headers | ||||
| 71 | $self; | ||||
| 72 | } | ||||
| 73 | |||||
| 74 | |||||
| 75 | sub header | ||||
| 76 | # spent 162µs (73+89) within HTTP::Headers::header which was called 2 times, avg 81µs/call:
# 2 times (73µs+89µs) by LWP::UserAgent::default_header at line 654 of LWP/UserAgent.pm, avg 81µs/call | ||||
| 77 | 20 | 62µs | my $self = shift; | ||
| 78 | Carp::croak('Usage: $h->header($field, ...)') unless @_; | ||||
| 79 | my(@old); | ||||
| 80 | my %seen; | ||||
| 81 | while (@_) { | ||||
| 82 | my $field = shift; | ||||
| 83 | my $op = @_ ? ($seen{lc($field)}++ ? 'PUSH' : 'SET') : 'GET'; | ||||
| 84 | 2 | 89µs | @old = $self->_header($field, shift, $op); # spent 89µs making 2 calls to HTTP::Headers::_header, avg 44µs/call | ||
| 85 | } | ||||
| 86 | return @old if wantarray; | ||||
| 87 | return $old[0] if @old <= 1; | ||||
| 88 | join(", ", @old); | ||||
| 89 | } | ||||
| 90 | |||||
| 91 | sub clear | ||||
| 92 | { | ||||
| 93 | my $self = shift; | ||||
| 94 | %$self = (); | ||||
| 95 | } | ||||
| 96 | |||||
| 97 | |||||
| 98 | sub push_header | ||||
| 99 | { | ||||
| 100 | my $self = shift; | ||||
| 101 | return $self->_header(@_, 'PUSH_H') if @_ == 2; | ||||
| 102 | while (@_) { | ||||
| 103 | $self->_header(splice(@_, 0, 2), 'PUSH_H'); | ||||
| 104 | } | ||||
| 105 | } | ||||
| 106 | |||||
| 107 | |||||
| 108 | sub init_header | ||||
| 109 | { | ||||
| 110 | Carp::croak('Usage: $h->init_header($field, $val)') if @_ != 3; | ||||
| 111 | shift->_header(@_, 'INIT'); | ||||
| 112 | } | ||||
| 113 | |||||
| 114 | |||||
| 115 | sub remove_header | ||||
| 116 | { | ||||
| 117 | my($self, @fields) = @_; | ||||
| 118 | my $field; | ||||
| 119 | my @values; | ||||
| 120 | foreach $field (@fields) { | ||||
| 121 | $field =~ tr/_/-/ if $field !~ /^:/ && $TRANSLATE_UNDERSCORE; | ||||
| 122 | my $v = delete $self->{lc $field}; | ||||
| 123 | push(@values, ref($v) eq 'ARRAY' ? @$v : $v) if defined $v; | ||||
| 124 | } | ||||
| 125 | return @values; | ||||
| 126 | } | ||||
| 127 | |||||
| 128 | sub remove_content_headers | ||||
| 129 | { | ||||
| 130 | my $self = shift; | ||||
| 131 | unless (defined(wantarray)) { | ||||
| 132 | # fast branch that does not create return object | ||||
| 133 | delete @$self{grep $entity_header{$_} || /^content-/, keys %$self}; | ||||
| 134 | return; | ||||
| 135 | } | ||||
| 136 | |||||
| 137 | my $c = ref($self)->new; | ||||
| 138 | for my $f (grep $entity_header{$_} || /^content-/, keys %$self) { | ||||
| 139 | $c->{$f} = delete $self->{$f}; | ||||
| 140 | } | ||||
| 141 | $c; | ||||
| 142 | } | ||||
| 143 | |||||
| 144 | |||||
| 145 | sub _header | ||||
| 146 | # spent 89µs (84+5) within HTTP::Headers::_header which was called 2 times, avg 44µs/call:
# 2 times (84µs+5µs) by HTTP::Headers::header at line 84, avg 44µs/call | ||||
| 147 | 32 | 105µs | my($self, $field, $val, $op) = @_; | ||
| 148 | |||||
| 149 | 2 | 5µs | unless ($field =~ /^:/) { # spent 5µs making 2 calls to HTTP::Headers::CORE:match, avg 2µs/call | ||
| 150 | $field =~ tr/_/-/ if $TRANSLATE_UNDERSCORE; | ||||
| 151 | my $old = $field; | ||||
| 152 | $field = lc $field; | ||||
| 153 | unless(defined $standard_case{$field}) { | ||||
| 154 | # generate a %standard_case entry for this field | ||||
| 155 | $old =~ s/\b(\w)/\u$1/g; | ||||
| 156 | $standard_case{$field} = $old; | ||||
| 157 | } | ||||
| 158 | } | ||||
| 159 | |||||
| 160 | $op ||= defined($val) ? 'SET' : 'GET'; | ||||
| 161 | if ($op eq 'PUSH_H') { | ||||
| 162 | # Like PUSH but where we don't care about the return value | ||||
| 163 | if (exists $self->{$field}) { | ||||
| 164 | my $h = $self->{$field}; | ||||
| 165 | if (ref($h) eq 'ARRAY') { | ||||
| 166 | push(@$h, ref($val) eq "ARRAY" ? @$val : $val); | ||||
| 167 | } | ||||
| 168 | else { | ||||
| 169 | $self->{$field} = [$h, ref($val) eq "ARRAY" ? @$val : $val] | ||||
| 170 | } | ||||
| 171 | return; | ||||
| 172 | } | ||||
| 173 | $self->{$field} = $val; | ||||
| 174 | return; | ||||
| 175 | } | ||||
| 176 | |||||
| 177 | my $h = $self->{$field}; | ||||
| 178 | my @old = ref($h) eq 'ARRAY' ? @$h : (defined($h) ? ($h) : ()); | ||||
| 179 | |||||
| 180 | unless ($op eq 'GET' || ($op eq 'INIT' && @old)) { | ||||
| 181 | if (defined($val)) { | ||||
| 182 | my @new = ($op eq 'PUSH') ? @old : (); | ||||
| 183 | if (ref($val) ne 'ARRAY') { | ||||
| 184 | push(@new, $val); | ||||
| 185 | } | ||||
| 186 | else { | ||||
| 187 | push(@new, @$val); | ||||
| 188 | } | ||||
| 189 | $self->{$field} = @new > 1 ? \@new : $new[0]; | ||||
| 190 | } | ||||
| 191 | elsif ($op ne 'PUSH') { | ||||
| 192 | delete $self->{$field}; | ||||
| 193 | } | ||||
| 194 | } | ||||
| 195 | @old; | ||||
| 196 | } | ||||
| 197 | |||||
| 198 | |||||
| 199 | sub _sorted_field_names | ||||
| 200 | { | ||||
| 201 | my $self = shift; | ||||
| 202 | return [ sort { | ||||
| 203 | ($header_order{$a} || 999) <=> ($header_order{$b} || 999) || | ||||
| 204 | $a cmp $b | ||||
| 205 | } keys %$self ]; | ||||
| 206 | } | ||||
| 207 | |||||
| 208 | |||||
| 209 | sub header_field_names { | ||||
| 210 | my $self = shift; | ||||
| 211 | return map $standard_case{$_} || $_, @{ $self->_sorted_field_names }, | ||||
| 212 | if wantarray; | ||||
| 213 | return keys %$self; | ||||
| 214 | } | ||||
| 215 | |||||
| 216 | |||||
| 217 | sub scan | ||||
| 218 | { | ||||
| 219 | my($self, $sub) = @_; | ||||
| 220 | my $key; | ||||
| 221 | for $key (@{ $self->_sorted_field_names }) { | ||||
| 222 | next if substr($key, 0, 1) eq '_'; | ||||
| 223 | my $vals = $self->{$key}; | ||||
| 224 | if (ref($vals) eq 'ARRAY') { | ||||
| 225 | my $val; | ||||
| 226 | for $val (@$vals) { | ||||
| 227 | $sub->($standard_case{$key} || $key, $val); | ||||
| 228 | } | ||||
| 229 | } | ||||
| 230 | else { | ||||
| 231 | $sub->($standard_case{$key} || $key, $vals); | ||||
| 232 | } | ||||
| 233 | } | ||||
| 234 | } | ||||
| 235 | |||||
| 236 | |||||
| 237 | sub as_string | ||||
| 238 | { | ||||
| 239 | my($self, $endl) = @_; | ||||
| 240 | $endl = "\n" unless defined $endl; | ||||
| 241 | |||||
| 242 | my @result = (); | ||||
| 243 | for my $key (@{ $self->_sorted_field_names }) { | ||||
| 244 | next if index($key, '_') == 0; | ||||
| 245 | my $vals = $self->{$key}; | ||||
| 246 | if ( ref($vals) eq 'ARRAY' ) { | ||||
| 247 | for my $val (@$vals) { | ||||
| 248 | my $field = $standard_case{$key} || $key; | ||||
| 249 | $field =~ s/^://; | ||||
| 250 | if ( index($val, "\n") >= 0 ) { | ||||
| 251 | $val = _process_newline($val, $endl); | ||||
| 252 | } | ||||
| 253 | push @result, $field . ': ' . $val; | ||||
| 254 | } | ||||
| 255 | } | ||||
| 256 | else { | ||||
| 257 | my $field = $standard_case{$key} || $key; | ||||
| 258 | $field =~ s/^://; | ||||
| 259 | if ( index($vals, "\n") >= 0 ) { | ||||
| 260 | $vals = _process_newline($vals, $endl); | ||||
| 261 | } | ||||
| 262 | push @result, $field . ': ' . $vals; | ||||
| 263 | } | ||||
| 264 | } | ||||
| 265 | |||||
| 266 | join($endl, @result, ''); | ||||
| 267 | } | ||||
| 268 | |||||
| 269 | sub _process_newline { | ||||
| 270 | local $_ = shift; | ||||
| 271 | my $endl = shift; | ||||
| 272 | # must handle header values with embedded newlines with care | ||||
| 273 | s/\s+$//; # trailing newlines and space must go | ||||
| 274 | s/\n(\x0d?\n)+/\n/g; # no empty lines | ||||
| 275 | s/\n([^\040\t])/\n $1/g; # intial space for continuation | ||||
| 276 | s/\n/$endl/g; # substitute with requested line ending | ||||
| 277 | $_; | ||||
| 278 | } | ||||
| 279 | |||||
| - - | |||||
| 282 | 3 | 10µs | if (eval { require Storable; 1 }) { | ||
| 283 | *clone = \&Storable::dclone; | ||||
| 284 | } else { | ||||
| 285 | *clone = sub { | ||||
| 286 | my $self = shift; | ||||
| 287 | my $clone = HTTP::Headers->new; | ||||
| 288 | $self->scan(sub { $clone->push_header(@_);} ); | ||||
| 289 | $clone; | ||||
| 290 | }; | ||||
| 291 | } | ||||
| 292 | |||||
| 293 | |||||
| 294 | sub _date_header | ||||
| 295 | { | ||||
| 296 | require HTTP::Date; | ||||
| 297 | my($self, $header, $time) = @_; | ||||
| 298 | my($old) = $self->_header($header); | ||||
| 299 | if (defined $time) { | ||||
| 300 | $self->_header($header, HTTP::Date::time2str($time)); | ||||
| 301 | } | ||||
| 302 | $old =~ s/;.*// if defined($old); | ||||
| 303 | HTTP::Date::str2time($old); | ||||
| 304 | } | ||||
| 305 | |||||
| 306 | |||||
| 307 | sub date { shift->_date_header('Date', @_); } | ||||
| 308 | sub expires { shift->_date_header('Expires', @_); } | ||||
| 309 | sub if_modified_since { shift->_date_header('If-Modified-Since', @_); } | ||||
| 310 | sub if_unmodified_since { shift->_date_header('If-Unmodified-Since', @_); } | ||||
| 311 | sub last_modified { shift->_date_header('Last-Modified', @_); } | ||||
| 312 | |||||
| 313 | # This is used as a private LWP extension. The Client-Date header is | ||||
| 314 | # added as a timestamp to a response when it has been received. | ||||
| 315 | sub client_date { shift->_date_header('Client-Date', @_); } | ||||
| 316 | |||||
| 317 | # The retry_after field is dual format (can also be a expressed as | ||||
| 318 | # number of seconds from now), so we don't provide an easy way to | ||||
| 319 | # access it until we have know how both these interfaces can be | ||||
| 320 | # addressed. One possibility is to return a negative value for | ||||
| 321 | # relative seconds and a positive value for epoch based time values. | ||||
| 322 | #sub retry_after { shift->_date_header('Retry-After', @_); } | ||||
| 323 | |||||
| 324 | sub content_type { | ||||
| 325 | my $self = shift; | ||||
| 326 | my $ct = $self->{'content-type'}; | ||||
| 327 | $self->{'content-type'} = shift if @_; | ||||
| 328 | $ct = $ct->[0] if ref($ct) eq 'ARRAY'; | ||||
| 329 | return '' unless defined($ct) && length($ct); | ||||
| 330 | my @ct = split(/;\s*/, $ct, 2); | ||||
| 331 | for ($ct[0]) { | ||||
| 332 | s/\s+//g; | ||||
| 333 | $_ = lc($_); | ||||
| 334 | } | ||||
| 335 | wantarray ? @ct : $ct[0]; | ||||
| 336 | } | ||||
| 337 | |||||
| 338 | sub content_type_charset { | ||||
| 339 | my $self = shift; | ||||
| 340 | require HTTP::Headers::Util; | ||||
| 341 | my $h = $self->{'content-type'}; | ||||
| 342 | $h = $h->[0] if ref($h); | ||||
| 343 | $h = "" unless defined $h; | ||||
| 344 | my @v = HTTP::Headers::Util::split_header_words($h); | ||||
| 345 | if (@v) { | ||||
| 346 | my($ct, undef, %ct_param) = @{$v[0]}; | ||||
| 347 | my $charset = $ct_param{charset}; | ||||
| 348 | if ($ct) { | ||||
| 349 | $ct = lc($ct); | ||||
| 350 | $ct =~ s/\s+//; | ||||
| 351 | } | ||||
| 352 | if ($charset) { | ||||
| 353 | $charset = uc($charset); | ||||
| 354 | $charset =~ s/^\s+//; $charset =~ s/\s+\z//; | ||||
| 355 | undef($charset) if $charset eq ""; | ||||
| 356 | } | ||||
| 357 | return $ct, $charset if wantarray; | ||||
| 358 | return $charset; | ||||
| 359 | } | ||||
| 360 | return undef, undef if wantarray; | ||||
| 361 | return undef; | ||||
| 362 | } | ||||
| 363 | |||||
| 364 | sub content_is_text { | ||||
| 365 | my $self = shift; | ||||
| 366 | return $self->content_type =~ m,^text/,; | ||||
| 367 | } | ||||
| 368 | |||||
| 369 | sub content_is_html { | ||||
| 370 | my $self = shift; | ||||
| 371 | return $self->content_type eq 'text/html' || $self->content_is_xhtml; | ||||
| 372 | } | ||||
| 373 | |||||
| 374 | sub content_is_xhtml { | ||||
| 375 | my $ct = shift->content_type; | ||||
| 376 | return $ct eq "application/xhtml+xml" || | ||||
| 377 | $ct eq "application/vnd.wap.xhtml+xml"; | ||||
| 378 | } | ||||
| 379 | |||||
| 380 | sub content_is_xml { | ||||
| 381 | my $ct = shift->content_type; | ||||
| 382 | return 1 if $ct eq "text/xml"; | ||||
| 383 | return 1 if $ct eq "application/xml"; | ||||
| 384 | return 1 if $ct =~ /\+xml$/; | ||||
| 385 | return 0; | ||||
| 386 | } | ||||
| 387 | |||||
| 388 | sub referer { | ||||
| 389 | my $self = shift; | ||||
| 390 | if (@_ && $_[0] =~ /#/) { | ||||
| 391 | # Strip fragment per RFC 2616, section 14.36. | ||||
| 392 | my $uri = shift; | ||||
| 393 | if (ref($uri)) { | ||||
| 394 | $uri = $uri->clone; | ||||
| 395 | $uri->fragment(undef); | ||||
| 396 | } | ||||
| 397 | else { | ||||
| 398 | $uri =~ s/\#.*//; | ||||
| 399 | } | ||||
| 400 | unshift @_, $uri; | ||||
| 401 | } | ||||
| 402 | ($self->_header('Referer', @_))[0]; | ||||
| 403 | } | ||||
| 404 | 1 | 1µs | *referrer = \&referer; # on tchrist's request | ||
| 405 | |||||
| 406 | sub title { (shift->_header('Title', @_))[0] } | ||||
| 407 | sub content_encoding { (shift->_header('Content-Encoding', @_))[0] } | ||||
| 408 | sub content_language { (shift->_header('Content-Language', @_))[0] } | ||||
| 409 | sub content_length { (shift->_header('Content-Length', @_))[0] } | ||||
| 410 | |||||
| 411 | sub user_agent { (shift->_header('User-Agent', @_))[0] } | ||||
| 412 | sub server { (shift->_header('Server', @_))[0] } | ||||
| 413 | |||||
| 414 | sub from { (shift->_header('From', @_))[0] } | ||||
| 415 | sub warning { (shift->_header('Warning', @_))[0] } | ||||
| 416 | |||||
| 417 | sub www_authenticate { (shift->_header('WWW-Authenticate', @_))[0] } | ||||
| 418 | sub authorization { (shift->_header('Authorization', @_))[0] } | ||||
| 419 | |||||
| 420 | sub proxy_authenticate { (shift->_header('Proxy-Authenticate', @_))[0] } | ||||
| 421 | sub proxy_authorization { (shift->_header('Proxy-Authorization', @_))[0] } | ||||
| 422 | |||||
| 423 | sub authorization_basic { shift->_basic_auth("Authorization", @_) } | ||||
| 424 | sub proxy_authorization_basic { shift->_basic_auth("Proxy-Authorization", @_) } | ||||
| 425 | |||||
| 426 | sub _basic_auth { | ||||
| 427 | require MIME::Base64; | ||||
| 428 | my($self, $h, $user, $passwd) = @_; | ||||
| 429 | my($old) = $self->_header($h); | ||||
| 430 | if (defined $user) { | ||||
| 431 | Carp::croak("Basic authorization user name can't contain ':'") | ||||
| 432 | if $user =~ /:/; | ||||
| 433 | $passwd = '' unless defined $passwd; | ||||
| 434 | $self->_header($h => 'Basic ' . | ||||
| 435 | MIME::Base64::encode("$user:$passwd", '')); | ||||
| 436 | } | ||||
| 437 | if (defined $old && $old =~ s/^\s*Basic\s+//) { | ||||
| 438 | my $val = MIME::Base64::decode($old); | ||||
| 439 | return $val unless wantarray; | ||||
| 440 | return split(/:/, $val, 2); | ||||
| 441 | } | ||||
| 442 | return; | ||||
| 443 | } | ||||
| 444 | |||||
| 445 | |||||
| 446 | 1 | 36µs | 1; | ||
| 447 | |||||
| 448 | __END__ | ||||
# spent 5µs within HTTP::Headers::CORE:match which was called 2 times, avg 2µs/call:
# 2 times (5µs+0s) by HTTP::Headers::_header at line 149, avg 2µs/call |