__PACKAGE__->mk_classdata(
'notify_hub'
);
sub
setup
{
my
$c
=
shift
;
$c
->notify_hub( Event::Notify->new );
$c
->setup_log();
$c
->setup_provider();
$c
->setup_handler();
$c
->setup_engine();
$c
->setup_plugins();
$c
;
}
sub
setup_log
{
my
$c
=
shift
;
my
$log_config
= { %{
$c
->config->{
log
} || {
logs
=> [] }} };
my
$module
=
delete
$log_config
->{module} ||
'Simple'
;
my
$pkg
=
$c
->load_gungho_module(
$module
,
'Log'
);
my
$log
=
$pkg
->new(
config
=>
$log_config
->{config} ||
$log_config
);
$log
->setup(
$c
);
$c
->
log
(
$log
);
}
sub
setup_provider
{
my
$c
=
shift
;
my
$config
=
$c
->config->{provider};
my
$ref
=
ref
$config
;
if
(!
$config
|| !
defined
$ref
) {
Carp::croak(
"Gungho requires a provider"
);
}
if
(
$ref
eq
'CODE'
) {
my
$code
=
$config
;
$config
= {
module
=>
"Inline"
,
config
=> {
callback
=>
$code
}
}
}
elsif
(
$ref
ne
'HASH'
) {
Carp::croak(
"Gungho requires a provider"
);
}
my
$pkg
=
$c
->load_gungho_module(
$config
->{module},
'Provider'
);
$pkg
->isa(
'Gungho::Provider'
) or
die
"$pkg is not a Gungho::Provider subclass"
;
my
$obj
=
$pkg
->new(
config
=>
$config
->{config} || {} );
$obj
->setup(
$c
);
$c
->provider(
$obj
);
}
sub
setup_engine
{
my
$c
=
shift
;
my
$config
=
$c
->config->{engine} || {
module
=>
'POE'
,
};
if
(!
$config
||
ref
$config
ne
'HASH'
) {
Carp::croak(
"Gungho requires a engine"
);
}
my
$pkg
=
$c
->load_gungho_module(
$config
->{module},
'Engine'
);
$pkg
->isa(
'Gungho::Engine'
) or
die
"$pkg is not a Gungho::Engine subclass"
;
my
$obj
=
$pkg
->new(
config
=>
$config
->{config} || {} );
$obj
->setup(
$c
);
$c
->engine(
$obj
);
}
sub
setup_handler
{
my
$c
=
shift
;
my
$config
=
$c
->config->{handler} || {
module
=>
'Null'
,
config
=> {}
};
my
$ref
=
ref
$config
;
if
(!
$config
|| !
defined
$ref
) {
Carp::croak(
"Gungho requires a handler"
);
}
if
(
$ref
eq
'CODE'
) {
my
$code
=
$config
;
$config
= {
module
=>
"Inline"
,
config
=> {
callback
=>
$code
}
}
}
elsif
(
$ref
ne
'HASH'
) {
Carp::croak(
"Gungho requires a handler"
);
}
my
$pkg
=
$c
->load_gungho_module(
$config
->{module},
'Handler'
);
$pkg
->isa(
'Gungho::Handler'
) or
die
"$pkg is not a Gungho::Handler subclass"
;
my
$obj
=
$pkg
->new(
config
=>
$config
->{config} || {});
$obj
->setup(
$c
);
$c
->handler(
$obj
);
}
sub
setup_plugins
{
my
$c
=
shift
;
my
$plugins
=
$c
->config->{plugins} || [];
foreach
my
$plugin
(
@$plugins
) {
my
$pkg
=
$c
->load_gungho_module(
$plugin
->{module},
'Plugin'
);
my
$obj
=
$pkg
->new(
config
=>
$plugin
->{config} || {});
$obj
->setup(
$c
);
}
}
sub
has_feature
{
my
(
$c
,
$name
) =
@_
;
return
exists
$c
->features()->{
$name
};
}
sub
load_gungho_module
{
my
(
$c
,
$pkg
,
$prefix
) =
@_
;
return
Gungho::Util::load_module(
$pkg
,
$prefix
?
"Gungho::${prefix}"
:
"Gunho"
);
Class::Inspector->loaded(
$pkg
) or
$pkg
->
require
or
die
;
return
$pkg
;
}
sub
dispatch_requests
{
my
$c
=
shift
;
if
(
$c
->is_running) {
$c
->provider->dispatch(
$c
,
@_
);
$c
->notify(
'dispatch.dispatch_requests'
);
}
}
sub
prepare_request
{
my
$c
=
shift
;
my
$req
=
shift
;
$c
->notify(
'dispatch.prepare_request'
,
$req
);
return
$req
;
}
sub
prepare_response
{
my
(
$c
,
$res
) =
@_
;
{
my
$old
=
$res
;
$res
= Gungho::Response->new(
$res
->code,
$res
->message,
$res
->headers,
$res
->content
);
$res
->request(
$old
->request );
}
return
$res
;
}
sub
send_request
{
my
$c
=
shift
;
my
$request
=
shift
;
$request
=
$c
->prepare_request(
$request
);
return
$c
->engine->send_request(
$c
,
$request
);
}
sub
pushback_request
{
my
(
$c
,
$request
) =
@_
;
$c
->provider->pushback_request(
$c
,
$request
);
}
sub
request_is_allowed { 1 }
sub
handle_response
{
my
$c
=
shift
;
my
(
$req
,
$res
) =
@_
;
my
$e
;
eval
{
$c
->maybe::
next
::method(
$req
,
$res
);
};
if
(
$e
= Gungho::Exception->caught(
'Gungho::Exception::HandleResponse::Handled'
)) {
return
;
}
elsif
(
$e
= Gungho::Exception->caught()) {
die
$e
;
}
$c
->handler->handle_response(
$c
,
$req
,
$res
);
}
sub
handle_dns_response
{
my
(
$c
,
$request
,
$answer
,
$dns_response
) =
@_
;
my
$host
=
$request
->uri->host;
my
$addr
=
$answer
->address;
$request
->header(
Host
=>
$host
);
$request
->notes(
original_host
=>
$host
);
$request
->notes(
resolved_ip
=>
$addr
);
eval
{
$c
->send_request(
$request
);
};
if
(
my
$e
= $@) {
if
(
$e
->isa(
'Gungho::Exception::RequestThrottled'
)) {
$c
->provider->pushback_request(
$c
,
$request
);
}
else
{
die
$e
;
}
}
return
1;
}
sub
_http_error
{
my
(
$self
,
$code
,
$message
,
$request
) =
@_
;
my
$nl
=
"\n"
;
my
$r
= Gungho::Response->new(
$code
);
my
$http_msg
= status_message(
$code
);
my
$m
= (
"<html>$nl"
.
"<HEAD><TITLE>Error: $http_msg</TITLE></HEAD>$nl"
.
"<BODY>$nl"
.
"<H1>Error: $http_msg</H1>$nl"
.
"$message$nl"
.
"</BODY>$nl"
.
"</HTML>$nl"
);
$r
->content(
$m
);
$r
->request(
$request
);
return
$r
;
}
sub
register_event
{
my
$c
=
shift
;
$c
->notify_hub->register_event(
@_
);
}
*register_hook
= \
®ister_event
;
sub
unregister_event
{
my
$c
=
shift
;
$c
->notify_hub->unregister_event(
@_
);
}
sub
notify
{
my
(
$c
,
$event
,
@args
) =
@_
;
$c
->notify_hub->notify(
$event
,
$c
,
@args
);
}
*run_hook
= \
¬ify
;
sub
shutdown
{
my
(
$c
,
$reason
) =
@_
;
$reason
||=
'unknown reason'
;
$c
->
log
->notice(
"Gungho received a shutdown request!: '$reason'"
);
$c
->is_running(0);
$c
->provider->stop(
$reason
);
$c
->handler->stop(
$reason
);
$c
->engine->stop(
$reason
);
}
1;