仅使用VirtualDocumentRoot *如果存在合适的文档根目录

我想build立一个环境,可以在不重新加载configuration的情况下dynamic创buildApache虚拟主机

我可以用mod_vhost_alias来做到这一点,我设置了我的默认虚拟主机

<VirtualHost *> UseCanonicalName Off VirtualDocumentRoot /var/www/sandboxes/domains/%0 ServerName catchall.host </VirtualHost> 

这工作得很好,但如果请求是一个主机名目前没有build立,我得到一个404未find错误。

真正想做的只是在文档根目录存在的情况下才使用这个VirtualHost脚本,否则就尝试与另一个vhost相匹配(换句话说,使VirtualDocumentRoot的工作方式与使用ServerAlias)

我试图让这第二个虚拟主机,第一个虚拟主机只处理所有的请求,但是这不起作用 – 虚拟文档根目录configuration域的请求下降到默认虚拟主机。

那么,我怎样才能dynamic地configuration虚拟主机,但是如果还没有configuration任何虚拟主机,还可以使用另一个虚拟主机呢?

我发现了一个解决方法,适合我。

我可以使用ErrorDocument来获取PHP脚本中的404错误。 起初,这似乎有问题。 如果没有DocumentRoot,脚本将在哪里生存?

我可以使用来自不同域的错误消息的URL。 然而,在testing中,我发现没有办法知道最初请求的域是什么。

答案是别名一个目录,并提供错误,所以我的虚拟主机看起来像这样

 <VirtualHost *> UseCanonicalName Off VirtualDocumentRoot /var/www/sandboxes/domains/%0 ServerName catchall.host Alias /errors /var/www/default/errors/ ErrorDocument 404 /errors/notfound.php </VirtualHost> 

现在,当请求未configuration的域时,将调用/var/www/default/errors/notfound.php脚本。 该脚本可以检查$ _SERVER ['HTTP_HOST']来查看请求的域名。 如果它是真正configuration的,那么我们有一个常规的404。如果没有configuration,我们可以显示一些备用的错误信息。 就我而言,这就是我展示UI来帮助设置虚拟主机的地方。

当谷歌search时,我发现你的问题。 我有完全相同的问题,并应用保罗的答案中所述的修复。 然而,对于我的复杂的networking应用程序,我不满意路由所有请求通过一个notfound.php

最后,我设法修复了无外部脚本的问题,只能编辑我的VirtualHostconfiguration。

起初,我的VirtualHost是这样configuration的:

 <VirtualHost *:80> Usecanonicalname Off Virtualdocumentroot /mnt/ramdisk/www/cms-%-3.0-development/ </VirtualHost> 

我有像client1.domainname.comclient2.domainname.comwhatever.domainname.comurl

解决了/mnt/ramdisk/www/cms-client1-development//mnt/ramdisk/www/cms-client2-development//mnt/ramdisk/www/cms-whatever-development/

但是,像nonexistent.domainname.com这样的URL会给我一个404,因为目录/mnt/ramdisk/www/cms-nonexistent-development/不存在。 我希望这些子域使用目录/mnt/ramdisk/www/cms-default-development/

我使用ModRewriteModProxy修复了这个ModProxy

 <VirtualHost *:80> Usecanonicalname Off Virtualdocumentroot /mnt/ramdisk/www/cms-%-3.0-development/ RewriteEngine on RewriteCond %{HTTP_HOST} ^(.*)\.domainname\.com$ [NC] RewriteCond /mnt/ramdisk/www/cms-%1-development/ !-d RewriteRule (.*) http://default.domainname.com/$1 [P,L] </VirtualHost> 

它的作用是:获取子域( .domainname.com之前的部分),将其插入到path(%1)中,并将代理请求插入到默认的URL中, 除非该目录不存在。

通过使用代理,该过程是透明的,用户认为他正在访问http://nonexistent.domainname.com ,而他实际上从http://default.domainname.com/查看内容&#x3002;

我也遇到了这个问题,searchapache2dynamic虚拟主机后备和吕克的答案帮助我很多解决我的问题,但我仍然要显示我做了什么来实现我的目标,主要是因为它涉及一些额外的工作,因为我认为它可能有助于未来的任何谷歌…

