BEGIN {
$ENV
{PERL_LWP_USE_HTTP_10} = 1;
$ENV
{APACHE_TEST_HTTP_09_OK} ||= 0;
}
use
constant
INTERP_KEY
=>
'X-PerlInterpreter'
;
my
$have_lwp
= 0;
unless
(
$ENV
{APACHE_TEST_PRETEND_NO_LWP}) {
$have_lwp
=
eval
{
unless
(
defined
&HTTP::Request::Common::OPTIONS
) {
no
strict
'vars'
;
*OPTIONS
=
sub
{ _simple_req(
OPTIONS
=>
@_
) };
push
@EXPORT
,
'OPTIONS'
;
}
1;
};
}
unless
(
$have_lwp
) {
}
sub
has_lwp {
$have_lwp
}
unless
(
$have_lwp
) {
@HTTP::Request::Common::EXPORT
=
qw(GET HEAD POST PUT OPTIONS)
;
}
sub
install_http11 {
eval
{
die
"no LWP"
unless
$have_lwp
;
LWP->VERSION(5.60);
LWP::Protocol::implementor(
'http'
,
'LWP::Protocol::http'
);
};
}
use
vars
qw(@EXPORT @ISA $RedirectOK $DebugLWP)
;
*import
= \
&Exporter::import
;
@EXPORT
=
@HTTP::Request::Common::EXPORT
;
@ISA
=
qw(LWP::UserAgent)
;
my
$UA
;
my
$REDIR
=
$have_lwp
?
undef
: 1;
my
$conn_opts
= {};
sub
module {
my
$module
=
shift
;
$Apache::TestRequest::Module
=
$module
if
$module
;
$Apache::TestRequest::Module
;
}
sub
scheme {
my
$scheme
=
shift
;
$Apache::TestRequest::Scheme
=
$scheme
if
$scheme
;
$Apache::TestRequest::Scheme
;
}
sub
module2path {
my
$package
=
shift
;
(
my
$path
=
$package
) =~ s/::/__/g;
return
$path
;
}
sub
module2url {
my
$module
=
shift
;
my
$opt
=
shift
|| {};
my
$scheme
=
$opt
->{scheme} ||
'http'
;
my
$path
=
exists
$opt
->{path} ?
$opt
->{path} : module2path(
$module
);
module(
$module
);
my
$config
= Apache::Test::config();
my
$hostport
= hostport(
$config
);
$path
=~ s|^/||;
}
sub
user_agent {
my
$args
= {
@_
};
if
(
delete
$args
->{
reset
}) {
$UA
=
undef
;
}
if
(
exists
$args
->{requests_redirectable}) {
my
$redir
=
$args
->{requests_redirectable};
if
(
ref
$redir
and (
@$redir
> 1 or
$redir
->[0] ne
'POST'
)) {
$REDIR
=
$have_lwp
?
undef
: 1;
}
elsif
(
$redir
) {
if
(
$have_lwp
) {
$args
->{requests_redirectable} = [
qw/GET HEAD POST/
];
$REDIR
=
undef
;
}
else
{
$REDIR
= 1;
}
}
else
{
$REDIR
=
$have_lwp
?
undef
: 0;
}
}
$args
->{keep_alive} ||=
$ENV
{APACHE_TEST_HTTP11};
if
(
$args
->{keep_alive}) {
install_http11();
eval
{
LWP::Protocol::implementor(
'https'
,
'LWP::Protocol::https'
);
};
}
if
(
$have_lwp
and
$LWP::VERSION
>= 6.0 and not
exists
$args
->{ssl_opts}->{SSL_ca_file}) {
my
$vars
= Apache::Test::vars();
my
$cafile
=
"$vars->{sslca}/$vars->{sslcaorg}/certs/ca.crt"
;
$args
->{ssl_opts}->{SSL_ca_file} =
$cafile
;
$conn_opts
->{SSL_ca_file} =
$cafile
;
}
eval
{
$UA
||= __PACKAGE__->new(
%$args
); };
}
sub
user_agent_request_num {
my
$res
=
shift
;
$res
->header(
'Client-Request-Num'
) ||
$res
->header(
'Client-Response-Num'
);
}
sub
user_agent_keepalive {
$ENV
{APACHE_TEST_HTTP11} =
shift
;
}
sub
do_request {
my
(
$ua
,
$method
,
$url
,
$callback
) =
@_
;
my
$r
= HTTP::Request->new(
$method
, resolve_url(
$url
));
my
$response
=
$ua
->request(
$r
,
$callback
);
lwp_trace(
$response
);
}
sub
hostport {
my
$config
=
shift
|| Apache::Test::config();
my
$vars
=
$config
->{vars};
local
$vars
->{scheme} =
$Apache::TestRequest::Scheme
||
$vars
->{scheme};
my
$hostport
=
$config
->hostport;
my
$default_hostport
=
join
':'
,
$vars
->{servername},
$vars
->{port};
if
(
my
$module
=
$Apache::TestRequest::Module
) {
$hostport
=
$module
eq
'default'
?
$default_hostport
:
$config
->{vhosts}->{
$module
}->{hostport};
}
$hostport
||
$default_hostport
;
}
sub
resolve_url {
my
$url
=
shift
;
Carp::croak(
"no url passed"
)
unless
defined
$url
;
return
$url
if
$url
=~ m,^(\w+):/,;
$url
=
"/$url"
unless
$url
=~ m,^/,;
my
$vars
= Apache::Test::vars();
local
$vars
->{scheme} =
$Apache::TestRequest::Scheme
||
$vars
->{scheme} ||
'http'
;
scheme_fixup(
$vars
->{scheme});
my
$hostport
= hostport();
return
"$vars->{scheme}://$hostport$url"
;
}
my
%wanted_args
=
map
{
$_
, 1}
qw(username password realm content filename
redirect_ok cert)
;
sub
wanted_args {
\
%wanted_args
;
}
sub
redirect_ok {
my
$self
=
shift
;
if
(
$have_lwp
) {
return
$RedirectOK
if
defined
$RedirectOK
;
return
$self
->SUPER::redirect_ok(
@_
);
}
return
0
if
$self
->method eq
'POST'
;
return
$RedirectOK
if
defined
$RedirectOK
;
return
$REDIR
;
}
my
%credentials
;
sub
new {
my
$self
=
shift
->SUPER::new(
@_
);
lwp_debug();
my
$config
= Apache::Test::config();
if
(
my
$proxy
=
$config
->configure_proxy) {
$self
->proxy(
http
=>
"http://$proxy"
);
}
$self
->timeout(UA_TIMEOUT);
$self
;
}
sub
credentials {
my
$self
=
shift
;
return
$self
->get_basic_credentials(
@_
);
}
sub
get_basic_credentials {
my
(
$self
,
$realm
,
$uri
,
$proxy
) =
@_
;
for
(
$realm
,
'__ALL__'
) {
next
unless
$_
&&
$credentials
{
$_
};
return
@{
$credentials
{
$_
} };
}
return
(
undef
,
undef
);
}
sub
vhost_socket {
my
$module
=
shift
;
local
$Apache::TestRequest::Module
=
$module
if
$module
;
my
$hostport
= hostport(Apache::Test::config());
my
(
$host
,
$port
) =
split
':'
,
$hostport
;
my
(
%args
) = (
PeerAddr
=>
$host
,
PeerPort
=>
$port
);
if
(
$module
and (
$module
=~ /ssl/ ||
$module
eq
'h2'
)) {
map
{
$args
{
$_
} =
$conn_opts
->{
$_
}}
keys
%{
$conn_opts
};
return
IO::Socket::SSL->new(
%args
,
Timeout
=> UA_TIMEOUT);
}
else
{
return
IO::Socket::INET->new(
%args
);
}
}
my
%getline
= (
'IO::Socket::SSL'
=>
sub
{
my
$self
=
shift
;
my
$ssl
=
$self
->_get_ssl_object;
my
(
$got
,
$rv
,
$errs
);
my
$reply
=
''
;
while
(1) {
(
$got
,
$rv
) = Net::SSLeay::
read
(
$ssl
, 1);
if
(!
defined
$got
) {
my
$err
= Net::SSLeay::get_error(
$ssl
,
$rv
);
if
(
$err
!= Net::SSLeay::ERROR_WANT_READ() and
$err
!= Net::SSLeay::ERROR_WANT_WRITE()) {
$errs
= Net::SSLeay::print_errs(
'SSL_read'
);
last
;
}
next
;
}
last
if
$got
eq
''
;
$reply
.=
$got
;
last
if
$got
eq
"\n"
;
}
wantarray
? (
$reply
,
$errs
) :
$reply
;
},
);
sub
getline {
my
$sock
=
shift
;
my
$class
=
ref
$sock
;
my
$method
=
$getline
{
$class
} ||
'getline'
;
$sock
->
$method
();
}
sub
socket_trace {
my
$sock
=
shift
;
return
unless
$sock
->can(
'get_peer_certificate'
);
my
$cert
=
$sock
->get_peer_certificate;
print
"#Cipher: "
,
$sock
->get_cipher,
"\n"
;
print
"#Peer DN: "
,
$cert
->subject_name,
"\n"
;
}
sub
prepare {
my
$url
=
shift
;
if
(
$have_lwp
) {
user_agent();
$url
= resolve_url(
$url
);
}
else
{
lwp_debug()
if
$ENV
{APACHE_TEST_DEBUG_LWP};
}
my
(
$pass
,
$keep
) = Apache::TestConfig::filter_args(\
@_
, \
%wanted_args
);
%credentials
= ();
if
(
defined
$keep
->{username}) {
$credentials
{
$keep
->{realm} ||
'__ALL__'
} =
[
$keep
->{username},
$keep
->{password}];
}
if
(
defined
(
my
$content
=
$keep
->{content})) {
if
(
$content
eq
'-'
) {
$content
=
join
''
, <STDIN>;
}
elsif
(
$content
=~ /^x(\d+)$/) {
$content
=
'a'
x $1;
}
push
@$pass
,
content
=>
$content
;
}
if
(
exists
$keep
->{cert}) {
set_client_cert(
$keep
->{cert});
}
return
(
$url
,
$pass
,
$keep
);
}
sub
UPLOAD {
my
(
$url
,
$pass
,
$keep
) = prepare(
@_
);
local
$RedirectOK
=
exists
$keep
->{redirect_ok}
?
$keep
->{redirect_ok}
:
$RedirectOK
;
if
(
$keep
->{filename}) {
return
upload_file(
$url
,
$keep
->{filename},
$pass
);
}
else
{
return
upload_string(
$url
,
$keep
->{content});
}
}
sub
UPLOAD_BODY {
UPLOAD(
@_
)->content;
}
sub
UPLOAD_BODY_ASSERT {
content_assert(UPLOAD(
@_
));
}
sub
upload_string {
my
(
$url
,
$data
) =
@_
;
my
$CRLF
=
"\015\012"
;
my
$bound
= 742617000027;
my
$req
= HTTP::Request->new(
POST
=>
$url
);
my
$content
=
join
$CRLF
,
"--$bound"
,
"Content-Disposition: form-data; name=\"HTTPUPLOAD\"; filename=\"b\""
,
"Content-Type: text/plain"
,
""
,
$data
,
"--$bound--"
,
""
;
$req
->header(
"Content-Length"
,
length
(
$content
));
$req
->content_type(
"multipart/form-data; boundary=$bound"
);
$req
->content(
$content
);
$UA
->request(
$req
);
}
sub
upload_file {
my
(
$url
,
$file
,
$args
) =
@_
;
my
$content
= [
@$args
,
filename
=> [
$file
]];
$UA
->request(HTTP::Request::Common::POST(
$url
,
Content_Type
=>
'form-data'
,
Content
=>
$content
,
));
}
sub
lwp_as_string {
my
(
$r
,
$want_body
) =
@_
;
my
$content
=
$r
->content;
unless
(
$r
->isa(
'HTTP::Request'
) or
$r
->header(
'Content-Length'
) or
$r
->header(
'Transfer-Encoding'
))
{
$r
->header(
'Content-Length'
=>
length
$content
);
$r
->header(
'X-Content-length-note'
=>
'added by Apache::TestRequest'
);
}
$r
->content(
''
)
unless
$want_body
;
(
my
$string
=
$r
->as_string) =~ s/^/\
$r
->content(
$content
);
$string
;
}
$DebugLWP
= 0;
sub
lwp_debug {
my
$val
=
$_
[0] ||
$ENV
{APACHE_TEST_DEBUG_LWP};
return
unless
$val
;
if
(
$val
=~ /^\d+$/) {
$Apache::TestRequest::DebugLWP
=
$val
;
return
"\$Apache::TestRequest::DebugLWP = $val\n"
;
}
else
{
my
(
@args
) =
@_
?
@_
:
split
/\s+/,
$val
;
LWP::Debug->
import
(
@args
);
return
"LWP::Debug->import(@args)\n"
;
}
}
sub
lwp_trace {
my
$r
=
shift
;
unless
(
$r
->request->protocol) {
my
$proto
= user_agent_request_num(
$r
) ?
"1.1"
:
"1.0"
;
$r
->request->protocol(
"HTTP/$proto"
);
}
my
$want_body
=
$DebugLWP
> 1;
print
"#lwp request:\n"
,
lwp_as_string(
$r
->request,
$want_body
);
print
"#server response:\n"
,
lwp_as_string(
$r
,
$want_body
);
}
sub
lwp_call {
my
(
$name
,
$shortcut
) = (
shift
,
shift
);
my
$r
= (\&{
$name
})->(
@_
);
Carp::croak(
"$name(@_) didn't return a response object"
)
unless
$r
;
my
$error
=
""
;
unless
(
$shortcut
) {
if
(
$r
->method eq
"POST"
&& !
defined
(
$r
->header(
"Content-Length"
))) {
$r
->header(
'Content-Length'
=>
length
(
$r
->content));
}
$r
=
$UA
?
$UA
->request(
$r
) :
$r
;
my
$proto
=
$r
->protocol;
if
(
defined
(
$proto
)) {
if
(
$proto
!~ /^HTTP\/(\d\.\d)$/) {
$error
=
"response had no protocol (is LWP broken or something?)"
;
}
if
($1 ne
"1.0"
&& $1 ne
"1.1"
) {
$error
=
"response had protocol HTTP/$1 (headers not sent?)"
unless
($1 eq
"0.9"
&&
$ENV
{APACHE_TEST_HTTP_09_OK});
}
}
}
if
(
$DebugLWP
and not
$shortcut
) {
lwp_trace(
$r
);
}
Carp::croak(
$error
)
if
$error
;
return
$shortcut
?
$r
->
$shortcut
() :
$r
;
}
my
%shortcuts
= (
RC
=>
sub
{
shift
->code },
OK
=>
sub
{
shift
->is_success },
STR
=>
sub
{
shift
->as_string },
HEAD
=>
sub
{ lwp_as_string(
shift
, 0) },
BODY
=>
sub
{
shift
->content },
BODY_ASSERT
=>
sub
{ content_assert(
shift
) },
);
for
my
$name
(
@EXPORT
) {
my
$package
=
$have_lwp
?
'HTTP::Request::Common'
:
'Apache::TestClient'
;
my
$method
=
join
'::'
,
$package
,
$name
;
no
strict
'refs'
;
next
unless
defined
&$method
;
*$name
=
sub
{
my
(
$url
,
$pass
,
$keep
) = prepare(
@_
);
local
$RedirectOK
=
exists
$keep
->{redirect_ok}
?
$keep
->{redirect_ok}
:
$RedirectOK
;
return
lwp_call(
$method
,
undef
,
$url
,
@$pass
);
};
while
(
my
(
$shortcut
,
$cv
) =
each
%shortcuts
) {
my
$alias
=
join
'_'
,
$name
,
$shortcut
;
*$alias
=
sub
{ lwp_call(
$name
,
$cv
,
@_
) };
}
}
my
@export_std
=
@EXPORT
;
for
my
$method
(
@export_std
) {
push
@EXPORT
,
map
{
join
'_'
,
$method
,
$_
}
keys
%shortcuts
;
}
push
@EXPORT
,
qw(UPLOAD UPLOAD_BODY UPLOAD_BODY_ASSERT)
;
sub
to_string {
my
$obj
=
shift
;
ref
(
$obj
) ?
$obj
->as_string :
$obj
;
}
sub
same_interp_tie {
my
(
$url
) =
@_
;
my
$res
= GET(
$url
, INTERP_KEY,
'tie'
);
unless
(
$res
->code == 200) {
die
sprintf
"failed to init the same_handler data (url=%s). "
.
"Failed with code=%s, response:\n%s"
,
$url
,
$res
->code,
$res
->content;
}
my
$same_interp
=
$res
->header(INTERP_KEY);
return
$same_interp
;
}
sub
same_interp_do {
my
(
$same_interp
,
$sub
,
$url
,
@args
) =
@_
;
die
"must pass an interpreter id, obtained via same_interp_tie()"
unless
defined
$same_interp
and
$same_interp
;
push
@args
, (INTERP_KEY,
$same_interp
);
my
$res
=
''
;
my
$times
= 0;
my
$found_same_interp
=
''
;
do
{
$res
=
$sub
->(
$url
,
@args
);
die
"no result"
unless
$res
;
my
$code
=
$res
->code;
if
(
$code
== 200) {
$found_same_interp
=
$res
->header(INTERP_KEY) ||
''
;
}
elsif
(
$code
== 404) {
}
else
{
die
sprintf
"failed to run the request (url=%s):\n"
.
"code=%s, response:\n%s"
,
$url
,
$code
,
$res
->content;
}
unless
(
$found_same_interp
eq
$same_interp
) {
$found_same_interp
=
''
;
}
if
(
$times
++ > TRY_TIMES) {
die
"unable to find interp $same_interp\n"
;
}
}
until
(
$found_same_interp
);
return
$found_same_interp
?
$res
:
undef
;
}
sub
set_client_cert {
my
$name
=
shift
;
my
$vars
= Apache::Test::vars();
my
$dir
=
join
'/'
,
$vars
->{sslca},
$vars
->{sslcaorg};
if
(
$name
) {
my
(
$cert
,
$key
) = (
"$dir/certs/$name.crt"
,
"$dir/keys/$name.pem"
);
$conn_opts
->{SSL_cert_file} =
$cert
;
$conn_opts
->{SSL_key_file} =
$key
;
if
(
$LWP::VERSION
>= 6.0) {
if
(
$UA
) {
$UA
->ssl_opts(
SSL_cert_file
=>
$cert
);
$UA
->ssl_opts(
SSL_key_file
=>
$key
);
}
else
{
user_agent(
ssl_opts
=> {
SSL_cert_file
=>
$cert
,
SSL_key_file
=>
$key
});
}
}
}
else
{
$conn_opts
->{SSL_cert_file} =
undef
;
$conn_opts
->{SSL_key_file} =
undef
;
if
(
$LWP::VERSION
>= 6.0 and
$UA
) {
$UA
->ssl_opts(
SSL_cert_file
=>
undef
);
$UA
->ssl_opts(
SSL_key_file
=>
undef
);
}
}
}
sub
set_ca_cert {
my
$vars
= Apache::Test::vars();
my
$cafile
=
"$vars->{sslca}/$vars->{sslcaorg}/certs/ca.crt"
;
$conn_opts
->{SSL_ca_file} =
$cafile
;
}
sub
install_net_socket_new {
my
(
$module
,
$code
) =
@_
;
return
unless
Apache::Test::have_module(
$module
);
no
strict
'refs'
;
my
$new
;
my
$isa
= \@{
"$module\::ISA"
};
for
(
@$isa
) {
last
if
$new
=
$_
->can(
'new'
);
}
my
$fixup_class
=
"Apache::TestRequest::$module"
;
unshift
@$isa
,
$fixup_class
;
*{
"$fixup_class\::new"
} =
sub
{
my
$class
=
shift
;
my
$args
= {
@_
};
$code
->(
$args
);
return
$new
->(
$class
,
%$args
);
};
}
my
%scheme_fixups
= (
'news'
=>
sub
{
return
if
$INC
{
'Net/NNTP.pm'
};
eval
{
install_net_socket_new(
'Net::NNTP'
=>
sub
{
my
$args
=
shift
;
my
(
$host
,
$port
) =
split
':'
,
Apache::TestRequest::hostport();
$args
->{PeerPort} =
$port
;
$args
->{PeerAddr} =
$host
;
});
};
},
);
sub
scheme_fixup {
my
$scheme
=
shift
;
my
$fixup
=
$scheme_fixups
{
$scheme
};
return
unless
$fixup
;
$fixup
->();
}
sub
content_assert {
my
$res
=
shift
;
return
$res
->content
if
$res
->is_success;
die
join
"\n"
,
"request has failed (the response code was: "
.
$res
->code .
")"
,
"see t/logs/error_log for more details\n"
;
}
1;
=head1 NAME
Apache::TestRequest - Send requests to your Apache test server
=head1 SYNOPSIS
plan
tests
=> 1, have_lwp;
my
$res
= GET
'/test.html'
;
ok
$res
->code == HTTP_OK,
"Request is ok"
;
=head1 DESCRIPTION
B<Apache::TestRequest> provides convenience functions to allow you to
make requests to your Apache test server in your test scripts. It
subclasses C<LWP::UserAgent>, so that you have access to all
if
its
methods, but also exports a number of useful functions likely useful
for
majority of your test requests. Users of the old C<Apache::test>
(or C<Apache::testold>) module, take note! Herein lie most of the
functions you'll need to
use
to replace C<Apache::test> in your test
suites.
Each of the functions exported by C<Apache::TestRequest> uses an
C<LWP::UserAgent> object to submit the request and retrieve its
results. The
return
value
for
many of these functions is an
HTTP::Response object. See L<HTTP::Response|HTTP::Response>
for
documentation of its methods, which you can
use
in your tests. For
example,
use
the C<code()> and C<content()> methods to test the
response code and content of your request. Using C<GET>, you can
perform a couple of tests using these methods like this:
plan
tests
=> 2, have_lwp;
my
$uri
=
"/test.html?foo=1&bar=2"
;
my
$res
= GET
$uri
;
ok
$res
->code == HTTP_OK,
"Check that the request was OK"
;
ok
$res
->content eq
"foo => 1, bar => 2"
,
"Check its content"
;
Note that you can also
use
C<Apache::TestRequest>
with
C<Test::Builder> and its derivatives, including C<Test::More>:
is
$res
->code, HTTP_OK,
"Check that the request was OK"
;
is
$res
->content,
"foo => 1, bar => 2"
,
"Check its content"
;
=head1 CONFIGURATION FUNCTION
You can
tell
C<Apache::TestRequest> what kind of C<LWP::UserAgent>
object to
use
for
its convenience functions
with
C<user_agent()>. This
function uses its arguments to construct an internal global
C<LWP::UserAgent> object that will be used
for
all subsequent requests
made by the convenience functions. The arguments it takes are the same
as
for
the C<LWP::UserAgent> constructor. See the
C<L<LWP::UserAgent|LWP::UserAgent>> documentation
for
a complete list.
The C<user_agent()> function only creates the internal
C<LWP::UserAgent> object the first
time
it is called. Since this
function is called internally by C<Apache::TestRequest>, you should
always
use
the C<
reset
> parameter to force it to create a new global
C<LWP::UserAgent> Object:
Apache::TestRequest::user_agent(
reset
=> 1,
%params
);
C<user_agent()> differs from C<< LWP::UserAgent->new >> in two
additional ways. First, it supports an additional parameter,
C<keep_alive>, which enables connection persistence, where the same
connection is used to process multiple requests (and, according to the
C<L<LWP::UserAgent|LWP::UserAgent>> documentation,
has
the effect of
loading and enabling the new experimental HTTP/1.1 protocol module).
And
finally
, the semantics of the C<requests_redirectable> parameter is
different than
for
C<LWP::UserAgent> in that you can pass it a boolean
value as well as an array
for
C<LWP::UserAgent>. To force
C<Apache::TestRequest> not to follow redirects in any of its convenience
functions, pass a false value to C<requests_redirectable>:
Apache::TestRequest::user_agent(
reset
=> 1,
requests_redirectable
=> 0);
If LWP is not installed, then you can still pass in an array reference
as C<LWP::UserAgent> expects. C<Apache::TestRequest> will examine the
array and allow redirects
if
the array contains more than one value or
if
there is only one value and that value is not
"POST"
:
my
$redir
= have_lwp() ? [
qw(GET HEAD POST)
] : 1;
Apache::TestRequest::user_agent(
reset
=> 1,
requests_redirectable
=>
$redir
);
But note that redirection will B<not> work
with
C<POST>
unless
LWP is
installed. It's best, therefore, to check C<have_lwp>
before
running
tests that rely on a redirection from C<POST>.
Sometimes it is desireable to have C<Apache::TestRequest> remember
cookies sent by the pages you are testing and
send
them back to the
server on subsequent requests. This is especially necessary
when
testing pages whose functionality relies on sessions or the presence
of preferences stored in cookies.
By
default
, C<LWP::UserAgent> does B<not> remember cookies between
requests. You can
tell
it to remember cookies between request by
adding:
Apache::TestRequest::user_agent(
cookie_jar
=> {});
before
issuing the requests.
=head1 FUNCTIONS
C<Apache::TestRequest> exports a number of functions that will likely
prove convenient
for
use
in the majority of your request tests.
=head2 Optional Parameters
Each function also takes a number of optional arguments.
=over 4
=item redirect_ok
By
default
a request will follow redirects retrieved from the server. To
prevent this behavior, pass a false value to a C<redirect_ok>
parameter:
my
$res
= GET
$uri
,
redirect_ok
=> 0;
Alternately,
if
all of your tests need to disable redirects,
tell
C<Apache::TestRequest> to
use
an C<LWP::UserAgent> object that
disables redirects:
Apache::TestRequest::user_agent(
reset
=> 1,
requests_redirectable
=> 0 );
=item cert
If you need to force an SSL request to
use
a particular SSL
certificate, pass the name of the certificate via the C<cert>
parameter:
my
$res
= GET
$uri
,
cert
=>
'my_cert'
;
=item content
If you need to add content to your request,
use
the C<content>
parameter:
my
$res
= GET
$uri
,
content
=>
'hello world!'
;
=item filename
The name of a
local
file on the file
system
to be sent to the Apache
test server via C<UPLOAD()> and its friends.
=back
=head2 The Functions
=head3 GET
my
$res
= GET
$uri
;
Sends a simple GET request to the Apache test server. Returns an
C<HTTP::Response> object.
You can also supply additional headers to be sent
with
the request by
adding their name/value pairs
after
the C<url> parameter,
for
example:
my
$res
= GET
$url
,
'Accept-Language'
=>
'de,en-us,en;q=0.5'
;
=head3 GET_STR
A shortcut function
for
C<GET(
$uri
)-E<gt>as_string>.
=head3 GET_BODY
A shortcut function
for
C<GET(
$uri
)-E<gt>content>.
=head3 GET_BODY_ASSERT
Use this function
when
your test is outputting content that you need
to check, and you want to make sure that the request was successful
before
comparing the contents of the request. If the request was
unsuccessful, C<GET_BODY_ASSERT> will
return
an error
message. Otherwise it will simply
return
the content of the request
just as C<GET_BODY> would.
=head3 GET_OK
A shortcut function
for
C<GET(
$uri
)-E<gt>is_success>.
=head3 GET_RC
A shortcut function
for
C<GET(
$uri
)-E<gt>code>.
=head3 GET_HEAD
Throws out the content of the request, and returns the string
representation of the request. Since the body
has
been thrown out, the
representation will consist solely of the headers. Furthermore,
C<GET_HEAD> inserts a
"#"
at the beginning of
each
line of the
return
string, so that the contents are suitable
for
printing to STDERR
during your tests without interfering
with
the workings of
C<Test::Harness>.
=head3 HEAD
my
$res
= HEAD
$uri
;
Sends a HEAD request to the Apache test server. Returns an
C<HTTP::Response> object.
=head3 HEAD_STR
A shortcut function
for
C<HEAD(
$uri
)-E<gt>as_string>.
=head3 HEAD_BODY
A shortcut function
for
C<HEAD(
$uri
)-E<gt>content>. Of course, this
means that it will likely
return
nothing.
=head3 HEAD_BODY_ASSERT
Use this function
when
your test is outputting content that you need
to check, and you want to make sure that the request was successful
before
comparing the contents of the request. If the request was
unsuccessful, C<HEAD_BODY_ASSERT> will
return
an error
message. Otherwise it will simply
return
the content of the request
just as C<HEAD_BODY> would.
=head3 HEAD_OK
A shortcut function
for
C<GET(
$uri
)-E<gt>is_success>.
=head3 HEAD_RC
A shortcut function
for
C<GET(
$uri
)-E<gt>code>.
=head3 HEAD_HEAD
Throws out the content of the request, and returns the string
representation of the request. Since the body
has
been thrown out, the
representation will consist solely of the headers. Furthermore,
C<GET_HEAD> inserts a
"#"
at the beginning of
each
line of the
return
string, so that the contents are suitable
for
printing to STDERR
during your tests without interfering
with
the workings of
C<Test::Harness>.
=head3 PUT
my
$res
= PUT
$uri
;
Sends a simple PUT request to the Apache test server. Returns an
C<HTTP::Response> object.
=head3 PUT_STR
A shortcut function
for
C<PUT(
$uri
)-E<gt>as_string>.
=head3 PUT_BODY
A shortcut function
for
C<PUT(
$uri
)-E<gt>content>.
=head3 PUT_BODY_ASSERT
Use this function
when
your test is outputting content that you need
to check, and you want to make sure that the request was successful
before
comparing the contents of the request. If the request was
unsuccessful, C<PUT_BODY_ASSERT> will
return
an error
message. Otherwise it will simply
return
the content of the request
just as C<PUT_BODY> would.
=head3 PUT_OK
A shortcut function
for
C<PUT(
$uri
)-E<gt>is_success>.
=head3 PUT_RC
A shortcut function
for
C<PUT(
$uri
)-E<gt>code>.
=head3 PUT_HEAD
Throws out the content of the request, and returns the string
representation of the request. Since the body
has
been thrown out, the
representation will consist solely of the headers. Furthermore,
C<PUT_HEAD> inserts a
"#"
at the beginning of
each
line of the
return
string, so that the contents are suitable
for
printing to STDERR
during your tests without interfering
with
the workings of
C<Test::Harness>.
=head3 POST
my
$res
= POST
$uri
, [
arg
=>
$val
,
arg2
=>
$val
];
Sends a POST request to the Apache test server and returns an
C<HTTP::Response> object. An array reference of parameters passed as
the second argument will be submitted to the Apache test server as the
POST content. Parameters corresponding to those documented in
L<Optional Parameters|/Optional
Parameters> can follow the optional array reference of parameters, or
after
C<
$uri
>.
To upload a chunk of data, simply
use
:
my
$res
= POST
$uri
,
content
=>
$data
;
=head3 POST_STR
A shortcut function
for
C<POST(
$uri
,
@args
)-E<gt>content>.
=head3 POST_BODY
A shortcut function
for
C<POST(
$uri
,
@args
)-E<gt>content>.
=head3 POST_BODY_ASSERT
Use this function
when
your test is outputting content that you need
to check, and you want to make sure that the request was successful
before
comparing the contents of the request. If the request was
unsuccessful, C<POST_BODY_ASSERT> will
return
an error
message. Otherwise it will simply
return
the content of the request
just as C<POST_BODY> would.
=head3 POST_OK
A shortcut function
for
C<POST(
$uri
,
@args
)-E<gt>is_success>.
=head3 POST_RC
A shortcut function
for
C<POST(
$uri
,
@args
)-E<gt>code>.
=head3 POST_HEAD
Throws out the content of the request, and returns the string
representation of the request. Since the body
has
been thrown out, the
representation will consist solely of the headers. Furthermore,
C<POST_HEAD> inserts a
"#"
at the beginning of
each
line of the
return
string, so that the contents are suitable
for
printing to STDERR
during your tests without interfering
with
the workings of
C<Test::Harness>.
=head3 UPLOAD
my
$res
= UPLOAD
$uri
, \
@args
,
filename
=>
$filename
;
Sends a request to the Apache test server that includes an uploaded
file. Other POST parameters can be passed as a second argument as an
array reference.
C<Apache::TestRequest> will
read
in the contents of the file named via
the C<filename> parameter
for
submission to the server. If you'd
rather, you can submit
use
the C<content> parameter instead of
C<filename>, and its value will be submitted to the Apache server as
file contents:
my
$res
= UPLOAD
$uri
,
undef
,
content
=>
"This is file content"
;
The name of the file sent to the server will simply be
"b"
. Note that
in this case, you cannot pass other POST arguments to C<UPLOAD()> --
they would be ignored.
=head3 UPLOAD_BODY
A shortcut function
for
C<UPLOAD(
$uri
,
@params
)-E<gt>content>.
=head3 UPLOAD_BODY_ASSERT
Use this function
when
your test is outputting content that you need
to check, and you want to make sure that the request was successful
before
comparing the contents of the request. If the request was
unsuccessful, C<UPLOAD_BODY_ASSERT> will
return
an error
message. Otherwise it will simply
return
the content of the request
just as C<UPLOAD_BODY> would.
=head3 OPTIONS
my
$res
= OPTIONS
$uri
;
Sends an C<OPTIONS> request to the Apache test server. Returns an
C<HTTP::Response> object
with
the I<Allow> header, indicating which
methods the server supports. Possible methods include C<OPTIONS>,
C<GET>, C<HEAD> and C<POST>. This function thus can be useful
for
testing what options the Apache server supports. Consult the HTTPD 1.1
specification, section 9.2, at
=head2 URL Manipulation Functions
C<Apache::TestRequest> also includes a few helper functions to aid in
the creation of urls used in the functions above.
=head3 C<module2path>
$path
= Apache::TestRequest::module2path(
$module_name
);
Convert a module name to a path, safe
for
use
in the various request
methods above. e.g. C<::> can't be used in URLs on win32. For example:
$path
= Apache::TestRequest::module2path(
'Foo::Bar'
);
returns:
/Foo__Bar
=head3 C<module2url>
$url
= Apache::TestRequest::module2url(
$module
);
$url
= Apache::TestRequest::module2url(
$module
, \
%options
);
Convert a module name to a full URL including the current
configurations C<hostname:port> and sets C<module> accordingly.
$url
= Apache::TestRequest::module2url(
'Foo::Bar'
);
returns:
The
default
scheme used is C<http>. You can
override
this by passing
your preferred scheme into an optional second param. For example:
$module
=
'MyTestModule::TestHandler'
;
$url
= Apache::TestRequest::module2url(
$module
, {
scheme
=>
'https'
});
returns:
https://
$hostname
:
$port
/MyTestModule__TestHandler
You may also
override
the
default
path
with
a path of your own:
$module
=
'MyTestModule::TestHandler'
;
$url
= Apache::TestRequest::module2url(
$module
, {
path
=>
'/foo'
});
returns:
=head1 ENVIRONMENT VARIABLES
The following environment variables can affect the behavior of
C<Apache::TestRequest>:
=over
=item APACHE_TEST_PRETEND_NO_LWP
If the environment variable C<APACHE_TEST_PRETEND_NO_LWP> is set to a
true value, C<Apache::TestRequest> will pretend that LWP is not
available so one can test whether the test suite will survive on a
system
which doesn't have libwww-perl installed.
=item APACHE_TEST_HTTP_09_OK
If the environment variable C<APACHE_TEST_HTTP_09_OK> is set to a
true value, C<Apache::TestRequest> will allow HTTP/0.9 responses
from the server to proceed. The
default
behavior is to
die
if
the response protocol is not either HTTP/1.0 or HTTP/1.1.
=back
=head1 SEE ALSO
L<Apache::Test|Apache::Test> is the main Apache testing module. Use it
to set up your tests, create a plan, and to ensure that you have the
Apache version and modules you need.
Use L<Apache::TestMM|Apache::TestMM> in your I<Makefile.PL> to set up
your distribution
for
testing.
=head1 AUTHOR
Doug MacEachern
with
contributions from Geoffrey Young, Philippe
M. Chiasson, Stas Bekman and others. Documentation by David Wheeler.
Questions can be asked at the test-dev <at> httpd.apache.org list. For