web-dev-qa-db-fra.com

Redirige les sous-domaines vers leurs dossiers sans double barre oblique et de telle sorte que les paramètres soient envoyés via la connexion

J'ai une configuration DNS générique sur mon serveur, quelque chose comme .example.com. Il y a quelques sites dans mon dossier racine. Il me faut donc quelque chose comme ceci: test.example.com devrait utiliser le répertoire test (j'ai près de 50 sites, pas un seul).

Je veux le faire avec le fichier .htaccess. Actuellement, j'ai les règles suivantes dans mon fichier .htaccess:

    RewriteEngine On

    RewriteCond %{HTTP_Host} !^www\. [NC]
    RewriteCond %{HTTP_Host} ^([^.]+)\.example\.com$ [NC]
    RewriteCond %{DOCUMENT_ROOT}/%1 !-d
    RewriteRule ^ - [L,R=404]

    RewriteCond %{HTTP_Host} !^www\. [NC]
    RewriteCond %{HTTP_Host} ^([^.]+)\.example\.com$ [NC]
    RewriteCond %{DOCUMENT_ROOT}/%1 -d
    RewriteCond %{DOCUMENT_ROOT}/%1%{REQUEST_FILENAME} -f [OR]
    RewriteCond %{DOCUMENT_ROOT}/%1%{REQUEST_FILENAME} -d
    RewriteRule ^(.*)$ /%1/$1 [R=301,L]

Il fait quelque chose, c’est-à-dire que lorsque je tape test.example.com, il apparaît dans le répertoire de test et récupère les données, mais il écrit l’URL sous la forme test.example.com/test// (2 barres obliques à la fin).

De plus, lorsque je clique sur un lien (par exemple, /login), il me faut test.example.com/login mais il ne fonctionne pas pendant que test.example.com/test//login charge la page, mais il n'envoie pas les données de formulaire soumises. pour la connexion (perdu à cause de la redirection 301).

2
Prince

Dans un contexte répertoire/.htaccess, le code que vous avez posté ci-dessus ne fera réellement rien!? Donc, vous voyez soit le résultat d’une réponse en cache, ce qui est tout à fait possible puisque vous utilisez des redirections 301 (permanentes), qui sont naturellement mises en cache par le navigateur. Ou, vous avez un autre code qui effectue cette redirection?

De plus, je ne vois pas d'où viendrait la double barre oblique, même si "quelque chose" s'est réellement produit - ce qui me laisse supposer que vous voyez une réponse en cache, ou quelque chose d'autre est en train de disparaître?

(Si, toutefois, ces directives étaient directement dans la configuration du serveur, contrairement à .htaccess (comme indiqué), ces directives feraient probablement quelque chose et vous obtiendriez en fait une double barre oblique!)

Plus précisément...

RewriteCond %{DOCUMENT_ROOT}/%1%{REQUEST_FILENAME} -f [OR]
RewriteCond %{DOCUMENT_ROOT}/%1%{REQUEST_FILENAME} -d

Dans un contexte/.htaccess contexte, ces conditions seront jamais réussies. La directive suivante RewriteRule qui effectue la redirection ne se produira jamais. Vous vouliez probablement utiliser la variable de serveur REQUEST_URI au lieu de REQUEST_FILENAME. (Cependant, dans un contexte de serveur, REQUEST_FILENAME est identique à REQUEST_URI au moment du traitement initial de la demande.)

REQUEST_FILENAME contient déjà le chemin d'accès absolu du système de fichiers vers lequel l'URI est mappé; il est donc évidemment préfixé par le chemin du système de fichiers du DOCUMENT_ROOT et le sous-répertoire ne fonctionnera pas.

Cependant, je me demande si vous voulez vraiment faire cela de toute façon. (c.-à-d. vérifier l'existence du fichier/répertoire demandé dans le sous-répertoire respectif avant de le rediriger.) Cela semblerait inutile à mon avis et limite le type de "sites" que vous pouvez héberger. Je pense qu'il serait préférable de réécrire sans condition toutes les demandes du sous-domaine dans le sous-répertoire respectif (s'il existe) et de permettre à chaque "site" de gérer le 404 - ce qui vous permet d'avoir un 404 personnalisé pour chaque site si vous le souhaitez.

En outre, je pense que cela devrait être un réécriture interne (au sous-répertoire), plutôt qu'une redirection externe. c'est à dire. Une demande de test.example.com/login doit rester à test.example.com/login (autant que voit l'utilisateur) et non redirigé en externe à test.example.com/test/login? Sinon, à quoi sert le sous-domaine? Cela résoudrait également le problème de non transmission des données de formulaire via la redirection (car un 301 transforme la demande POST en une requête GET).

Donc, essayez plutôt quelque chose comme ce qui suit:

RewriteEngine On

# Don't process requests for the www subdomain or apex domain
RewriteCond %{HTTP_Host} ^(www\.)?example\.com [NC]
RewriteRule ^ - [L]

# Rewrite all direct requests for subdomains that exist as subdirectories
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{HTTP_Host} ^([^.]+)\.example\.com [NC]
RewriteCond %{DOCUMENT_ROOT}/%1 -d
RewriteRule (.*) /%1/$1 [L]

Vos règles précédentes incluaient une condition (répétée pour chaque règle) excluant les demandes du sous-domaine www. J'ai séparé cela dans sa propre règle.

Auparavant, vous aviez une vérification préalable qui vérifiait que le sous-domaine existait en tant que sous-répertoire. Cela n'est pas nécessaire si vous vérifiez l'existence de ce sous-répertoire dans le deuxième bloc de règles.

La directive RewriteCond qui vérifie la variable d'environnement REDIRECT_STATUS garantit que toutes les demandes directes (du client) sont redirigées et non les réécritures internes, ce qui évite les boucles de réécriture. Notez que cela réécrit toutes requêtes (sauf s'il existe un autre fichier .htaccess dans le sous-répertoire qui utilise mod_rewrite), que le sous-répertoire soit déjà préfixé sur l'URL - cela permet l'imbrication de sous-répertoires. avec le même nom, à n'importe quelle profondeur, par exemple. /test/test/test/<whatever>. Toutefois, il serait préférable que le sous-répertoire du site soit unique sur ce site.

L'absence du drapeau R sur le RewriteRule en fait un réécriture interne au lieu d'un redirection externe (de sorte que l'URL n'est pas mise à jour dans la barre d'adresse).

Et assurez-vous que le cache du navigateur est vide!

1
MrWhite