我的目标

  • dynamic虚拟所有域名和子域名指向我的VPS
  • foo.com服务内容与www.foo.com相同
  • 为未知的域回落到某种默认状态
  • foo.com未知子域名回foo.com www.foo.com除非www不可用,而是回退到默认值

DNS

我有几个域(及其所有子域)指向我的VPS,例如:

  • foo.com
  • bar.com
  • foob​​ar.com

文件系统

我有以下目录,域包含可用的子域的名称的目录,www目录是必需的,但configuration应该能够处理它不存在的情况。 本地主机被用作默认回退:

 /var /www /localhost /foo.com /www /bar /bar.com /foo 

testing

将我的目标转化为可testing的情况:

  • foo.com应该来自foo.com/www
  • http://www.foo.com应该来自foo.com/www
  • bar.foo.com应该从foo.com/bar提供
  • foo.foo.com应该从foo.com/www(foo.com/foo不存在)
  • bar.com应该从localhost (bar.com/www不存在)
  • http://www.bar.com应该从localhost (bar.com/www不存在)
  • 应该从bar.com/foo提供 foo.bar.com
  • bar.bar.com应该从localhost (bar.com/bar不存在)
  • foob​​ar.com应该从localhost (foobar.com不存在)
  • http://www.foobar.com应该从localhost (foobar.com不存在)
  • foo.foobar.com应该从localhost提供 (foobar.com不存在)

解决scheme

这使用: mod_rewritemod_proxy_http和ofcourse mod_vhost_alias

 ServerName my.domain ServerAdmin [email protected] <VirtualHost *:80> ServerName localhost VirtualDocumentRoot /var/www/localhost </VirtualHost> <VirtualHost *:80> ServerName sub.domain ServerAlias *.*.* VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3 RewriteEngine on RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC] RewriteCond /var/www/%2.%3 !-d RewriteRule (.*) http://localhost/$1 [P] RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC] RewriteCond /var/www/%2.%3/%1 !-d RewriteCond /var/www/%2.%3/www !-d RewriteRule (.*) http://localhost/$1 [P] RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC] RewriteCond /var/www/%2.%3/%1 !-d RewriteRule (.*) http://%2.%3/$1 [P] </VirtualHost> <VirtualHost *:80> ServerName bare.domain ServerAlias *.* VirtualDocumentRoot /var/www/%-2.0.%-1.0/www RewriteEngine on RewriteCond %{HTTP_HOST} ^(.*)\.(.*)$ [NC] RewriteCond /var/www/%1.%2 !-d [OR] RewriteCond /var/www/%1.%2/www !-d RewriteRule (.*) http://localhost/$1 [P] </VirtualHost> 

这个怎么用? 有三个虚拟主机定义:

本地主机

本地主机是默认的。 所有不可parsing的请求都由localhost提供。 设置从本地主机到任何域名的符号链接就像是将该网站设置为默认网站。

sub.domain

sub.domain虚拟主机以*.*.*的forms提取所有请求。 默认情况下,所有请求均由VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3定义的/domain.com/sub提供。

倒退:

第一个RewriteRule处理未知域,例如。 domain.com目录不存在,通过代理localhost网站。

domain.com/subdomain.com/www目录都不存在时,第二个RewriteRule也代理本地主机。

domain.com/sub不存在时,第三个RewriteRule代理到domain.com 。 由于第二个重写块,我们知道domain.com/www确实存在。

bare.domain

bare.domain虚拟主机正在接受*.*请求并将其提供给/domain.com/www

这里,当domain.comdomain.com/www不存在时, RewriteRule将代理到本地主机。

^ $%*!

我在RewriteCondRewriteRule所有$%符号上都遇到了麻烦,所以我将在这里解释一下:

  ServerAlias *.*.* VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3 RewriteCond %{HTTP_HOST} ^(.*)\.(.*)\.(.*)$ [NC] RewriteCond /var/www/%2.%3/%1 !-d RewriteRule (.*) http://%2.%3/$1 [P] 
  • ServerAlias中的*只是通配符。
  • VirtualDocumentRoot中的%n来自文档名称插值 。
  • 第二个RewriteCond%n是指第一个RewriteCond中的选项(.*) ,例如。 请求的域的部分。
  • RewriteRule%n也是。
  • RewriteRule$1是指RewriteRule开头的选项(.*) 。 哪些捕获从领域的一切,直到? 在请求的url。 任何查询string都会通过mod_proxy自动添加到url中。