First pass at adding key files
This commit is contained in:
		
							
								
								
									
										1430
									
								
								site/slowtwitch.com/cgi-bin/articles/GT/WWW/http.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1430
									
								
								site/slowtwitch.com/cgi-bin/articles/GT/WWW/http.pm
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										649
									
								
								site/slowtwitch.com/cgi-bin/articles/GT/WWW/http/Header.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										649
									
								
								site/slowtwitch.com/cgi-bin/articles/GT/WWW/http/Header.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,649 @@
 | 
			
		||||
# ====================================================================
 | 
			
		||||
# Gossamer Threads Module Library - http://gossamer-threads.com/
 | 
			
		||||
#
 | 
			
		||||
#   GT::WWW::http::Header
 | 
			
		||||
#   Author: Jason Rhinelander
 | 
			
		||||
#   CVS Info : 087,071,086,086,085      
 | 
			
		||||
#   $Id: Header.pm,v 1.8 2004/02/17 01:33:08 jagerman Exp $
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
 | 
			
		||||
# ====================================================================
 | 
			
		||||
#
 | 
			
		||||
# Description:
 | 
			
		||||
#   Header object for GT::WWW::http request/response headers.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
package GT::WWW::http::Header;
 | 
			
		||||
use strict;
 | 
			
		||||
 | 
			
		||||
use Carp;
 | 
			
		||||
use GT::Socket::Client qw/CRLF/;
 | 
			
		||||
use overload
 | 
			
		||||
    '""' => \&format_headers,
 | 
			
		||||
    bool => \&boolean;
 | 
			
		||||
 | 
			
		||||
my $ctls = '\x00-\x1f\x7f'; # Control characters (CTL in HTTP 1.1 RFC 2616)
 | 
			
		||||
my $ctls_without_tab = '\x00-\x08\x0a-\x1f\x7f';
 | 
			
		||||
my $separators = '()<>@,;:\\\\"/\[\]?={} \t'; # Separators
 | 
			
		||||
my $token = "[^$ctls$separators]"; # HTTP "token" (RFC 2616)
 | 
			
		||||
my $quoted_string = qq{"((?:\\\\.|[^$ctls_without_tab"])*)"}; # HTTP 1.1 quoted-string.
 | 
			
		||||
 | 
			
		||||
my %Private;
 | 
			
		||||
 | 
			
		||||
