In order to switch between different server configurations by just supplying
another Host header, it'd be useful to have name based VHs in our testsuite.
The attached patch tries to solve this problem. The Syntax is like

<VirtualHost servername:module>
...
</VirtualHost>

If servername is not _default_, the above will be transformed to:

Listen $port
NameVirtualHost *:$port
<VirtualHost *:$port>
    ServerName $servername:$port (or 1.3 like, however)
    ...
</VirtualHost>

A sample input and transformation are also attached. Opinions?

nd
# WARNING: this file is generated, do not edit
# 01: 
/work/nd/cvs/apache.org/httpd-test/perl-framework/Apache-Test/lib/Apache/TestConfig.pm:739
# 02: 
/work/nd/cvs/apache.org/httpd-test/perl-framework/Apache-Test/lib/Apache/TestConfig.pm:756
# 03: 
/work/nd/cvs/apache.org/httpd-test/perl-framework/Apache-Test/lib/Apache/TestConfig.pm:1143
# 04: 
/work/nd/cvs/apache.org/httpd-test/perl-framework/Apache-Test/lib/Apache/TestConfig.pm:1342
# 05: 
/work/nd/cvs/apache.org/httpd-test/perl-framework/Apache-Test/lib/Apache/TestRun.pm:339
# 06: 
/work/nd/cvs/apache.org/httpd-test/perl-framework/Apache-Test/lib/Apache/TestRun.pm:386
# 07: 
/work/nd/cvs/apache.org/httpd-test/perl-framework/Apache-Test/lib/Apache/TestRun.pm:589
# 08: 
/work/nd/cvs/apache.org/httpd-test/perl-framework/Apache-Test/lib/Apache/TestRun.pm:589
# 09: t/TEST:22

<IfDefine APACHE2>
<IfModule mod_include.c>

    <Directory 
/work/nd/cvs/apache.org/httpd-test/perl-framework/t/htdocs/modules/include>
        Options Includes
        AddOutputFilter INCLUDES .shtml
    </Directory>

    Listen 8533

    NameVirtualHost *:8533

    <VirtualHost *:8533>
        ServerName ssi-default:8533

        DocumentRoot 
/work/nd/cvs/apache.org/httpd-test/perl-framework/t/htdocs/modules/include
    </VirtualHost>

    <VirtualHost *:8533>
        ServerName ssi-retagged:8533

        DocumentRoot 
/work/nd/cvs/apache.org/httpd-test/perl-framework/t/htdocs/modules/include

        SSIStartTag --->
        SSIEndTag   --->
    </VirtualHost>

</IfModule>
</IfDefine>
<IfDefine APACHE2>
<IfModule mod_include.c>

    <Directory @SERVERROOT@/htdocs/modules/include>
        Options Includes
        AddOutputFilter INCLUDES .shtml
    </Directory>

    <VirtualHost ssi-default:mod_include>
        DocumentRoot @SERVERROOT@/htdocs/modules/include
    </VirtualHost>

    <VirtualHost ssi-retagged:mod_include>
        DocumentRoot @SERVERROOT@/htdocs/modules/include

        SSIStartTag --->
        SSIEndTag   --->
    </VirtualHost>

</IfModule>
</IfDefine>


