264 lines
7.7 KiB
Perl
264 lines
7.7 KiB
Perl
# ====================================================================
|
|
# Gossamer Threads Module Library - http://gossamer-threads.com/
|
|
#
|
|
# GT::WWW::http::Response
|
|
# Author: Jason Rhinelander
|
|
# CVS Info :
|
|
# $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
|