2009-07-22 1 views
6

J'essaye d'écrire un ensemble de règles mod_rewrite qui permettent à mes utilisateurs d'utiliser un seul dossier pour faire du développement sur différents projets, et ne pas avoir à jouer avec l'ajout de vhosts pour chaque projet.Apache mod_rewrite un sous-domaine dans un sous-dossier (via redirection interne)

Mon idée pour accomplir ceci, est de mettre en place un "Global VHost" pour chaque utilisateur qui a besoin de cette capacité (seulement 3-4), le vhost serait quelque chose comme: .my-domain.com. De là, je veux promouvoir mes utilisateurs à écrire du code comme si c'était sur un domaine, et non dans un sous-dossier. Par exemple, si Bob travaillait sur un projet nommé 'gnome', je voudrais charger l'URL de bob (et toute autre personne sur notre réseau interne) pour arriver à ce projet: http://gnome.bob.my-domain.com. Mais, ce que j'aimerais qu'Apache fasse, c'est reconnaître que "gnome" est un "projet" et donc mapper la requête, en interne, sur bob.my-domain.com/gnome/.

J'ai ce que je pensais fonctionner, et c'est assez simple, mais ça ne marche pas! La requête passe simplement dans une boucle infinie et conserve le préfixe du sous-domaine sur l'URI réécrit de la requête.

Le code mod rewrite i have est:

RewriteEngine On 

RewriteCond %{HTTP_HOST} ^([^.]+)\.bob\.my-domain\.com 
RewriteCond %{REQUEST_URI} !^/%1.* 
RewriteRule ^(.*)$  /%1/$1 [L] 

