our
$VERSION
=
'0.030.'
.
sprintf
"%04d"
, (
qw($Id: HTTP.pm 74 2007-06-08 00:42:53Z hacker $)
)[2];
my
@poco_cm
:Field
:All(
'poco_cm'
)
:Type(
'POE::Component::Client::KeepaliveRaw'
);
my
@poco_http
:Field
:All(
'poco_http'
)
:Type(
'POE::Component::Client::HTTPRaw'
);
my
@user_agents
:Field
:All(
'user_agents'
)
:Type(
'ARRAY'
);
my
@cookie_jar
:Field
:All(
'cookie_jar'
);
my
@id_count
:Field
:All(
'id_count'
)
:Type(
'NUMERIC'
);
sub
_preinit :PreInit {
my
(
$self
,
$args
) =
@_
;
$args
->{
'name'
} =
'tcli_http'
;
$args
->{
'session'
} = POE::Session->create(
object_states
=> [
$self
=> [
qw(
_start
_stop
_shutdown
_default
_child
establish_context
get
ProcessResponse
ResponseProgress
retry
)
],
],
);
}
sub
_init :Init {
my
$self
=
shift
;
$self
->set(\
@user_agents
, [
'TCLI Test Agent'
]);
$self
->LoadYaml(
<<'...');
---
Agent::TCLI::Parameter:
name: user_agents
help: An array of user_agents to be used, at random.
manual: >
Currently not supported. :(
type: Param
---
Agent::TCLI::Parameter:
name: url
constraints:
- HTTP_URL
help: The full http url to send to the webserver
manual: >
server. Currently only http is supported. DNS will be resolved from the
TCLI agent system.
type: Param
---
Agent::TCLI::Parameter:
name: id
help: An id to tag the request with.
manual: >
This is sort of deprecated. It allows one to set an id to tag a request
so that one can properly match up the response. With full RPC support
this does not seem necessary any more, so if it seems useful let the
author know.
type: Param
---
Agent::TCLI::Parameter:
name: response_code
aliases: resp
constraints:
- UINT
class: numeric
help: The desired response code.
manual: >
Used with the tget command to specifiy the desired response code. tget
will report ok if the proper code is received from the server.
type: Param
---
Agent::TCLI::Parameter:
name: retry_interval
aliases: ri
help: Retry in this many seconds
constraints:
- UINT
class: numeric
default: 30
manual: >
This parameter will cause a retry attempt of the same URL after the
specified number of seconds. This will only happen upon
successful completion of the first request. The same HTTP session
is used for the retry.
The default interval is 30 seconds.
type: Param
---
Agent::TCLI::Parameter:
name: retry_count
aliases: rc
constraints:
- UINT
class: numeric
default: 1
help: The number of times to retry when successful.
manual: >
This parameter will cause the specified number or retry attampts
This will only happen upon successful completion of the
first request. The default is 1.
type: Param
---
Agent::TCLI::Command:
name: http
call_style: session
command: tcli_http
contexts:
ROOT: http
handler: establish_context
help: http web cient environment
manual: >
Currently the http commands available only support limited capabilities.
One can request a url and verify that a desired response code was
received, but HTML content is not processed.
topic: net
usage: http tget url=http:\example.com\request resp=404
---
Agent::TCLI::Command:
name: tget
call_style: session
command: tcli_http
contexts:
http: tget
handler: get
help: makes a requests and expects a specific response code
manual: >
Tget makes an http request for the supplied url and checks to see that the
supplied response code is returned by the http server. This is useful in
test scripts to ensure that a request has been responeded to properly.
parameters:
url:
response_code:
retry_interval:
retry_count:
required:
url:
topic: net
usage: tget tget url=http:\example.com\request resp=404
---
Agent::TCLI::Command:
call_style: session
command: tcli_http
contexts:
http: cget
handler: get
help: makes a requests and returns response code
manual: >
Cget makes an http request for the supplied url and returns the
response code that is returned by the http server. This is useful in
checking what responses a server may be sending back.
name: cget
parameters:
url:
retry_interval:
retry_count:
required:
url:
topic: net
usage: http cget url=http:\example.com\request
...
}
sub
_start {
my
(
$kernel
,
$self
,
$session
) =
@_
[KERNEL, OBJECT, SESSION];
$self
->Verbose(
"_start: tcli http starting"
);
if
(!
defined
(
$self
->name ))
{
$kernel
->yield(
'_start'
);
return
;
}
$kernel
->alias_set(
$self
->name);
$self
->set(\
@poco_cm
, POE::Component::Client::Keepalive->new(
max_per_host
=> 4,
max_open
=> 128,
keep_alive
=> 15,
timeout
=> 120,
));
$self
->set(\
@poco_http
, POE::Component::Client::HTTP->spawn(
Agent
=>
$self
->user_agents,
Alias
=>
'http-client'
,
ConnectionManager
=>
$poco_cm
[
$$self
],
));
$self
->Verbose(
" Dump "
.
$self
->
dump
(1),3 );
}
sub
_stop {
my
(
$kernel
,
$self
,) =
@_
[KERNEL, OBJECT,];
$self
->Verbose(
"_stop: "
.
$self
->name.
" stopping"
,2);
$poco_cm
[
$$self
]->
shutdown
;
$self
->set(\
@poco_cm
,
undef
);
}
sub
get {
my
(
$kernel
,
$self
,
$session
,
$request
, ) =
@_
[KERNEL, OBJECT, SESSION, ARG0, ];
my
$txt
=
''
;
my
$param
;
my
$command
=
$request
->command->[0];
my
$cmd
=
$self
->commands->{
$command
};
return
unless
(
$param
=
$cmd
->Validate(
$kernel
,
$request
,
$self
) );
$self
->Verbose(
"get: url("
.
$param
->{
'url'
}.
") "
);
$self
->Verbose(
"get: $command params"
,3,
$param
);
$param
->{
'try_count'
} = 1;
$param
->{
'completed'
} = 0;
$param
->{
'start_time'
} =
time
();
$self
->requests->{
$request
->id}{
'request'
} =
$request
;
$self
->requests->{
$request
->id}{
'param'
} =
$param
;
$kernel
->post(
'http-client'
=>
'request'
=>
'ProcessResponse'
=>
GET(
$param
->{
'url'
},
Connection
=>
"Keep-Alive"
,
),
$request
->id,
'ResponseProgress'
,
''
,
);
$request
->Respond(
$kernel
,
'Trying '
.
$param
->{
'url'
},100)
if
(
$param
->{
'http_verbose'
} );
return
;
}
sub
ProcessResponse {
my
(
$kernel
,
$self
,
$request_packet
,
$response_packet
) =
@_
[KERNEL, OBJECT, ARG0, ARG1 ];
$self
->Verbose(
"ProcessResponse: \tEntering "
.
$self
->name.
" "
,3 );
my
$http_request
=
$request_packet
->[0];
my
$http_response
=
$response_packet
->[0];
my
$id
=
$request_packet
->[1];
my
$request
=
$self
->requests->{
$id
}{
'request'
};
my
$param
=
$self
->requests->{
$id
}{
'param'
};
my
$txt
;
my
$backtxt
=
''
;
$self
->Verbose(
"ProcessResponse: for request id("
.
$id
.
")"
);
$self
->Verbose(
"ProcessResponse: request{"
.
$id
.
"}"
,3,
$request
);
$self
->Verbose(
"ProcessResponse: request{"
.
$id
.
"} param"
,2,
$param
);
$param
->{
'end_time'
} =
time
()
unless
defined
(
$param
->{
'end_time'
} );
if
(!
defined
$http_response
->code )
{
$self
->Verbose(
"ProcessResponse: Bad HTTP response code id("
.
$id
.
") "
,3);
$request
->Respond(
$kernel
,
"Error: "
.
$id
.
" Bad HTTP response code"
,400);
return
;
}
if
(
defined
(
$param
->{
'retry_interval'
} ) &&
$param
->{
'retry_count'
} >
$param
->{
'try_count'
} )
{
$self
->Verbose(
"ProcessResponse: id("
.
$id
.
") RETRY ri("
.
$param
->{
'retry_interval'
}.
") rc("
.
$param
->{
'retry_count'
}.
") tries("
.
$param
->{
'try_count'
}.
") "
,2);
$kernel
->delay(
'retry'
=>
$param
->{
'retry_interval'
},
$id
);
}
else
{
$param
->{
'completed'
} = 1;
$self
->Verbose(
"ProcessResponse: id("
.
$id
.
") COMPLETED ri("
.
$param
->{
'retry_interval'
}.
") rc("
.
$param
->{
'retry_count'
}.
") tries("
.
$param
->{
'try_count'
}.
") "
,2);
}
$self
->Verbose(
"ProcessResponse: id{"
.
$id
.
"} command("
.
$request
->command->[0].
") "
);
if
(
$request
->command->[0] eq
'tget'
&&
$param
->{
'completed'
} )
{
if
(
$txt
=
$self
->NotWithin(
$http_response
->code(),
$param
->{
'response_code'
} ) )
{
$txt
=
"failed "
.
$id
.
" - response within ("
.
$param
->{
'response_code'
}.
")"
.
"\n#\texpected in the range ("
.
$param
->{
'response_code'
}.
")"
.
" got ("
.
$http_response
->code().
")"
.
" for url "
.
$param
->{
'url'
}.
"\n"
.
$txt
;
}
else
{
$txt
=
"ok "
.
$id
.
" - response within ("
.
$param
->{
'response_code'
}.
")"
.
" "
;
}
$self
->Verbose(
"ProcessResponse: tget code txt("
.
$txt
.
$backtxt
.
") "
,3);
$request
->Respond(
$kernel
,
$txt
.
$backtxt
);
return
;
}
elsif
(
$request
->command->[0] eq
'tget'
&& not
$param
->{
'completed'
} )
{
$self
->Verbose(
"ProcessResponse: tget tries("
.
$param
->{
'try_count'
}.
") rc("
.
$param
->{
'retry_count'
}.
") "
,3);
return
;
}
elsif
(
$request
->command->[0] eq
'cget'
)
{
$txt
=
$param
->{
'url'
}.
" "
.
"resp="
.
$http_response
->code().
" "
;
if
(
$param
->{
'retry_count'
} > 1 )
{
$txt
.=
"try="
.
$param
->{
'try_count'
}.
" "
;
}
$self
->Verbose(
"ProcessResponse: get txt("
.
$txt
.
$backtxt
.
") "
,3);
$request
->Respond(
$kernel
,
$txt
.
$backtxt
);
return
;
}
$self
->Verbose(
"ProcessResponse: WHOOPS! id{"
.
$id
.
"} "
,1,
$request
);
}
sub
retry {
my
(
$kernel
,
$self
,
$id
) =
@_
[KERNEL, OBJECT, ARG0 ];
my
$txt
;
$self
->Verbose(
"retry: id("
.
$id
.
") "
);
my
$request
=
$self
->requests->{
$id
}{
'request'
};
my
$param
=
$self
->requests->{
$id
}{
'param'
};
$param
->{
'try_count'
}++ ;
$kernel
->post(
'http-client'
=>
'request'
=>
'ProcessResponse'
=>
GET(
$param
->{
'url'
},
Connection
=>
"Keep-Alive"
,
),
$id
,
'ResponseProgress'
,
''
,
);
}
sub
ResponseProgress {
my
(
$kernel
,
$self
,
$gen_args
,
$call_args
) =
@_
[KERNEL, OBJECT, ARG0, ARG1 ];
$self
->Verbose(
"ResponseProgress: \tEntering "
.
$self
->name.
" "
);
my
$req
=
$gen_args
->[0];
my
$tag
=
$gen_args
->[1];
my
$got
=
$call_args
->[0];
my
$tot
=
$call_args
->[1];
my
$oct
=
$call_args
->[2];
my
$percent
=
$got
/
$tot
* 100;
my
$request
=
$self
->requests->{
$tag
}{
'request'
};
}
1;