適切なドキュメントルートが存在する場合にのみVirtualDocumentRootを使用する*


8

構成を再ロードせずにApache仮想ホストを動的に作成できる環境をセットアップしたいと思います。

これはmod_vhost_aliasで実行できます。デフォルトの仮想ホストを次のように設定します

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

これは問題なく機能しますが、現在設定されていないホスト名に対してリクエストが行われた場合、404 Not Foundエラーが発生します。

私が本当にやりたいことは、ドキュメントルートが存在する場合にのみ、このVirtualHostを有効にすることです。それ以外の場合は、別のvhostに一致させようとします(つまり、VirtualDocumentRootの存在を、 ServerAlias)

これを2つ目のvhostにしてみましたが、最初のvhostがすべての要求を処理するだけでしたが、これは機能しませんでした。VirtualDocumentRootが構成されているドメインに対する要求は、デフォルトのvhostにフォールスルーしました。

それで、どうすれば動的に構成されたvhostを作成できますが、まだ構成されていないものについては別のvhostにフォールバックできますか?

回答:


7

私に役立つ回避策を見つけました。

ErrorDocumentを使用して、PHPスクリプトで404エラーを取得できます。最初は問題があるように見えました。DocumentRootがない場合、スクリプトはどこにありますか?

別のドメインから提供されたエラーメッセージのURLを使用できます。しかし、テストでは、最初に要求されたドメインが何であるかを知る方法が見つかりませんでした。

答えはAlias a directoryであり、そこからエラーを処理するため、私のvhostは次のようになります

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

これで、未構成のドメインが要求されると、代わりに/var/www/default/errors/notfound.phpにあるスクリプトが呼び出されます。このスクリプトは、$ _ SERVER ['HTTP_HOST']をチェックして、要求されたドメインを確認できます。実際に構成されている場合は、通常の404があります。構成されていない場合は、代替のエラーメッセージを表示できます。私の場合、vhostの設定に役立つUIを表示します。


それはデフォルトへのすべての要求のステータスとして404をスローしませんか?
カイル

1
エラーハンドラーは、VirtualDocumentRootが存在しない場合にのみ呼び出されます(または、実際には404でしたが、notfound.phpで簡単に違いがわかります)。
ポールディクソン

3

グーグルで質問を見つけました。私はまったく同じ問題を抱えており、ポールの回答に記載されているように修正を適用しました。ただし、複雑なWebアプリでは、すべてのリクエストを1つのルーティングでルーティングすることに満足していませんでしたnotfound.php

最終的に、VirtualHost構成を編集するだけで、外部スクリプトなしで問題を解決することができました。

最初、私のVirtualHostは次のように構成されていました。

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

のようなURLがclient1.domainname.comありclient2.domainname.comwhatever.domainname.com

これに解決/mnt/ramdisk/www/cms-client1-development//mnt/ramdisk/www/cms-client2-development/および/mnt/ramdisk/www/cms-whatever-development/

ただし、のようなURLでは、nonexistent.domainname.comディレクトリ/mnt/ramdisk/www/cms-nonexistent-development/が存在しないため、404が返されます。これらのサブドメインでディレクトリを使用したかった/mnt/ramdisk/www/cms-default-development/

私はModRewriteand を使用してこれを修正しました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)を取得し、パス(%1)に挿入して、ディレクトリが存在しない場合のみ、デフォルトのURLにリクエストをプロキシします。

プロキシを使用することにより、プロセスは透過的であり、ユーザーはhttp://nonexistent.domainname.comにアクセスしているように見えますが、実際にはhttp://default.domainname.com/のコンテンツを表示しています


3

私はまた、apache2ダイナミックvhostフォールバックググるこの質問に出くわし、Lucの回答は私の問題を解決するのに大いに役立ちましたが、主にいくつかの余分な作業が含まれていたため今後のGoogle社員に役立つかもしれません...

私の目標

  • VPSを指すすべてのドメインとサブドメインの動的vhosting
  • foo.com 同じコンテンツを提供する必要があります www.foo.com
  • 不明なドメインを何らかのデフォルトにフォールバック
  • foo.comtoの不明なサブドメインのフォールバックはwww.foo.comwwwが利用できない場合を除き、代わりにデフォルトにフォールバックします

DNS

私のVPSを指すドメイン(およびそのすべてのサブドメイン)がいくつかあります。たとえば、

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