J'ai googlé autour d'un peu à ce sujet, mais je n'ai pas encore trouver de véritables solutions qui fonctionnent. Est-ce que quelqu'un a essayé cela - ou peut-être, quelqu'un a-t-il une meilleure idée? Un qui n'implique pas de faire un hôte virtuel pour chaque projet (j'ai des concepteurs .. Je pense que tout le monde serait d'accord qu'un concepteur ne devrait pas faire des hôtes virtuels ..)

Merci!

Voici un extrait de la rewrite_log:

[rid#838dc88/initial] (3) [perdir /home/bob/http/] strip per-dir prefix: /home/bob/http/index.html -> index.html 
[rid#838dc88/initial] (3) [perdir /home/bob/http/] applying pattern '^(.*)$' to uri 'index.html' 
[rid#838dc88/initial] (4) [perdir /home/bob/http/] RewriteCond: input='gnome.bob.my-domain.com' pattern='^([^.]+)\.bob\.my-domain\.com' => matched 
[rid#838dc88/initial] (4) [perdir /home/bob/http/] RewriteCond: input='/index.html' pattern='!^/%1.*' => matched 
[rid#838dc88/initial] (2) [perdir /home/bob/http/] rewrite 'index.html' -> '/gnome/index.html' 
[rid#838dc88/initial] (1) [perdir /home/bob/http/] internal redirect with /gnome/index.html [INTERNAL REDIRECT] 
[rid#8392f30/initial/redir#1] (3) [perdir /home/bob/http/] strip per-dir prefix: /home/bob/http/gnome/index.html -> gnome/index.html 
[rid#8392f30/initial/redir#1] (3) [perdir /home/bob/http/] applying pattern '^(.*)$' to uri 'gnome/index.html' 
[rid#8392f30/initial/redir#1] (4) [perdir /home/bob/http/] RewriteCond: input='gnome.bob.my-domain.com' pattern='^([^\.]+)\.bob\.my-domain\.com' => matched 
[rid#8392f30/initial/redir#1] (4) [perdir /home/bob/http/] RewriteCond: input='/gnome/index.html' pattern='!^/%1.*' => matched 
[rid#8392f30/initial/redir#1] (2) [perdir /home/bob/http/] rewrite 'gnome/index.html' -> '/gnome/gnome/index.html' 
[rid#8392f30/initial/redir#1] (1) [perdir /home/bob/http/] internal redirect with /gnome/gnome/index.html [INTERNAL REDIRECT] 
[rid#8397970/initial/redir#2] (3) [perdir /home/bob/http/] add path info postfix: /home/bob/http/gnome/gnome -> /home/bob/http/gnome/gnome/index.html 

Ceci est juste un extrait, il y a quelques 10s ou quelque 100 lignes de apache ré-écriture essentiellement /gnome/index.html à/gnome/gnome /gnome/gnome/gnome/index.html, etc avant sa frappe apache limite de réécriture, donne, et lancers francs erreur 500

+0

Ajout d'un peu plus d'informations à partir des journaux de réécriture, j'espère que quelqu'un a déjà essayé cela, ou a des commentaires sur la façon dont je peux y arriver! Merci les gars (et les filles) –

Répondre

5

Après quelques années d'ignorer ce problème et revenir à à divers points, j'ai finalement trouvé une solution réalisable.

RewriteEngine on 
RewriteCond %{HTTP_HOST} ^([^.]+)\.bob\.my-domain\.com 
RewriteCond %1::%{REQUEST_URI} !^(.*?)::/\1/ 
RewriteRule ^(.*)$ /%1/$1 [L] 

Ce que je trouve est que références arrière pour les directions précédentes RewriteCond ne sont pas disponibles dans le paramètre ConditionPattern de RewriteConditions futures. Si vous souhaitez utiliser une référence arrière d'une directive précédente RewriteCond, vous ne pouvez l'utiliser que dans le paramètre TestString.

Les directives ci-dessus préfixent le sous-domaine correspondant dans la première directive RewriteCond à RequestURI, délimité par ::. Ce que nous faisons ensuite dans la chaîne de test RewriteCond (regex) est de recapturer le nom du sous-domaine, puis de vérifier que notre RequestURI réel ne commence pas avec ce sous-domaine en tant que dossier utilisant une référence arrière dans la même regex . Cela semble beaucoup plus déroutant qu'il ne l'est vraiment, et je ne peux pas prendre le crédit pour la découverte de la réponse. J'ai trouvé la réponse en réponse à une autre question ici, %N backreference inside RewriteCond. Merci à Jon Lin pour répondre à cette question, et à son insu, ma question aussi!

+0

Juste une note que j'ai dû enlever le trailing/sur le deuxième RewriteCond pour le faire fonctionner correctement pour moi. J'ai pu charger mon URL avec (installation de gallery3), mais les ressources CSS ne se chargeaient pas correctement. En décollant la barre oblique, il a été réparé. Il semblait que ça se terminait par // dans l'URL avec ça là-dedans. – stuckj

0

Quelques questions:

vous avez dit "carte interne" - N'êtes-vous pas Voulez-vous utiliser une redirection?

Utilisez-vous le même VirtualHost pour gnome.bob.mysite.com et bob.mysite.com

Avez-vous pensé à créer un ServerAlias ​​pour *.bob.mysite.com?


Voici une version brute que vous pourriez modifier pour fonctionner. Il va capturer le sous-domaine et l'URL demandée, et faire une redirection vers le domaine principal avec le sous-domaine comme première partie du chemin, suivi par le chemin demandé, suivi de la chaîne de requête.

ServerName www.mysite.com 
ServerAlias *.mysite.com 

RewriteCond %{HTTP_HOST} ^([a-zA-Z0-9-]+)\\.mysite.com$ 
RewriteRule ^/(.*)  http://www.mysite.com/%1/$1  [R=301,L]',  
+0

Je veux vraiment une redirection interne. le but de ceci est d'être capable d'utiliser des chemins absolus sur les liens, css, img srcs, etc. Il y a/aura un hôte virtuel pour .my-site.com avec un alias pour *. .mon-site.com, de sorte que tout domaine demandé de .my-site.com ou ci-dessous sera ramassé par ce vhost –

0

Avez-vous essayé d'utiliser une autre règle de réécriture pour traiter celle qui la précède?

RewriteEngine On 

RewriteCond %{HTTP_HOST}      ^([^.]+)\.bob\.my-domain\.com 
RewriteCond %{REQUEST_URI}      !^/%1.* 
RewriteRule ^(.*)$        /%1/$1 [C]  
RewriteRule ^/(.*)\.bob\.my-domain\.com/(.*) /$1/$2 [L] 

Mais je pense que votre plus gros problème est le fait que votre serveur ne comprend pas qu'il est servi sous un nom différent.

Il pense qu'il s'exécute dans le répertoire/gnome/alors que le navigateur fonctionne dans le répertoire /. Donc, toute URL relative que vous avez va causer des problèmes.

Ce dont vous avez besoin est un filtre qui va exécuter toutes les URL de votre page via un processeur et les changer de/gnome/à /.

+0

l'idée est de décourager les URLs relatifs, mais sous cette structure, ils devraient également travailler. –

+0

aussi, je suis assez sûr que l'hôte HTTP n'est pas utilisé dans le RewriteRule, juste l'URI –