Apache...:Config(3pm)
π Apache::Admin::Config π
okay so bestie, welcome to Apache::Admin::Config, from the 3pm manual pages (Perl, obviously π
). This is the module for reading and writing Apache-style config files, and honestly? It's giving main character energy. Let's get into it π«Ά
β¨ NAME β¨
Apache::Admin::Config β a whole module dedicated to reading AND writing Apache-like configuration files. Both directions. Iconic. π
πΈ SYNOPSIS πΈ
here's the vibe, copy-paste ready, no cap:
use Apache::Admin::Config;
# Parse an apache configuration file
my $conf = new Apache::Admin::Config "/path/to/config_file.conf"
or die $Apache::Admin::Config::ERROR;
my $directive = $conf->directive('documentroot');
print $directive->name; # "documentroot"
print $directive->value; # "/my/document/root"
print $directive->type; # "directive"
$directive->isin($conf); # true
$directive->delete;
# print the directive list
foreach($conf->directive())
{
print $_->name, "\n";
}
# print the virtualhost list
print $_->section('servername')->value(), "\n"
foreach $conf->section(-name => "virtualhost");
# add a directive in all virtualhosts
foreach($conf->section(-name => "virtualhost"))
{
$_->add_directive(php_admin_value => 'open_basedir "/path"');
}
# Deleting all "AddType" directives
$_->delete for $conf->directive("AddType");
# saving changes in place
$conf->save;
like. look at that. parse a file, poke at directives, loop through virtualhosts, add stuff to every single one of them, delete a whole directive type in one line, save it back. all of it. slay π
π¦ DESCRIPTION π¦
Apache::Admin::Config hands you an object oriented interface for reading and writing Apache-like configuration files, and the best part? It does it without touching your comments, your indentation, or your truncated lines. Your file stays exactly as pretty as you left it. periodt. π
You can pull info out of an apache config super easily, or you can manage htaccess files. Either way, you're eating. π
So why does this module even exist? Story time π§: the author wrote this class because they work for an IPP, and they were constantly manipulating apache configuration files β adding new clients, activating features, locking and unlocking directories via htaccess, all of it. It's also lowkey perfect for writing one-shot migration scripts in just a few lines. β¨
fr fr, if you've ever hand-edited an apache config at 2am and broken prod, this module is your emotional support bestie. π«Ά
more coming bestie, don't go anywhere π
β¨ METHODES β¨
new π
$obj = new Apache::Admin::Config [/path/to/file|handle],
[-indent => $integer], ['-create'], ['-no-comment-grouping'],
['-no-blank-grouping']
Okay so create or read β if you pass it β an apache-like config file, and it hands you back an Apache::Admin::Config instance. Iconic. β¨
Arguments:
/path/to/fileβ Path to the configuration file to parse. If none given, create a new one. πhandleβ Instead of specifying a path to a file, you can give a reference to a handle that points to an already opened file. You can do this like this:
my $obj = new Apache::Admin::Config (\*MYHANDLE);
-indent => $integerβ If greater than 0, activates the indentation on added lines. The integer tells how many spaces you went per level of indentation (suggest 4). A negative value means padding with tabulation(s). π-createβ If present and path to an unexisting file is given, don't return an error. π-no-comment-groupingβ When there are several successive comment-lines, if comment grouping is enabled only one comment item is created. If present, disable comment grouping at parsing time. Enabled by default. π¬-no-blank-groupingβ Same as comment grouping but for blank lines. β¬
save πΎ
$obj->save(['/path/to/file'|HANDLE], ['-reformat'])
Write modifications to the configuration file. If a path to a file is given, save the modification to this file instead. You also can give a reference to a filehandle like this:
$conf->save(\*MYHANDLE) or die($conf->error());
Note: If you invoke save() on an object instantiated with a filehandle, you should emptied it before. Keep in mind that the constructor don't seek the FH to the begin neither before nor after reading it. Read that twice, bestie. π
dump_raw π¦
$obj->dump_raw
Returns the configuration file as same as it will be if it was saved in a file with the save() method. If you don't call this method from the top level section, it returns the part of the configuration file that is under the object's context.
dump_reformat π
$obj->dump_raw
Same as dump_raw(), but reformat each line. Usefull used with -indent constructor parameter. β¨
select π
@result = $obj->select
(
[-type => $type],
[-name => $name],
[-value => $value],
[-which => $index],
);
@directives = $obj->select('directive');
@sections_foo = $obj->select('section', 'Foo');
This method search in the current context for items (directives, sections, comments...) that correspond to a properties given by arguments. It returns a list of matched nods. π
This method can only be called on an object of type "section". This method search only for elements in the section pointed by object, and isn't recursive. So elements in sub-sections of current section aren's seek (it's not a bug). Not a bug, just the vibe. π¦
Arguments:
typeβ Selects item(s) oftypetype.nameβ Selects item(s) withnamename.valueβ Selects item(s) withvaluevalue.whichβ Instead of returning a list of items, returns only a single one pointed by index given to the-whichoption. Caution, returns an empty string if none selected, so don't cascade your methodes calls like$obj->select(-which=>0)->name. Index starts at 0. No cascading, periodt. π
Method returns a list of item(s) founds. Each items is an Apache::Admin::Config object with same methods but pointing to a different part of the tree.
directive π
@directives = $obj->directive(args...)
Same as calling select('directive', args...).
section ποΈ
@sections = $obj->section(args...)
Same as calling select('section', args...).
comment π¬
@comments = $obj->comment(args...)
Same as calling select('comment', args...).
blank β¬
@blanks = $obj->blank(args...)
Same as calling select('blank', args...).
set_write_directive π οΈ
$conf->set_write_directive($code);
Replace the directive writing engine by you own code. Code is call for adding new directives, or when you tell Apache::Admin::Config to reformat the whole configuration file. See save() and dump_reformat() methods for more details.
Your handler receives 3 arguments : $self, $name and $value. You can call the "indent()" method to get the number of spaces to put before the current line (see indent() methods for more details)
$conf->set_write_directive(sub
{
my($self, $name, $value) = @_;
return $self->indent . "$name $value\n";
}
set_write_section π§±
$conf->set_write_section($code);
Same as set_write_directive() but for section.
Your handler receives 3 arguments: $self, $name and $value. You can call the "indent()" method to get the number of spaces to put before the current line (see indent() methods for more details)
$conf->set_write_section(sub
{
my($self, $name, $value) = @_;
return $self->indent . "<$name $value>\n";
}
set_write_section_closing π
$conf->set_write_section_closing($code);
Same as set_write_directive() but for end of sections.
Your handler receives 2 arguments: $self and $name. You can call the "indent()" method to get the number of spaces to put before the current line (see indent() methods for more details)
$conf->set_write_section_closing(sub
{
my($self, $name) = @_;
return $self->indent . "</$name>\n";
}
set_write_comment π
$conf->set_write_comment($code);
Same as set_write_directive() but for comments.
Your handler receives 2 arguments: $self and $value. You can call the "indent()" method to get the number of spaces to put before the current line (see indent() methods for more details)
$conf->set_write_comment(sub
{
my($self, $value) = @_;
# handle comment grouping
$value =~ s/\n/\n# /g;
return $self->indent . join('#', split(/\n/, $value));
}
set_write_blank π«§
$conf->set_write_blank($code);
Same as set_write_directive() but for blank lines.
Your handler receives 2 arguments: $self and $number.
$conf->set_write_blank(sub
{
my($self, $number) = @_;
return $number x "\n";
}
add β
$item = $obj->add
(
$type|$item, [$name], [$value],
[-before => $target | -after => $target | '-ontop' | '-onbottom']
);
$item = $obj->add('section', foo => 'bar', -after => $conf_item_object);
$item = $obj->add('comment', 'a simple comment', '-ontop');
Add a line of type $type with name foo and value bar in the context pointed by $object.
Aguments:
typeβ Type of object to add (directive, section, comment or blank).nameβ Only relevant for directives and sections.valueβ For directive and section, it defines the value, for comments it defined the text.-before=> target β Inserts item one line before target. target _have_ to be in the same context.-after=> target β Inserts item one line after target. target _have_ to be in the same context.-ontopβ Insert item on the fist line of current context;-onbottomβ Iinsert item on the last line of current context;
Returns the added item.
add_section π·οΈ
$section = $obj->add_section($name, $value)
Same as calling add('section', $name, $value)
add_directive π
$directive = $obj->add_directive($name, $value)
Same as calling add('directive', $name, $value)
add_comment π¬
$comment = $obj->add_comment("string", [$group])
Same as calling add('comment', 'string', )
$group is a boolean value that control grouping of consecutive comment lines. Disabled by default.
add_blank β¬
$blank = $obj->add_blank([$group])
Same as calling add('blank')
$group is a boolean value that control grouping of consecutive blank lines. Enabled by default.
set_value π§
$obj->set_value($newvalue)
Change the value of a directive or section. If no argument given, return the value.
value π
Returns the value of item pointed by the object if any.
(Actually "value" and "set_value" are the same method)
move π
$obj->move
(
$dest_section,
-before => target |
-after => $target |
'-ontop' |
'-onbottom'
)
Move item into given section. See "add()" method for options description.
copy π
$item->copy
(
$dest_section,
-before => target |
-after => $target |
'-ontop' |
'-onbottom'
)
Copy item into given section. See "add()" method for options description.
clone π§¬
$clone = $item->clone();
Clone item and all its children. Returns the cloned item.
first_line π
No extra description in the original β just the name, periodt. π
last_line π
Same, no extra description in the original. β¨
count_lines π’
Still no extra description in the original. π«Ά
isin π§
$boolean = $obj->($section_obj, ['-recursif'])
Returns true if object point to a rule that is in the section represented by $section_obj. If "-recursif" option is present, true is also return if object is a sub-section of target.
<section target>
<sub section>
directive test
</sub>
</section>
$test_directive->isin($target_section) => return false
$test_directive->isin($sub_section) => return true
$test_directive->isin($target_section, '-recursif') => return true
$target_section->isin($target_section) => return true
name π·οΈ
Returns the name of the current pointed object if any.
parent πͺ
Returns the parent context of object. This method on the top level object returns "undef".
type π
Returns the type of object.
remove β
Synonym for unlink (deprecated). See unlink().
unlink βοΈ
$boolean = $item->unlink();
Unlinks item from the tree, resulting in two separate trees. The item to unlink becomes the root of a new tree.
destroy π₯
$boolean = $item->destroy();
Destroy item and its children. Caution, you should call delete() method instead if you want destroy a part of a tree. This method don't notice item's parents of its death.
delete ποΈ
$booleen = $item->delete;
Remove the current item from it's parent children list and destroy it and all its children (remove() + destroy()).
error β οΈ
Return the last appended error.
β¨ EXAMPLES β¨
Okay bestie, this is the part where it all comes together π These are the actual real-life glow-ups people do with this module, and yes they're all copy-pasteable, no cap.
π Reindent a config file, but make it cute
Want your httpd.conf to stop looking like it was formatted by a raccoon? Say less:
#
# Reindent configuration file properly
#
my $conf = Apache::Admin::Config
(
'/etc/apache/httpd.conf',
-indent => 2
);
$conf->save('-reformat');
That's it. Two-space indent, reformatted, saved. The vibes are immaculate. β¨
πΈ Managing virtual-hosts (the main character move)
#
# Managing virtual-hosts:
#
my $conf = new Apache::Admin::Config "/etc/apache/httpd.conf";
# adding a new virtual-host:
my $vhost = $conf->add_section(VirtualHost=>'127.0.0.1');
$vhost->add_directive(ServerAdmin=>'webmaster@localhost.localdomain');
$vhost->add_directive(DocumentRoot=>'/usr/share/www');
$vhost->add_directive(ServerName=>'www.localhost.localdomain');
$vhost->add_directive(ErrorLog=>'/var/log/apache/www-error.log');
my $location = $vhost->add_section(Location=>'/admin');
$location->add_directive(AuthType=>'basic');
$location->add_directive(Require=>'group admin');
$conf->save;
# selecting a virtual-host:
my $vhost;
foreach my $vh (@{$conf->section('VirtualHost')})
{
if($vh->directive('ServerName')->value eq 'www.localhost.localdomain')
{
$vhost = $vh;
last;
}
}
So you're building a whole vhost from scratch, nesting a <Location /admin> inside it, and locking that admin area down with basic auth. Then $conf->save and it's done. And when you need to find that vhost again later? You loop through $conf->section('VirtualHost') and vibe-check the ServerName directive's value until it matches. Chef's kiss π
π Suppress ALL the comments
Sometimes you just want the raw config, no commentary:
#
# Suppress all comments in the file
#
sub delete_comments
{
foreach(shift->comment)
{
$_->delete;
}
}
sub delete_all_comments
{
foreach($_[0]->section)
{
delete_all_comments($_);
}
delete_comments($_[0]);
}
delete_all_comments($conf);
Notice how delete_all_comments recurses down into every section before nuking the comments at its own level? That's because sections can be nested inside sections, and comments can be hiding anywhere. She's thorough. She's methodical. She's iconic. π¦
π Transform the config into XML (yes, really)
This one is the showstopper. You override the write callbacks and suddenly your Apache config speaks XML:
#
# Transform configuration file into XML format
#
my $c = new Apache::Admin::Config "/path/to/file", -indent => 2
or die $Apache::Admin::Config::ERROR;
$c->set_write_directive(sub {
my($self, $name, $value) = @_;
return($self->indent.qq(<directive name="$name" value="$value />\n));
});
$c->set_write_section(sub {
my($self, $name, $value) = @_;
return($self->indent.qq(<section name="$name" value="$value">\n));
});
$c->set_write_section_closing(sub {
my($self, $name) = @_;
return($self->indent."</section>\n");
});
$c->set_write_comment(sub {
my($self, $value) = @_;
$value =~ s/\n//g;
return($self->indent."<!-- $value -->");
});
print $c->dump_reformat();
Four overrides β set_write_directive, set_write_section, set_write_section_closing, and set_write_comment β and then dump_reformat() spits out the whole thing in your custom format. The -indent => 2 still does the pretty-printing, and the comment writer strips newlines with s/\n//g before wrapping in <!-- -->. Lowkey genius, highkey reusable. π₯
π AUTHOR π
Olivier Poitrey <rs@rhapsodyk.net> β the legend herself. Respect. π«Ά
π AVAILABILITY π
The official FTP location is:
ftp://ftp.rhapsodyk.net/pub/devel/perl/Apache-Admin-Config-current.tar.gz
Also available on CPAN. (CPAN bestie, always CPAN π)
Anonymous CVS repository:
CVS_RSH=ssh cvs -d anonymous@cvs.rhapsodyk.net:/devel co Apache-Admin-Config
(Supply an empty string as password β just hit enter, she's not picky π)
CVS repository on the web:
http://www.rhapsodyk.net/cgi-bin/cvsweb/Apache-Admin-Config/
π BUGS π
Found something broken? Please send bug-reports to <aac@list.rhapsodyk.net>. You can subscribe to the list by sending an empty mail to <aac-subscribe@list.rhapsodyk.net>.
Fr fr, don't just suffer in silence with a weird parsing bug β the mailing list is right there. Empty email, instant subscription, you're in. π
β LICENCE β
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
Okay this part is the boring-but-important one, so listen up: no warranty, periodt. It might be perfect, it might not, and legally she's not promising either way. That's just how LGPL rolls. π
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
π COPYRIGHT π
Copyright (C) 2001 - Olivier Poitrey
And that's the whole page, bestie!! π¦ You made it to the end, which honestly? Main character energy. This beauty is documented as perl v5.36.0, dated 2022-12-09, and it lives under the name Apache...:Config(3pm) β go forth and parse some Apache configs, you absolute icon. β¨ππ
π¦ where this page comes from
- debian bookworm: libapache-admin-config-perl 0.95-3 Β· LGPL-2.1-or-later
- debian trixie: libapache-admin-config-perl 0.95-3 Β· LGPL-2.1-or-later
- ubuntu noble: libapache-admin-config-perl 0.95-3 Β· LGPL-2.1-or-later
- ubuntu resolute: libapache-admin-config-perl 0.95-3 Β· LGPL-2.1-or-later
- ubuntu stonking: libapache-admin-config-perl 0.95-3 Β· LGPL-2.1-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms