Filename | /usr/share/perl5/HTTP/Headers.pm |
Statements | Executed 224 statements in 3.36ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
2 | 1 | 1 | 44µs | 45µs | _header | HTTP::Headers::
2 | 1 | 1 | 30µs | 75µs | header | HTTP::Headers::
1 | 1 | 1 | 21µs | 27µs | BEGIN@3 | HTTP::Headers::
1 | 1 | 1 | 12µs | 12µs | new | HTTP::Headers::
1 | 1 | 1 | 11µs | 69µs | BEGIN@6 | HTTP::Headers::
1 | 1 | 1 | 6µs | 6µs | BEGIN@4 | HTTP::Headers::
2 | 1 | 1 | 1µs | 1µs | CORE:match (opcode) | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | __ANON__[:288] | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | __ANON__[:290] | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | _basic_auth | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | _date_header | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | _process_newline | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | _sorted_field_names | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | as_string | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | authorization | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | authorization_basic | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | clear | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | client_date | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | content_encoding | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | content_is_html | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | content_is_text | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | content_is_xhtml | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | content_is_xml | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | content_language | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | content_length | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | content_type | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | content_type_charset | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | date | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | expires | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | from | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | header_field_names | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | if_modified_since | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | if_unmodified_since | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | init_header | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | last_modified | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | proxy_authenticate | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | proxy_authorization | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | proxy_authorization_basic | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | push_header | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | referer | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | remove_content_headers | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | remove_header | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | scan | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | server | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | title | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | user_agent | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | warning | HTTP::Headers::
0 | 0 | 0 | 0s | 0s | www_authenticate | HTTP::Headers::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package HTTP::Headers; | ||||
2 | |||||
3 | 3 | 30µs | 2 | 33µs | # spent 27µs (21+6) within HTTP::Headers::BEGIN@3 which was called:
# once (21µs+6µs) by LWP::UserAgent::BEGIN@10 at line 3 # spent 27µs making 1 call to HTTP::Headers::BEGIN@3
# spent 6µs making 1 call to strict::import |
4 | 3 | 29µs | 1 | 6µs | # spent 6µs within HTTP::Headers::BEGIN@4 which was called:
# once (6µs+0s) by LWP::UserAgent::BEGIN@10 at line 4 # spent 6µs making 1 call to HTTP::Headers::BEGIN@4 |
5 | |||||
6 | 3 | 2.84ms | 2 | 127µs | # spent 69µs (11+58) within HTTP::Headers::BEGIN@6 which was called:
# once (11µs+58µs) by LWP::UserAgent::BEGIN@10 at line 6 # spent 69µs making 1 call to HTTP::Headers::BEGIN@6
# spent 58µs making 1 call to vars::import |
7 | 1 | 1µ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 | 700ns | $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 | 3µs | my @general_headers = qw( | ||
20 | Cache-Control Connection Date Pragma Trailer Transfer-Encoding Upgrade | ||||
21 | Via Warning | ||||
22 | ); | ||||
23 | |||||
24 | 1 | 4µ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 | 2µs | my @response_headers = qw( | ||
32 | Accept-Ranges Age ETag Location Proxy-Authenticate Retry-After Server | ||||
33 | Vary WWW-Authenticate | ||||
34 | ); | ||||
35 | |||||
36 | 1 | 2µ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 | 14µs | my %entity_header = map { lc($_) => 1 } @entity_headers; | ||
42 | |||||
43 | 1 | 11µ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 | 200ns | my %header_order; | ||
53 | 1 | 200ns | my %standard_case; | ||
54 | |||||
55 | { | ||||
56 | 2 | 1µs | my $i = 0; | ||
57 | 1 | 2µs | for (@header_order) { | ||
58 | 47 | 14µs | my $lc = lc $_; | ||
59 | 47 | 34µs | $header_order{$lc} = ++$i; | ||
60 | 47 | 44µs | $standard_case{$lc} = $_; | ||
61 | } | ||||
62 | } | ||||
63 | |||||
- - | |||||
66 | sub new | ||||
67 | # spent 12µs within HTTP::Headers::new which was called:
# once (12µs+0s) by LWP::UserAgent::default_headers at line 643 of LWP/UserAgent.pm | ||||
68 | 1 | 1µs | my($class) = shift; | ||
69 | 1 | 8µs | my $self = bless {}, $class; | ||
70 | 1 | 500ns | $self->header(@_) if @_; # set up initial headers | ||
71 | 1 | 5µs | $self; | ||
72 | } | ||||
73 | |||||
74 | |||||
75 | sub header | ||||
76 | # spent 75µs (30+45) within HTTP::Headers::header which was called 2 times, avg 37µs/call:
# 2 times (30µs+45µs) by LWP::UserAgent::default_header at line 654 of LWP/UserAgent.pm, avg 37µs/call | ||||
77 | 2 | 1µs | my $self = shift; | ||
78 | 2 | 800ns | Carp::croak('Usage: $h->header($field, ...)') unless @_; | ||
79 | 2 | 800ns | my(@old); | ||
80 | 2 | 700ns | my %seen; | ||
81 | 2 | 2µs | while (@_) { | ||
82 | 2 | 900ns | my $field = shift; | ||
83 | 2 | 5µs | my $op = @_ ? ($seen{lc($field)}++ ? 'PUSH' : 'SET') : 'GET'; | ||
84 | 2 | 9µs | 2 | 45µs | @old = $self->_header($field, shift, $op); # spent 45µs making 2 calls to HTTP::Headers::_header, avg 23µs/call |
85 | } | ||||
86 | 2 | 1µs | return @old if wantarray; | ||
87 | 2 | 8µs | 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 45µs (44+1) within HTTP::Headers::_header which was called 2 times, avg 23µs/call:
# 2 times (44µs+1µs) by HTTP::Headers::header at line 84, avg 23µs/call | ||||
147 | 2 | 3µs | my($self, $field, $val, $op) = @_; | ||
148 | |||||
149 | 2 | 11µs | 2 | 1µs | unless ($field =~ /^:/) { # spent 1µs making 2 calls to HTTP::Headers::CORE:match, avg 700ns/call |
150 | 2 | 3µs | $field =~ tr/_/-/ if $TRANSLATE_UNDERSCORE; | ||
151 | 2 | 1µs | my $old = $field; | ||
152 | 2 | 1µs | $field = lc $field; | ||
153 | 2 | 2µs | 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 | 2 | 800ns | $op ||= defined($val) ? 'SET' : 'GET'; | ||
161 | 2 | 2µs | 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 | 2 | 2µs | my $h = $self->{$field}; | ||
178 | 2 | 3µs | my @old = ref($h) eq 'ARRAY' ? @$h : (defined($h) ? ($h) : ()); | ||
179 | |||||
180 | 2 | 2µs | unless ($op eq 'GET' || ($op eq 'INIT' && @old)) { | ||
181 | 2 | 2µs | if (defined($val)) { | ||
182 | 2 | 2µs | my @new = ($op eq 'PUSH') ? @old : (); | ||
183 | 2 | 3µs | if (ref($val) ne 'ARRAY') { | ||
184 | push(@new, $val); | ||||
185 | } | ||||
186 | else { | ||||
187 | push(@new, @$val); | ||||
188 | } | ||||
189 | 2 | 4µs | $self->{$field} = @new > 1 ? \@new : $new[0]; | ||
190 | } | ||||
191 | elsif ($op ne 'PUSH') { | ||||
192 | delete $self->{$field}; | ||||
193 | } | ||||
194 | } | ||||
195 | 2 | 7µs | @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 | 177µ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 | 2µ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 | 54µs | 1; | ||
447 | |||||
448 | __END__ | ||||
# spent 1µs within HTTP::Headers::CORE:match which was called 2 times, avg 700ns/call:
# 2 times (1µs+0s) by HTTP::Headers::_header at line 149, avg 700ns/call |