diff -Nur httpd-test~/Apache-Test/lib/Apache/TestConfig.pm httpd-test/Apache-Test/lib/Apache/TestConfig.pm
--- httpd-test~/Apache-Test/lib/Apache/TestConfig.pm
+++ httpd-test/Apache-Test/lib/Apache/TestConfig.pm
@@ -927,10 +927,11 @@
 sub parse_vhost {
     my($self, $line) = @_;
 
-    my($indent, $module);
-    if ($line =~ /^(\s*)<VirtualHost\s+(?:_default_:)?(.*?)\s*>\s*$/) {
-        $indent = $1 || "";
-        $module = $2;
+    my($indent, $module, $namebased);
+    if ($line =~ /^(\s*)<VirtualHost\s+(?:_default_:|([^:]+):)?(.*?)\s*>\s*$/) {
+        $indent    = $1 || "";
+        $namebased = $2 || "";
+        $module    = $3;
     }
     else {
         return undef;
@@ -956,14 +957,23 @@
     }
 
     #allocate a port and configure this module into $self->{vhosts}
-    my $port = $self->new_vhost($module);
+    my $port = $self->new_vhost($module, $namebased);
 
     #extra config that should go *inside* the <VirtualHost ...>
-    my @in_config = $self->servername_config($vars->{servername},
+    my @in_config = $self->servername_config($namebased
+                                               ? $namebased
+                                               : $vars->{servername},
                                              $port);
 
-    #extra config that should go *outside* the <VirtualHost ...>
-    my @out_config = ([Listen => $port]);
+    my @out_config;
+    if ($self->{vhosts}->{$module}->{namebased} < 2) {
+        #extra config that should go *outside* the <VirtualHost ...>
+        @out_config = ([Listen => $port]);
+
+        if ($self->{vhosts}->{$module}->{namebased}) {
+            push @out_config => [NameVirtualHost => "*:$port"];
+        }
+    }
 
     #there are two ways of building a vhost
     #first is when we parse test .pm and .c files
@@ -989,7 +999,8 @@
         #used when parsing *.conf.in files
         in_string     => $form_string->($double_indent, @in_config),
         out_string    => $form_string->($indent, @out_config),
-        line          => "$indent<VirtualHost _default_:$port>",
+        line          => "$indent<VirtualHost ". ($namebased? '*': '_default_').
+                         ":$port>",
     };
 }
 
diff -Nur httpd-test~/Apache-Test/lib/Apache/TestConfigPerl.pm httpd-test/Apache-Test/lib/Apache/TestConfigPerl.pm
--- httpd-test~/Apache-Test/lib/Apache/TestConfigPerl.pm
+++ httpd-test/Apache-Test/lib/Apache/TestConfigPerl.pm
@@ -214,17 +214,31 @@
 sub vhost_container {
     my($self, $module) = @_;
     my $port = $self->{vhosts}->{$module}->{port};
-    VirtualHost => "_default_:$port";
+    my $namebased = $self->{vhosts}->{$module}->{namebased};
+
+    VirtualHost => ($namebased ? '*' : '_default_') . ":$port";
 }
 
 sub new_vhost {
-    my($self, $module) = @_;
+    my($self, $module, $namebased) = @_;
+    my ($port, $servername, $vhost);
 
-    my $port       = $self->server->select_port;
-    my $servername = $self->{vars}->{servername};
-    my $vhost      = $self->{vhosts}->{$module} = {};
+    unless ($namebased and exists $self->{vhosts}->{$module}) {
+        $port       = $self->server->select_port;
+        $vhost      = $self->{vhosts}->{$module} = {};
+
+        $vhost->{port}       = $port;
+        $vhost->{namebased}  = $namebased ? 1 : 0;
+    }
+    else {
+        $vhost      = $self->{vhosts}->{$module};
+        $port       = $vhost->{port};
+        # remember the already configured Listen/NameVirtualHost
+        ++$vhost->{namebased};
+    }
+
+    $servername = $self->{vars}->{servername};
 
-    $vhost->{port}       = $port;
     $vhost->{servername} = $servername;
     $vhost->{name}       = join ':', $servername, $port;
     $vhost->{hostport}   = $self->hostport($vhost, $module);
@@ -354,7 +368,7 @@
     if ($cfg) {
         my $port = $cfg->{port};
         $cfg->{out_postamble}->();
-        $self->postamble("$indent<VirtualHost _default_:$port>");
+        $self->postamble($cfg->{line});
         $cfg->{in_postamble}->();
     } else {
         $self->postamble("$indent$line");

Reply via email to