ファイルシステム

次のディレクトリがあります。ドメインには、使用可能なサブドメインの名前のディレクトリが含まれます。wwwディレクトリが必要ですが、configはそれが存在しない状況に対応できるはずです。Localhostはデフォルトのフォールバックとして使用されます。

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

テスト

私の目標をテスト可能なケースに変換する:

  • foo.comから提供されなければならないfoo.com/www
  • www.foo.comから提供されなければならないfoo.com/www
  • bar.foo.comから提供されなければならないfoo.com/bar
  • foo.foo.comはから提供されなければならないfoo.com/www(foo.com/fooが存在しません)
  • bar.comlocalhostから提供する必要があります(bar.com/wwwは存在しません)
  • www.bar.comlocalhostから提供する必要があります(bar.com/wwwは存在しません)
  • foo.bar.comから提供されなければならないbar.com/foo
  • bar.bar.comlocalhostから提供する必要があります(bar.com/barは存在しません)
  • foob​​ar.comlocalhostから提供する必要があります(foobar.comは存在しません)
  • www.foobar.comlocalhostから提供する必要があります(foobar.comは存在しません)
  • foo.foobar.comlocalhostから提供する必要があります(foobar.comは存在しません)

ソリューション

これは使用します:mod_rewritemod_proxy_httpそしてもちろんmod_vhost_alias

ServerName my.domain
ServerAdmin admin@my.domain

<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>

これはどのように作動しますか?3つの仮想ホストが定義されています。

ローカルホスト

localhostがデフォルトとして機能します。解決できないすべての要求は、localhostによって処理されます。localhostから任意のドメインへのシンボリックリンクを設定することは、そのサイトをデフォルトとして設定することに似ています。

sub.domain

sub.domain vhostは、すべてのリクエストをの形式で受け取ります*.*.*。デフォルトでは、すべてのリクエストはの/domain.com/sub定義に従って提供されVirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3ます。

後退する:

1つ目RewriteRuleは不明なドメインを処理します。domain.comlocalhostウェブサイトをプロキシすることにより、ディレクトリが存在しません。

2つ目RewriteRuleも、domain.com/subdomain.com/wwwディレクトリの両方が存在しない場合、localhostにプロキシします。

存在しない場合の3番目のRewriteRuleプロキシ。2番目の書き換えブロックのために存在することはわかっています。domain.comdomain.com/subdomain.com/www

bare.domain

bare.domain vhostが*.*リクエストを受け取って処理します/domain.com/www

ここではRewriteRulelocalhostにするとき意志プロキシdomain.comまたはdomain.com/www存在しません。

^ $%。* !!!

私はいくつかのトラブルすべてのそれらのまわりで私の頭をラップだった$し、%中にサインをRewriteCondし、RewriteRule私はここでそれらについて説明しますので。

    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単にワイルドカードです。
  • %nは、ドキュメント名の補間VirtualDocumentRootからのものです。
  • %n中には、第二RewriteCondの選択を参照して(.*)最初からRewriteCond例えば、。要求されたドメインの部分。
  • %n中には、RewriteRuleあまりにも行います。
  • $1は、の最初のRewriteRule選択(.*)を指しRewriteRuleます。ドメインから?リクエストURL までのすべてをキャプチャします。クエリ文字列はによって自動的にURLに追加されmod_proxyます。

1

そこに捨てるだけで、RemyNLと同じ結果(localhostリダイレクトを除く)が得られますが、直接接続するときにIPアドレスも含まれます。

<VirtualHost _default_:80>
    RewriteEngine On
    RewriteCond %{HTTPS} Off [OR] 
    RewriteCond %{HTTP:X-Forwarded-Proto} !https
    RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R=301,L]
</VirtualHost>

<VirtualHost _default_:443>
    ServerName a.b.c.d
    ServerAlias *.*.*.*
    VirtualDocumentRoot /var/www/%0
</VirtualHost>

<VirtualHost _default_:443>
    ServerName a.b.c
    ServerAlias *.*.*
    VirtualDocumentRoot /var/www/%-2.0.%-1.0/%-3
</VirtualHost>

<VirtualHost _default_:443>
    ServerName a.b
    ServerAlias *.*
    VirtualDocumentRoot /var/www/%-2.0.%-1.0/www
</VirtualHost>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.