package RunApp::Apache;
use strict;
use File::Spec::Functions qw(catfile catdir);
use base qw(RunApp); # child of RunApp because of build
use File::Copy qw(copy);
use File::Path;
sub get_info {
my $self = shift;
my $info;
my $ret = `$self->{httpd} -V`;
($info->{AP_VERSION}) = $ret =~ m{version: Apache/(\d)};
for ($ret =~ m/-D\s*(\S*)/mg) {
my ($key, $value) = m/^(\w+)(?:="?(.*?)"?)?$/;
die $_ unless defined $key;
$info->{$key} = defined $value ? $value : 1;
}
if ($self->{apxs}) {
$info->{$_} = $self->ap_query ($_) for @_;
}
return $info;
}
sub ap_query {
my ($self, $var) = @_;
my $ret = `$self->{apxs} -q $var`;
chomp $ret;
return $ret;
}
sub new {
my $class = shift;
my $self = bless {}, $class;
%$self = @_;
my %ctlarg;
if ($self->{apxs}) {
my $httpd = catfile($self->ap_query ('SBINDIR'), $self->ap_query ('TARGET'));
if (defined $self->{httpd} && $self->{httpd} ne $httpd) {
warn ". Warning: httpd setting disagreed with apxs\n";
}
$self->{httpd} = $httpd;
}
$self->{ctl_file} = catfile($self->{root}, "apachectl");
$self->{config_file} = catfile($self->{root}, "conf", 'httpd.conf');
$self->{mime_file} ||= catfile($self->{root}, "conf", 'mime.types');
$self->{CONF} ||= 'RunApp::Template::Apache';
unless ($self->{CTL}) {
$self->{CTL} = 'RunApp::Control::AppControl';
%ctlarg = ( args => ['-f', $self->{config_file}],
binary => $self->{httpd},
CONTROL => 'App::Control::Apache',
);
}
$self->load($_) for @{$self}{qw/CONF CTL/};
$self->services ( conf => $self->{CONF}->new (file => $self->{config_file}),
ctl => $self->{CTL}->new (file => $self->{ctl_file}, %ctlarg)
);
return $self;
}
sub build {
my ($self, $conf) = @_;
my $info = $self->get_info ('LIBEXECDIR');
undef $conf->{logs} if ref $conf->{logs}; # XXX: something else
$conf->{logs} ||= catfile($self->{root}, 'logs');
$conf->{pidfile} ||= catfile($conf->{logs}, 'httpd.pid');
$self->{_debug} = catfile($conf->{logs}, 'error_log');
mkpath [catfile ($self->{root}, 'conf'),
$conf->{logs}] or die $!
unless -d $self->{root};
my $apacheconf = {
MinSpareServers => 2,
MaxSpareServers => 2,
StartServers => 2,
MaxClients => 100,
MaxRequestsPerChild => 100,
user => (getpwuid($>) || ''),
group => (getgrgid($)) || ''),
};
# final tweak
my $combined = {%$apacheconf, %$self, %$conf, %$info};
# they don't like multi-request in a process.
$combined->{MaxRequestsPerChild} = 1 if $combined->{cover} || $combined->{profiler};
$self->SUPER::build ($combined);
my $mimefile = $info->{TYPES_CONFIG_FILE} || $info->{AP_TYPES_CONFIG_FILE};
$mimefile = catfile($info->{HTTPD_ROOT}, $mimefile)
unless File::Spec->file_name_is_absolute( $mimefile );
if (-r $mimefile) {
copy ($mimefile, $self->{mime_file});
}
else {
warn ". Warning: cant find $mimefile\n";
}
chmod 0755, $self->{ctl_file};
}
sub report {
my ($self, $conf) = @_;
return unless $self->{report};
print "Point your browser at the following URL to see the website:\n";
for (qw/port port_https/) {
next unless $conf->{$_};
print "http://$conf->{hostname}:$conf->{$_}/\n";
}
}
sub debug {
my ($self) = @_;
return unless $self->{_debug};
if (fork) {
return;
}
else {
system ('tail', -f => $self->{_debug});
exit;
}
}
sub dispatch {
my ($self, $cmd) = @_;
#warn ". $cmd => $self->{httpd}\n";
$self->{services}->{ctl}->$cmd;
}
1;
=head1 NAME
RunApp::Apache - Apache control for RunApp
=head1 SYNOPSIS
use RunApp::Apache;
$apache = RunApp::Apache->new
(root => "/tmp/apache_run",
report => 1,
apxs => '/usr/local/sbin/apxs',
# httpd => '/usr/local/sbin/httpd',
required_modules => ["log_config", "alias", "perl", "mime"],
config_block => q{
[% IF AP_VERSION == 2 %]
eval { use Apache2 };
eval { use Apache::compat };
[% END %]
AllowOverride None
SetHandler perl-script
PerlSetVar approot [% cwd %]
PerlHandler MyApp
Options +ExecCGI
});
=head1 DESCRIPTION
This is the class for defining a apache web server to be used in
L.
=head1 CONSTRUCTOR
=head2 new (%arg)
Required arg:
=over
=item root
The root for the apache instance.
=item apxs
=item httpd
If C is specified, C will be derived from it.
=item required_modules
A arrayref to the apache modules required.
=item config_block
The config block that will be the I block in the template used
by L.
=item CTL
The class for handling apachectl. The default is
L. You can also use
L.
=item CONF
The class for handling apache config. The default is
L. It is used in the C phase of
L
=back
=cut
=head1 SEE ALSO
L, L, L, L
=head1 AUTHORS
Chia-liang Kao
Refactored from works by Leon Brocard Eacme@astray.comE and
Tom Insam Etinsam@fotango.comE.
=head1 COPYRIGHT
Copyright (C) 2002-5, Fotango Ltd.
This module is free software; you can redistribute it or modify it
under the same terms as Perl itself.
=cut
1;