sub new {
 | 
			
		||||
    my $class = shift;
 | 
			
		||||
    $class = ref $class if ref $class;
 | 
			
		||||
    my $self = [];
 | 
			
		||||
    bless $self, $class;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub boolean { 1 } # So you can you do things like: $header or die
 | 
			
		||||
 | 
			
		||||
# Adds one or more headers. Takes a list of headers => value pairs.
 | 
			
		||||
# Without arguments, returns a list of all header names.
 | 
			
		||||
# With just one argument, returns all value(s) for that header (case-
 | 
			
		||||
# insensitive).
 | 
			
		||||
# When setting headers, you can pass in an array reference for the header
 | 
			
		||||
# value. The array will be passed as a list to join_words, and the return used
 | 
			
		||||
# as the header value.
 | 
			
		||||
 | 
			
		||||
# Sets a _join_words separator to something other than , - typically ;
 | 
			
		||||
sub _separator {
 | 
			
		||||
    my ($self, $sep) = @_;
 | 
			
		||||
    $Private{$self}->{separator} = $sep if $sep;
 | 
			
		||||
}
 | 
			
		||||
# Forces _join_words to put "quotes" around values.  You should call this, add
 | 
			
		||||
# the header that needs the quotes, then call ->_unforce_quotes;.
 | 
			
		||||
sub _force_quotes {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    $Private{$self}->{force_quotes} = 1;
 | 
			
		||||
}
 | 
			
		||||
sub _unforce_quotes {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    $Private{$self}->{force_quotes} = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub header {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    if (@_ == 1) {
 | 
			
		||||
        # Requesting a header, ie. $obj->header("Content-Type")
 | 
			
		||||
        my $header = lc shift;
 | 
			
		||||
        my @return;
 | 
			
		||||
        for (my $i = 0; $i < @$self; $i += 2) {
 | 
			
		||||
            if (lc $self->[$i] eq $header) {
 | 
			
		||||
                push @return, $self->[$i + 1];
 | 
			
		||||
                last unless wantarray;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return wantarray ? @return : $return[0];
 | 
			
		||||
    }
 | 
			
		||||
    elsif (@_) {
 | 
			
		||||
        @_ % 2 and croak "Invalid parameters to header: Odd number of elements passed to header()";
 | 
			
		||||
 | 
			
		||||
        while (@_) {
 | 
			
		||||
            my ($k, $v) = splice @_, 0, 2;
 | 
			
		||||
            if (ref $v eq 'ARRAY') {
 | 
			
		||||
                $v = $self->join_words(@$v);
 | 
			
		||||
            }
 | 
			
		||||
            push @$self, $k, $v;
 | 
			
		||||
        }
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        my @return;
 | 
			
		||||
        for (my $i = 0; $i < @$self; $i++) {
 | 
			
		||||
            push @return, $self->[$i];
 | 
			
		||||
        }
 | 
			
		||||
        return @return;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub header_words {
 | 
			
		||||
    my ($self, $header) = @_;
 | 
			
		||||
    $header or croak "Usage: \$header->header_words(HEADER_NAME)";
 | 
			
		||||
 | 
			
		||||
    my @result;
 | 
			
		||||
    for (my $i = 0; $i < @$self; $i += 2) {
 | 
			
		||||
        if (lc $self->[$i] eq lc $header) {
 | 
			
		||||
            push @result, $self->split_words($self->[$i + 1]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return @result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub split_words {
 | 
			
		||||
    shift if $_[0] and UNIVERSAL::isa($_[0], __PACKAGE__);
 | 
			
		||||
    my $str = shift or return ();
 | 
			
		||||
    my @result;
 | 
			
		||||
    # Pretend $str is: video/x-mng,image/png, foo=bar, image/gif;q=0.3,asdf/zxcv="y,uc;k";q="0.2";blah="a;b,c",*/*;q=0.1
 | 
			
		||||
    while (length $str) {
 | 
			
		||||
        if ($str =~ s/^\s*([^$ctls\s=,;]+)\s*//) { # parameter 'token' or 'attribute'
 | 
			
		||||
            push @result, $1;
 | 
			
		||||
 | 
			
		||||
            my @val;
 | 
			
		||||
            # The goal here is to get this array containing (given the above example) undef for
 | 
			
		||||
            # "video/x-mng", "bar" for "foo", [undef, "q", "0.3"] for "image/gif",
 | 
			
		||||
            # ["y,uc;k", "q", "0.2", "blah", "a;b,c"] for "asdf/zxcv".
 | 
			
		||||
 | 
			
		||||
            # First, handle an = clause, such as '=bar', or '="y,uc;k"' 
 | 
			
		||||
            if ($str =~ s/^=\s*$quoted_string//) { # quoted string (e.g. "y,uc;k")
 | 
			
		||||
                (my $val = $1) =~ s/\\(.)/$1/g;
 | 
			
		||||
                push @val, $val;
 | 
			
		||||
            }
 | 
			
		||||
            elsif ($str =~ s/^=\s*([^$ctls\s;,]*)//) { # some unquoted value (e.g. bar)
 | 
			
		||||
                push @val, $1;
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                push @val, undef;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            # Now look for continuing values (e.g. ;q="0.2";blah="a;b,c")
 | 
			
		||||
            while ($str =~ s/^;([^$ctls\s=,;]+)\s*//) {
 | 
			
		||||
                push @val, $1;
 | 
			
		||||
                # Look for an = clause, such as ="a;b,c"
 | 
			
		||||
                if ($str =~ s/^=\s*$quoted_string//) { # quoted string (e.g. "a;b,c")
 | 
			
		||||
                    (my $val = $1) =~ s/\\(.)/$1/g;
 | 
			
		||||
                    push @val, $val;
 | 
			
		||||
                }
 | 
			
		||||
                elsif ($str =~ s/^=\s*([^$ctls\s;,]*)//) { # some unquoted value (e.g. bar)
 | 
			
		||||
                    push @val, $1;
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    push @val, undef;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            push @result, @val == 1 ? $val[0] : \@val;
 | 
			
		||||
        }
 | 
			
		||||
        elsif ($str !~ s/^\s*[,;\s]//) {
 | 
			
		||||
            local $" = "|";
 | 
			
		||||
            die "Invalid header encountered: '$str' (Found \@result=(@result))";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Takes a header and header word, and returns true if the header word is
 | 
			
		||||
# present in the header. For example,
 | 
			
		||||
# $header->contains(Expect => '100-continue')
 | 
			
		||||
# will return true for the header:
 | 
			
		||||
# Expect: foo=bar, 100-continue, bar=foo
 | 
			
		||||
sub contains {
 | 
			
		||||
    my ($self, $header, $word) = @_;
 | 
			
		||||
    $header and $word or croak 'Usage: $header->contains(Header => Header_Word)';
 | 
			
		||||
 | 
			
		||||
    my @words = $self->header_words($header);
 | 
			
		||||
    for (my $i = 0; $i < @words; $i += 2) {
 | 
			
		||||
        if ($words[$i] eq $word) {
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return undef;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub join_words {
 | 
			
		||||
    my $self;
 | 
			
		||||
    $self = shift if $_[0] and UNIVERSAL::isa($_[0], __PACKAGE__);
 | 
			
		||||
    my @words = @_;
 | 
			
		||||
    my @encoded;
 | 
			
		||||
    for (my $i = 0; $i < @words; $i += 2) {
 | 
			
		||||
        my ($k, $v) = @words[$i, $i + 1];
 | 
			
		||||
        my @pairs = ($k, ref $v eq 'ARRAY' ? @$v : $v);
 | 
			
		||||
 | 
			
		||||
        @pairs % 2 and croak "Invalid composite value passed in for word '$k': Even number of elements in array ref";
 | 
			
		||||
 | 
			
		||||
        my @str;
 | 
			
		||||
        while (@pairs) {
 | 
			
		||||
            my ($word, $value) = splice @pairs, 0, 2;
 | 
			
		||||
            $word =~ /^[^$ctls\s=;,]+$/
 | 
			
		||||
                or croak "Unable to join: word contains invalid characters: '$word'";
 | 
			
		||||
            my $str = $word;
 | 
			
		||||
            if (defined $value) {
 | 
			
		||||
                $value =~ /[$ctls_without_tab]/
 | 
			
		||||
                    and croak "Unable to join: word value for word '$word' contains control characters: '$value'";
 | 
			
		||||
                $str .= '=';
 | 
			
		||||
                if ((not $self or not $Private{$self}->{force_quotes}) and $value =~ /^$token+$/) {
 | 
			
		||||
                    # If it only contains "token" characters, we don't need to quote it
 | 
			
		||||
                    $str .= $value;
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    $value =~ s/([\\"])/\\$1/g;
 | 
			
		||||
                    $str .= qq'"$value"';
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            push @str, $str;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        push @encoded, join ';', @str;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return join "$Private{$self}->{separator} ", @encoded
 | 
			
		||||
        if $self and $Private{$self}->{separator};
 | 
			
		||||
 | 
			
		||||
    return join ', ', @encoded;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Deletes a word from a header's value. If the word is present more than once,
 | 
			
		||||
# all forms are removed. Returned is, in scalar context, an integer indicating
 | 
			
		||||
# how many headers were removed (0 for no words (or no header) found). In list
 | 
			
		||||
# context, you get a list of all the values removed, or undef for valueless
 | 
			
		||||
# words.
 | 
			
		||||
sub delete_header_word {
 | 
			
		||||
    my ($self, $header, $word) = @_;
 | 
			
		||||
    my @ret;
 | 
			
		||||
    $header and $word or croak 'Usage: $header->delete_header_word(HEADER, WORD)';
 | 
			
		||||
    for (my $i = 0; $i < @$self; $i += 2) {
 | 
			
		||||
        if (lc $self->[$i] eq lc $header) {
 | 
			
		||||
            my @words = $self->split_words($self->[$i + 1]);
 | 
			
		||||
            my $found;
 | 
			
		||||
            for (my $j = 0; $j < @words; $j += 2) {
 | 
			
		||||
                if ($words[$j] eq $word) {
 | 
			
		||||
                    $found++;
 | 
			
		||||
                    push @ret, $words[$j + 1];
 | 
			
		||||
                    splice @words, $j, 2;
 | 
			
		||||
                    $j -= 2;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if ($found and @words) {
 | 
			
		||||
                $self->[$i + 1] = $self->join_words(@words);
 | 
			
		||||
            }
 | 
			
		||||
            elsif ($found) { # This header contains only the header word
 | 
			
		||||
                splice @$self, $i, 2;
 | 
			
		||||
                $i -= 2;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ret; # If the sub is called in scalar context, so is this
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Just like header(), but first deletes the headers to be added. Hence,
 | 
			
		||||
# $obj->replace_header($obj->header) should be a no-op.
 | 
			
		||||
sub replace_header {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    croak "Invalid parameters to replace_header: \$obj->replace_header(KEY => VALUE[, KEY => VALUE, ...]);"
 | 
			
		||||
        if !@_ or @_ % 2;
 | 
			
		||||
    my %headers;
 | 
			
		||||
    for (my $i = 0; $i < @_; $i += 2) {
 | 
			
		||||
        $headers{$_[$i]}++;
 | 
			
		||||
    }
 | 
			
		||||
    $self->delete_header(keys %headers);
 | 
			
		||||
 | 
			
		||||
    $self->header(@_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub format_headers {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    return '' if !@$self;
 | 
			
		||||
    my $return = '';
 | 
			
		||||
    for (my $i = 0; $i < @$self; $i += 2) {
 | 
			
		||||
        my ($key, $value) = @$self[$i, $i + 1];
 | 
			
		||||
        # Valid characters from HTTP/1.1 RFC, section 4.2 (page 32)
 | 
			
		||||
        $key   =~ s|([$ctls$separators()<>@,;:\\"/\[\]?={} \t])|sprintf "%%%02X", ord $1|eg;
 | 
			
		||||
        $value =~ s|([$ctls])|sprintf "%%%02X", ord $1|eg;
 | 
			
		||||
        $return .= "$key: $value" . CRLF;
 | 
			
		||||
    }
 | 
			
		||||
    $return .= CRLF;
 | 
			
		||||
    return $return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Clears all headers set for the current object.
 | 
			
		||||
sub clear_headers {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    $#$self = -1;
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Deletes one or more headers. Takes a list of headers to remove.
 | 
			
		||||
sub delete_header {
 | 
			
		||||
    my ($self, @headers) = @_;
 | 
			
		||||
    return 0 unless @$self;
 | 
			
		||||
    my $headers = join "|", map quotemeta, @headers;
 | 
			
		||||
    my $found;
 | 
			
		||||
    for (my $i = 0; $i < @$self; $i += 2) {
 | 
			
		||||
        if ($self->[$i] =~ /^(?:$headers)$/i) {
 | 
			
		||||
            splice @$self, $i, 2;
 | 
			
		||||
            $i -= 2;
 | 
			
		||||
            $found++;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return $found;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DESTROY {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    delete $Private{$self};
 | 
			
		||||
    1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
 | 
			
		||||
__END__
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
GT::WWW::http::Header - Module for GT::WWW::http request/response headers.
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
Typically:
 | 
			
		||||
 | 
			
		||||
    # Assuming $www is a GT::WWW::http object
 | 
			
		||||
    my $request_header = $www->header;
 | 
			
		||||
 | 
			
		||||
    # Set a header:
 | 
			
		||||
    $request_header->header('Some-Http-Header' => 'Header value');
 | 
			
		||||
 | 
			
		||||
    # After making a request:
 | 
			
		||||
    my $response_header = $www->response->header;
 | 
			
		||||
    # -- or --
 | 
			
		||||
    my $response_header = $response->header; # $response is the return of, e.g. $www->get
 | 
			
		||||
 | 
			
		||||
Much more advanced headers can be set and determined, using the various methods
 | 
			
		||||
available as described below.
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This module provides an easy to use yet powerful header retrieval/manipulation
 | 
			
		||||
object suitable for most HTTP headers.
 | 
			
		||||
 | 
			
		||||
=head1 METHODS
 | 
			
		||||
 | 
			
		||||
First, a note about the methods described which add/change/delete headers: such
 | 
			
		||||
methods should only be called on a request header, and only before making a
 | 
			
		||||
request.  Although nothing prevents you from making changes to the request
 | 
			
		||||
header after having made the request, or from changing the headers of a
 | 
			
		||||
response header object, such behaviour should be considered very bad practise
 | 
			
		||||
and is B<strongly> discouraged.
 | 
			
		||||
 | 
			
		||||
=head2 header
 | 
			
		||||
 | 
			
		||||
This is the most commonly used method as it is used both to add and retrieve
 | 
			
		||||
headers, depending on its usage.  The examples below assume the following
 | 
			
		||||
header:
 | 
			
		||||
 | 
			
		||||
    Date: Sun, 12 Jan 2003 08:21:21 GMT
 | 
			
		||||
    Server: Apache
 | 
			
		||||
    Keep-Alive: timeout=15, max=100
 | 
			
		||||
    Connection: Keep-Alive
 | 
			
		||||
    Content-Type: text/html
 | 
			
		||||
    Content-Encoding: gzip
 | 
			
		||||
    Content-Length: 3215
 | 
			
		||||
    X-Foo: bar1
 | 
			
		||||
    X-Foo: bar2, bar3
 | 
			
		||||
 | 
			
		||||
With no arguments, a list of all the header names is returned.  Given the
 | 
			
		||||
example, the following list would be returned:
 | 
			
		||||
 | 
			
		||||
    ('Date', 'Server', 'Keep-Alive', 'Connection', 'Content-Type', 'Content-Encoding', 'Content-Length', 'X-Foo', 'X-Foo')
 | 
			
		||||
 | 
			
		||||
With a single argument, a list of value(s) for headers of that name are
 | 
			
		||||
returned.  In scalar context, only the first value is returned. In list
 | 
			
		||||
context, a list of all values is returned.  Note that the header named passed
 | 
			
		||||
in is case-insensitive.
 | 
			
		||||
 | 
			
		||||
    my $server = $header->header('server'); # returns 'Apache'
 | 
			
		||||
    my $foo = $header->header('X-Foo'); # returns 'bar1'
 | 
			
		||||
    my @foo = $header->header('x-Foo'); # returns ('bar1', 'bar2, bar3')
 | 
			
		||||
 | 
			
		||||
Finally, when more than one argument is provided, header values are set.  At
 | 
			
		||||
its simplest level, it takes a list of key => value pairs (NOT a hash, since
 | 
			
		||||
duplicate keys are possible) of headers to set.  So, to set the headers
 | 
			
		||||
'Server' and 'Content-Length' above at once, you could call:
 | 
			
		||||
 | 
			
		||||
    $header->header(Server => 'Apache', 'Content-Length' => 3215);
 | 
			
		||||
 | 
			
		||||
Or, if you prefer:
 | 
			
		||||
 | 
			
		||||
    $header->header(Server => 'Apache');
 | 
			
		||||
    $header->header('Content-Length' => 3215);
 | 
			
		||||
 | 
			
		||||
Note that the order in which headers are added is preserved, for times when the
 | 
			
		||||
order of headers is important.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
B<WARNING>: Before reading the below information, you should first know that it
 | 
			
		||||
describes advanced usage of the header() method and requires have a grasp of
 | 
			
		||||
the intricacies of HTTP headers; the following is _not_ required knowledge for
 | 
			
		||||
typical GT::WWW use.
 | 
			
		||||
 | 
			
		||||
Consider the above Keep-Alive header an example.  Instead of specifying:
 | 
			
		||||
 | 
			
		||||
    $header->header('Keep-Alive' => 'timeout=15, max=100');
 | 
			
		||||
 | 
			
		||||
you could alternately write it as:
 | 
			
		||||
 | 
			
		||||
    $header->header('Keep-Alive' => [timeout => 15, max => 100]);
 | 
			
		||||
 | 
			
		||||
This allows you a more pragmatic approach when you already have some sort of
 | 
			
		||||
data structure of the header options.  You can go a step further with this, by
 | 
			
		||||
specifying C<undef> as the value:
 | 
			
		||||
 | 
			
		||||
    # Set the second X-Foo header in the example:
 | 
			
		||||
    $header->header('X-Foo' => [bar2 => undef, bar3 => undef]);
 | 
			
		||||
 | 
			
		||||
header() also allows you to set values such as:
 | 
			
		||||
 | 
			
		||||
    image/gif;q=0.2
 | 
			
		||||
 | 
			
		||||
As can be seen in this example:
 | 
			
		||||
 | 
			
		||||
    Accept: image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
 | 
			
		||||
 | 
			
		||||
To do so, specify the suboption value as another array reference.  The first
 | 
			
		||||
element of the array reference is usually undef, while the remaining are the
 | 
			
		||||
k=v pairs in the segment.  So, in the above header, the 'image/gif;q=0.2' section
 | 
			
		||||
would be specified as:
 | 
			
		||||
 | 
			
		||||
    'image/gif' => [undef, q => 0.2]
 | 
			
		||||
 | 
			
		||||
(If a segment such as "foo=bar;bar=foo" is ever needed, the C<undef> would be
 | 
			
		||||
changed to C<"bar">.)
 | 
			
		||||
 | 
			
		||||
So, piecing it all together, the Accept header shown above could be specified
 | 
			
		||||
like this:
 | 
			
		||||
 | 
			
		||||
    $header->header(
 | 
			
		||||
        Accept => [
 | 
			
		||||
            'image/png'  => undef,
 | 
			
		||||
            'image/jpeg' => undef,
 | 
			
		||||
            'image/gif'  => [undef, q => 0.2],
 | 
			
		||||
            '*/*'        => [undef, q => 0.1]
 | 
			
		||||
        ]
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=head2 header_words
 | 
			
		||||
 | 
			
		||||
When you need to see it a header value contains a particular "word", this
 | 
			
		||||
method is the one to use.  As an example, consider this header:
 | 
			
		||||
 | 
			
		||||
    X-Foo: bar, bar2, bar3
 | 
			
		||||
 | 
			
		||||
In order to determine whether or not "bar2" has been specified as an X-Foo
 | 
			
		||||
value, you could attempt some sort of regex - or you could just call this
 | 
			
		||||
method.  The return value splits up the header in such a way as to be useful to
 | 
			
		||||
determine the exact information contained within the header.
 | 
			
		||||
 | 
			
		||||
The method takes a case-insensitive header name, just like the single-argument
 | 
			
		||||
form of header().
 | 
			
		||||
 | 
			
		||||
A even-numbered hash-I<like> list is always returned - though each element of
 | 
			
		||||
that list depends on the content of the header.  First of all, if the header
 | 
			
		||||
specified does not exist, you'll get an empty list back.
 | 
			
		||||
 | 
			
		||||
Assuming that the header does exist, it will first be broken up by C<,>.
 | 
			
		||||
 | 
			
		||||
The even-indexed (0, 2, 4, ...) elements of the list are the keys, while the
 | 
			
		||||
odd numbered elements are the values associated with those keys - or undef if
 | 
			
		||||
there is no value (as above; an example with values is shown below).
 | 
			
		||||
 | 
			
		||||
So, using the above X-Foo header example, calling this method with C<'X-Foo'>
 | 
			
		||||
as an argument would give you back the list:
 | 
			
		||||
 | 
			
		||||
    (bar => undef, bar2 => undef, bar3 => undef)
 | 
			
		||||
 | 
			
		||||
Getting a little more complicated, consider the following header:
 | 
			
		||||
 | 
			
		||||
    X-Foo: bar, bar2=foo, bar3
 | 
			
		||||
 | 
			
		||||
Because of the "=foo" part, the list returned would now be:
 | 
			
		||||
 | 
			
		||||
    (bar => undef, bar2 => "foo", bar3 => undef)
 | 
			
		||||
 | 
			
		||||
Quoting of values is also permitted, so the following would be parsed correctly
 | 
			
		||||
with C<'1;2,3=4"5\6'> being the value of bar2:
 | 
			
		||||
 | 
			
		||||
    X-Foo: bar, bar2="1;2,3=4\"5\\6", bar3
 | 
			
		||||
 | 
			
		||||
Getting more complicated, this method also handles complex values containing
 | 
			
		||||
more than one piece of information.  A good example of this is in content type
 | 
			
		||||
weighting used by most browsers.  As a real life example (generated by
 | 
			
		||||
the Phoenix web browser):
 | 
			
		||||
 | 
			
		||||
    Accept: video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1
 | 
			
		||||
 | 
			
		||||
Working that into the X-Foo example, consider this header:
 | 
			
		||||
 | 
			
		||||
    X-Foo: bar, bar2=foo, bar3;foo1=24;foo2=10
 | 
			
		||||
 | 
			
		||||
In this case, the value for bar3 will become an array reference to handle the
 | 
			
		||||
multiple pieces of information in the third part:
 | 
			
		||||
 | 
			
		||||
    (bar => undef, bar2 => "foo", bar3 => [undef, foo1 => 24, foo2 => 10])
 | 
			
		||||
 | 
			
		||||
(If you've read the advanced section of the L<C<header()>|/header>
 | 
			
		||||
documentation, and this looks familiar, you're right - the return value of this
 | 
			
		||||
function, if put in an array reference, is completely compatible with a
 | 
			
		||||
header() value.)
 | 
			
		||||
 | 
			
		||||
The C<undef> value at the beginning of the array reference is rarely anything other
 | 
			
		||||
than C<undef>, but it I<could> be, if a header such as this were encountered:
 | 
			
		||||
 | 
			
		||||
    X-Foo: bar=foo,foo1=10
 | 
			
		||||
 | 
			
		||||
That would return:
 | 
			
		||||
 | 
			
		||||
    (bar => ["foo", foo1 => 10])
 | 
			
		||||
 | 
			
		||||
One additional thing to note is that header_words() returns the header words
 | 
			
		||||
for B<all> matching headers.  Thus if the following two headers were set:
 | 
			
		||||
 | 
			
		||||
    X-Foo: bar, bar2=foo
 | 
			
		||||
    X-Foo: bar3
 | 
			
		||||
 | 
			
		||||
You would get the same return as if this header was set (shown above):
 | 
			
		||||
 | 
			
		||||
    X-Foo: bar, bar2=foo, bar3
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
A good example usage of this is for a file download.  To get the filename, you
 | 
			
		||||
would do something like:
 | 
			
		||||
 | 
			
		||||
    my %cd = $header->header_words('Content-Disposition');
 | 
			
		||||
    my $filename;
 | 
			
		||||
    if ($cd{filename}) { $filename = $cd{filename} }
 | 
			
		||||
    else               { $filename = "unknown" }
 | 
			
		||||
 | 
			
		||||
=head2 split_words
 | 
			
		||||
 | 
			
		||||
This can be called as object method, class method, or function - it takes a
 | 
			
		||||
single argument, a string, which it proceeds to split up as described for the
 | 
			
		||||
above header_words() method.  Note that this knows nothing about header names -
 | 
			
		||||
it simply knows how to break a header value into the above format.
 | 
			
		||||
 | 
			
		||||
This method is used internally by header_words(), but can be used separately if
 | 
			
		||||
desired.
 | 
			
		||||
 | 
			
		||||
=head2 contains
 | 
			
		||||
 | 
			
		||||
This method takes two arguments: a header, and a header word.  It returns true
 | 
			
		||||
if the header word passed is found in the header specified. For example, the
 | 
			
		||||
following would return true:
 | 
			
		||||
 | 
			
		||||
    $header->contains('X-Foo' => 'bar2')
 | 
			
		||||
 | 
			
		||||
for any of these headers:
 | 
			
		||||
 | 
			
		||||
    X-Foo: bar2
 | 
			
		||||
    X-Foo: bar, bar2, bar3
 | 
			
		||||
    X-Foo: bar, bar2=10, bar3
 | 
			
		||||
    X-Foo: bar, bar2=10;q=0.3, bar3
 | 
			
		||||
 | 
			
		||||
but not for either of these:
 | 
			
		||||
 | 
			
		||||
    X-Foo: bar, bar3=bar2
 | 
			
		||||
    X-Foo: bar, bar3;bar2=10
 | 
			
		||||
 | 
			
		||||
=head2 join_words
 | 
			
		||||
 | 
			
		||||
join_words() does the opposite of split_words(). That is, it takes a value such
 | 
			
		||||
as might be returned by split_words(), and joins it up properly, quoting if
 | 
			
		||||
necessary.  This is called internally when creating the actual header, and can
 | 
			
		||||
be called separately at a method or function if desired.
 | 
			
		||||
 | 
			
		||||
=head2 delete_header_word
 | 
			
		||||
 | 
			
		||||
This takes a header and header word, and proceeds to remove any occurances of
 | 
			
		||||
the header word from the header specified.
 | 
			
		||||
 | 
			
		||||
After calling:
 | 
			
		||||
 | 
			
		||||
    $header->delete_header_word('X-Foo', 'bar2');
 | 
			
		||||
 | 
			
		||||
this header:
 | 
			
		||||
 | 
			
		||||
    X-Foo: bar, bar2;foo=bar, bar3
 | 
			
		||||
 | 
			
		||||
would become:
 | 
			
		||||
 | 
			
		||||
    X-Foo: bar, bar3
 | 
			
		||||
 | 
			
		||||
=head2 delete_header
 | 
			
		||||
 | 
			
		||||
This takes a list of header names.  The headers specified are completely
 | 
			
		||||
removed.
 | 
			
		||||
    
 | 
			
		||||
=head2 replace_header
 | 
			
		||||
 | 
			
		||||
This 2 or more arguments in exactly the same way as header(), however all the
 | 
			
		||||
specified headers are deleted (assuming they exist) before being readded.
 | 
			
		||||
 | 
			
		||||
=head2 format_headers
 | 
			
		||||
 | 
			
		||||
This returns a properly formatted (lines are CRLF delimited) header.  If you
 | 
			
		||||
use the header as a string (i.e. C<"$header">), this method will be internally
 | 
			
		||||
called, and so generally does not need to be called directly.
 | 
			
		||||
 | 
			
		||||
The returned string has the final blank line that identifies the end of the
 | 
			
		||||
header.
 | 
			
		||||
 | 
			
		||||
=head2 clear_headers
 | 
			
		||||
 | 
			
		||||
This deletes all headers.
 | 
			
		||||
 | 
			
		||||
=head1 SEE ALSO
 | 
			
		||||
 | 
			
		||||
L<GT::WWW::http>
 | 
			
		||||
L<GT::WWW>
 | 
			
		||||
RFC 2616: L<http://www.ietf.org/rfc/rfc2616.txt>
 | 
			
		||||
 | 
			
		||||
=head1 MAINTAINER
 | 
			
		||||
 | 
			
		||||
Jason Rhinelander
 | 
			
		||||
 | 
			
		||||
=head1 COPYRIGHT
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
 | 
			
		||||
http://www.gossamer-threads.com/
 | 
			
		||||
 | 
			
		||||
=head1 VERSION
 | 
			
		||||
 | 
			
		||||
Revision: $Id: Header.pm,v 1.8 2004/02/17 01:33:08 jagerman Exp $
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
							
								
								
									
										263
									
								
								site/slowtwitch.com/cgi-bin/articles/GT/WWW/http/Response.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								site/slowtwitch.com/cgi-bin/articles/GT/WWW/http/Response.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,263 @@
 | 
			
		||||
# ====================================================================
 | 
			
		||||
# Gossamer Threads Module Library - http://gossamer-threads.com/
 | 
			
		||||
#
 | 
			
		||||
#   GT::WWW::http::Response
 | 
			
		||||
#   Author: Jason Rhinelander
 | 
			
		||||
#   CVS Info : 087,071,086,086,085      
 | 
			
		||||
#   $Id: Response.pm,v 1.8 2004/08/04 19:23:07 jagerman Exp $
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
 | 
			
		||||
# ====================================================================
 | 
			
		||||
#
 | 
			
		||||
# Description:
 | 
			
		||||
#   Response object for GT::WWW HTTP/HTTPS requests.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
package GT::WWW::http::Response;
 | 
			
		||||
use strict;
 | 
			
		||||
 | 
			
		||||
use vars qw/$AUTOLOAD/;
 | 
			
		||||
use overload
 | 
			
		||||
    '""' => \&content,
 | 
			
		||||
    bool => \&boolean,
 | 
			
		||||
    cmp => \&strcmp;
 | 
			
		||||
use Carp;
 | 
			
		||||
 | 
			
		||||
sub new {
 | 
			
		||||
    my $class = shift;
 | 
			
		||||
    $class = ref $class if ref $class;
 | 
			
		||||
 | 
			
		||||
    my $self = {};
 | 
			
		||||
    bless $self, $class;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AUTOLOAD {
 | 
			
		||||
    my ($self, @args) = @_;
 | 
			
		||||
    my ($attr) = $AUTOLOAD =~ /([^:]+)$/;
 | 
			
		||||
    if (@args) {
 | 
			
		||||
        $self->{$attr} = shift @args;
 | 
			
		||||
    }
 | 
			
		||||
    $self->{$attr};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub content { $_[0]->{content} }
 | 
			
		||||
 | 
			
		||||
sub boolean { 1 } # So you can you do things like: $www->get() or die
 | 
			
		||||
 | 
			
		||||
sub status {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    if (@_) {
 | 
			
		||||
        my ($num, $str) = @_;
 | 
			
		||||
        $self->{status} = GT::WWW::http::Response::Status->new($num, $str);
 | 
			
		||||
    }
 | 
			
		||||
    $self->{status};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub header {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    if (@_) {
 | 
			
		||||
        $self->{header}->header(@_);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        $self->{header};
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub strcmp { $_[2] ? $_[1] cmp $_[0]->{content} : $_[0]->{content} cmp $_[1] }
 | 
			
		||||
 | 
			
		||||
package GT::WWW::http::Response::Status;
 | 
			
		||||
 | 
			
		||||
use overload
 | 
			
		||||
    '""' => \&string,
 | 
			
		||||
    bool => \&boolean,
 | 
			
		||||
    '0+' => \&numeric,
 | 
			
		||||
    '+'  => \&addition,
 | 
			
		||||
    '<=>' => \&numcmp,
 | 
			
		||||
    'cmp' => \&strcmp;
 | 
			
		||||
 | 
			
		||||
sub new {
 | 
			
		||||
    my ($class, $numeric, $string) = @_;
 | 
			
		||||
    my $self = [$numeric, $string];
 | 
			
		||||
    bless $self, $class;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub numeric  { $_[0]->[0] }
 | 
			
		||||
sub string   { "$_[0]->[0] $_[0]->[1]" }
 | 
			
		||||
sub boolean  { substr($_[0]->[0], 0, 1) eq '2' }
 | 
			
		||||
sub addition { int($_[0]) + int($_[1]) }
 | 
			
		||||
sub numcmp   { $_[2] ? $_[1] <=> $_[0]->[0] : $_[0]->[0] <=> $_[1] }
 | 
			
		||||
sub strcmp   { $_[2] ? $_[1] cmp $_[0]->[1] : $_[0]->[1] cmp $_[1] }
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
 | 
			
		||||
__END__
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
GT::WWW::http::Response and GT::WWW::http::Response::Status - Overloaded
 | 
			
		||||
response objects for HTTP request data.
 | 
			
		||||
 | 
			
		||||
=head1 SYNOPSIS
 | 
			
		||||
 | 
			
		||||
    # ($www is continued from GT::WWW::http SYNOPSIS)
 | 
			
		||||
 | 
			
		||||
    my $response = $www->get(); # or post(), or head()
 | 
			
		||||
    # -- or, after having called get(), post() or head(): --
 | 
			
		||||
    my $response = $www->response();
 | 
			
		||||
 | 
			
		||||
    my $status   = $response->status();
 | 
			
		||||
 | 
			
		||||
    my $content = "$response";
 | 
			
		||||
    my $response_code = int($status); # i.e. 200, 404, 500
 | 
			
		||||
    my $response_str = "$status"; # i.e. 'OK', 'Not Found', 'Internal Server Error'
 | 
			
		||||
    if ($status) { # True for 2xx requests, false otherwise (e.g. 404, 500, etc.)
 | 
			
		||||
        ...
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
GT::WWW::http::Response objects are returned by the L<C<get()>|GT::WWW/get>,
 | 
			
		||||
L<C<post()>|GT::WWW/post>, and L<C<head()>|GT::WWW/head> methods of GT::WWW
 | 
			
		||||
HTTP requests (and derivatives - i.e. HTTPS), or by calling
 | 
			
		||||
L<C<response()>|GT::WWW::http/response> after having made such a request.  The
 | 
			
		||||
objects are overloaded in order to provide a simple interface to the response,
 | 
			
		||||
while still having all the information available.
 | 
			
		||||
 | 
			
		||||
A response object always returns true in boolean context, allowing you to do
 | 
			
		||||
things like C<$www-E<gt>get($url) or die;> - even when a page is empty, or
 | 
			
		||||
contains just '0'.
 | 
			
		||||
 | 
			
		||||
=head1 CONTENT
 | 
			
		||||
 | 
			
		||||
In addition to the methods described below, the way to simply access the data
 | 
			
		||||
returned by the server is to simply use it like a string - for example,
 | 
			
		||||
printing it, concatenating it with another string, or quoting it.
 | 
			
		||||
 | 
			
		||||
You should, however, take note that when using the L<C<chunk()>|GT::WWW/chunk>
 | 
			
		||||
option for an HTTP request, the content will not be available.
 | 
			
		||||
 | 
			
		||||
=head1 METHODS
 | 
			
		||||
 | 
			
		||||
For simple requests, often the content alone is enough.  The following methods
 | 
			
		||||
are used to determine any other information available about the response.
 | 
			
		||||
 | 
			
		||||
=head2 content
 | 
			
		||||
 | 
			
		||||
Returns the content of the HTTP response.  Note that this returns the exact
 | 
			
		||||
same value as using the object in double quotes.
 | 
			
		||||
 | 
			
		||||
=head2 status
 | 
			
		||||
 | 
			
		||||
Returns the response status object for the request.  This object provides three
 | 
			
		||||
pieces of information, and has no public methods.  Instead, the data is
 | 
			
		||||
retrieved based on the context of the object.
 | 
			
		||||
 | 
			
		||||
    my $status = $response->status;
 | 
			
		||||
 | 
			
		||||
(N.B. Though the examples below use a C<$status> variable, there is no reason
 | 
			
		||||
they couldn't be written to use C<$response-E<gt>status> instead.)
 | 
			
		||||
 | 
			
		||||
=over 4
 | 
			
		||||
 | 
			
		||||
=item numeric status
 | 
			
		||||
 | 
			
		||||
The numeric status of an HTTP request (e.g. 200, 404, 500) is available simply
 | 
			
		||||
by using the status object as a number.
 | 
			
		||||
 | 
			
		||||
    my $numeric_status = int $status;
 | 
			
		||||
 | 
			
		||||
=item string status
 | 
			
		||||
 | 
			
		||||
The string status of an HTTP request (e.g. "OK", "Not Found", "Internal Server
 | 
			
		||||
Error") is available by using the status object as a string (e.g. printing it,
 | 
			
		||||
or concatenating it with another string).
 | 
			
		||||
 | 
			
		||||
    # Assign the status string to a variable:
 | 
			
		||||
    my $status_string = "$status";
 | 
			
		||||
 | 
			
		||||
    # Print out the status string:
 | 
			
		||||
    print $status;
 | 
			
		||||
 | 
			
		||||
    # To get a string such as "500 Internal Server Error":
 | 
			
		||||
    my $string = int($status) . " " . $status;
 | 
			
		||||
 | 
			
		||||
=item boolean status
 | 
			
		||||
 | 
			
		||||
In order to quickly determine whether or not a request was successful, you can
 | 
			
		||||
use the status object in a boolean context.
 | 
			
		||||
 | 
			
		||||
Success is determined by the numeric status of the response.  Any 2xx status
 | 
			
		||||
(usually 200 OK, but there are others) counts as a successful response, while
 | 
			
		||||
any other status counts as a failure.
 | 
			
		||||
 | 
			
		||||
    if ($status) { print "Request successful!" }
 | 
			
		||||
    else         { print "Request failed!"     }
 | 
			
		||||
 | 
			
		||||
=back
 | 
			
		||||
 | 
			
		||||
=head2 header
 | 
			
		||||
 | 
			
		||||
This method, called without arguments, returns the
 | 
			
		||||
L<header|GT::WWW::http::Header> object for the response.
 | 
			
		||||
 | 
			
		||||
    my $header = $response->header;
 | 
			
		||||
 | 
			
		||||
If this method is called with arguments, those arguments are passed to the
 | 
			
		||||
L<C<header()>|GT::WWW::http::Header/header> method of the header object.  This
 | 
			
		||||
allows this useful shortcut:
 | 
			
		||||
 | 
			
		||||
    my $some_header_value = $response->header("Some-Header");
 | 
			
		||||
 | 
			
		||||
instead of the alternative (which also works):
 | 
			
		||||
 | 
			
		||||
    my $some_header_value = $response->header->header("Some-Header");
 | 
			
		||||
 | 
			
		||||
Information on header object usage is contained in L<GT::WWW::http::Header>.
 | 
			
		||||
 | 
			
		||||
Note that although a header object allows for header manipulation, changing the
 | 
			
		||||
headers of a response object should be considered bad practise, and is strongly
 | 
			
		||||
discouraged.
 | 
			
		||||
 | 
			
		||||
=head1 CAVEATS
 | 
			
		||||
 | 
			
		||||
Although the response object _works_ like a string, keep in mind that it is
 | 
			
		||||
still an object, and thus a reference.  If you intend to pass the data to
 | 
			
		||||
another subroutine expecting a string, it is recommended that you force the
 | 
			
		||||
content into string form, either by quoting the variable (C<"$var">) or by
 | 
			
		||||
calling the content() method (C<$var-E<gt>content>).  Not doing so can lead to
 | 
			
		||||
unexpected results, particularly in cases where another subroutine may
 | 
			
		||||
differentiate between a string and a reference, and not just use the value as a
 | 
			
		||||
string.
 | 
			
		||||
 | 
			
		||||
Also, in terms of speed, obtaining the content (not the object) into another
 | 
			
		||||
variable (either via C<"$var"> or C<$var-E<gt>content>) can make quite a
 | 
			
		||||
substantial difference when several string comparison operations are performed.
 | 
			
		||||
The reason is simply that every time the object is used is a string, the
 | 
			
		||||
content method is called, which can amount to a significant slowdown.
 | 
			
		||||
 | 
			
		||||
Although string operations that change the string (i.e. s///) appear to work,
 | 
			
		||||
they in fact clobber the reference and turn your variable into an ordinary
 | 
			
		||||
string.  This should not be done - if the string needs to be modified, take a
 | 
			
		||||
copy of it first, and modify the copy.
 | 
			
		||||
 | 
			
		||||
=head1 SEE ALSO
 | 
			
		||||
 | 
			
		||||
L<GT::WWW>
 | 
			
		||||
L<GT::WWW::http>
 | 
			
		||||
L<GT::WWW::http::Header>
 | 
			
		||||
RFC 2616: L<http://www.ietf.org/rfc/rfc2616.txt>
 | 
			
		||||
 | 
			
		||||
=head1 MAINTAINER
 | 
			
		||||
 | 
			
		||||
Jason Rhinelander
 | 
			
		||||
 | 
			
		||||
=head1 COPYRIGHT
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
 | 
			
		||||
http://www.gossamer-threads.com/
 | 
			
		||||
 | 
			
		||||
=head1 VERSION
 | 
			
		||||
 | 
			
		||||
Revision: $Id: Response.pm,v 1.8 2004/08/04 19:23:07 jagerman Exp $
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
							
								
								
									
										63
									
								
								site/slowtwitch.com/cgi-bin/articles/GT/WWW/https.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								site/slowtwitch.com/cgi-bin/articles/GT/WWW/https.pm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
# ====================================================================
 | 
			
		||||
# Gossamer Threads Module Library - http://gossamer-threads.com/
 | 
			
		||||
#
 | 
			
		||||
#   GT::WWW::http
 | 
			
		||||
#   Author: Jason Rhinelander
 | 
			
		||||
#   CVS Info : 087,071,086,086,085      
 | 
			
		||||
#   $Id: https.pm,v 1.3 2004/01/13 01:35:20 jagerman Exp $
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
 | 
			
		||||
# ====================================================================
 | 
			
		||||
#
 | 
			
		||||
# Description:
 | 
			
		||||
#   GT::WWW::http subclass to handle HTTPS connections
 | 
			
		||||
#
 | 
			
		||||
# This class has only one methods of its own - the default port. Everything
 | 
			
		||||
# else is inherited directly from GT::WWW::http.  It does, however, have the
 | 
			
		||||
# SSLHandle use, which will err fatally if Net::SSLeay is not installed.
 | 
			
		||||
 | 
			
		||||
package GT::WWW::https;
 | 
			
		||||
use GT::WWW::http;
 | 
			
		||||
use GT::Socket::Client::SSLHandle;
 | 
			
		||||
 | 
			
		||||
@GT::WWW::https::ISA = 'GT::WWW::http';
 | 
			
		||||
 | 
			
		||||
sub default_port { 443 }
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
 | 
			
		||||
__END__
 | 
			
		||||
 | 
			
		||||
=head1 NAME
 | 
			
		||||
 | 
			
		||||
GT::WWW::https - HTTPS handling for GT::WWW
 | 
			
		||||
 | 
			
		||||
=head1 DESCRIPTION
 | 
			
		||||
 | 
			
		||||
This module is a simple subclass of GT::WWW::http used by GT::WWW to enable
 | 
			
		||||
HTTPS access as opposed to HTTP access.  Thus GT::WWW::http should be consulted
 | 
			
		||||
instead of this documentation.
 | 
			
		||||
 | 
			
		||||
=head1 REQUIREMENTS
 | 
			
		||||
 | 
			
		||||
GT::WWW HTTPS support requires GT::Socket::Client::SSLHandle, which in turn
 | 
			
		||||
requires the Net::SSLeay library.
 | 
			
		||||
 | 
			
		||||
=head1 SEE ALSO
 | 
			
		||||
 | 
			
		||||
L<GT::WWW::http>
 | 
			
		||||
 | 
			
		||||
=head1 MAINTAINER
 | 
			
		||||
 | 
			
		||||
Jason Rhinelander
 | 
			
		||||
 | 
			
		||||
=head1 COPYRIGHT
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
 | 
			
		||||
http://www.gossamer-threads.com/
 | 
			
		||||
 | 
			
		||||
=head1 VERSION
 | 
			
		||||
 | 
			
		||||
Revision: $Id: https.pm,v 1.3 2004/01/13 01:35:20 jagerman Exp $
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
		Reference in New Issue
	
	Block a user