IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Apache Discussion :

[URL REWRITING] Incohérence avec le fichier index ? [Fait]


Sujet :

Apache

  1. #1
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    397
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 397
    Points : 133
    Points
    133
    Par défaut [URL REWRITING] Incohérence avec le fichier index ?
    Bonjour,

    Pourquoi cette règle fonctionne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    RewriteRule (.*)index\.php$ /$1 [R=301,L]
    www.example.com/index.php renvoie vers www.example.com
    C'est à dire que si www.example.com est appelé Apache passe outre cette règle.


    En revanche, si l'on écrit la règle suivante pour capturer tout ce qui pourrait exister comme appel de page ou de dossier.
    Apache plante avec Internal Server Error.
    Parce qu'il doit tourner en boucle étant donné que la redirection vers / appelle pour lui index.php


    Hors si index.php semble être appelé dans ce cas, pourquoi le 1er exemple ne tourne pas en boucle non plus ?

    J'espère avoir été suffisamment clair.

    Ou est la logique ?

    Merci

  2. #2
    Rédacteur
    Avatar de _Mac_
    Profil pro
    Inscrit en
    Août 2005
    Messages
    9 601
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 9 601
    Points : 12 977
    Points
    12 977
    Par défaut
    Parce que dans le premier cas (RewriteRule (.*)index\.php$ ...) la règle est explicite pour index.php (index.php apparaît dans l'URL), alors qu'un simple "/repertoire/" appelle bien index.php (grâce à la directive DirectoryIndex) mais ça ne se voit pas dans l'URL.

    Pourquoi ça part en boucle ? Parce que mod_rewrite rejoue N fois les règles de réécriture jusqu'à converger vers une URL qui n'est pas réécrite. Contrairement à ce qu'on croit, [L] va arrêter le cycle de réécriture en cours mais pas le cycle complet. Si on applique ce fonctionnement pour chacune des deux règles que tu donnes :
    • Dans ton premier cas (index.php explicite), tu retires index.php de l'URL. Le résultat de cette réécriture est réinjecté dans mod_rewrite, mais comme aucun RewriteRule n'est activé (pas d'index.php dans l'URL), mod_rewrite est content, il a une URL qui n'a pas bougé donc il s'arrête là.
    • Ta seconde règle matche pour n'importe quoi, y compris le résultat de la première RewriteRule mais aussi et surtout pour son propre résultat. La boucle ne vient pas d'index.php mais du fait que le filtre (.+) est trop large et matche pour son propre résultat.

    Il faut donc que tu rajoutes un RewriteCond ou que tu précises davantage ton second RewriteRule pour faire en sorte que la seconde règle ne s'applique plus passé un moment et donc sortir de la boucle.

    Du détail, du détail, du détail !!!
    Revenons à la source : lisons la documentation et les fichiers de trace, la réponse à notre problème s'y trouve sans doute

  3. #3
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    397
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 397
    Points : 133
    Points
    133
    Par défaut
    Salut et merci pour ta réponse, oui la solution je l'ai avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    RewriteCond %{REQUEST_FILENAME} !index.php
    Mais donc qu'est-ce qui est capturé dans le (.+), c'est bien index.php puisque le RewriteCond permet de solutionner le problème ?

    C'est là que je ne comprends pas.

  4. #4
    Rédacteur
    Avatar de _Mac_
    Profil pro
    Inscrit en
    Août 2005
    Messages
    9 601
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 9 601
    Points : 12 977
    Points
    12 977
    Par défaut
    C'est possible mais si tu mets la règle avec index.php avant celle de .+, c'est peu probable. Pour le savoir, tu peux tenter des trucs du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    RewriteRule (.+) /?rewrite=$1 [R=302,L]
    Ca va faire une redirection navigateur, donc arrêter totalement le cycle de rewrite, et tu verras le résultat dans la barre d'URL.

    Du détail, du détail, du détail !!!
    Revenons à la source : lisons la documentation et les fichiers de trace, la réponse à notre problème s'y trouve sans doute

  5. #5
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    397
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 397
    Points : 133
    Points
    133
    Par défaut
    Voici comment ça fonctionne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    RewriteEngine on
     
    RewriteRule (.*)index\.php$ /membre/$1 [R=301,L]
     
    RewriteCond %{REQUEST_FILENAME} !index.php
    RewriteRule .+ /membre/ [L]

    Mais ma question reste la même, si index.php semble être appelé dans la seconde règle, pourquoi la 1ere règle ne tourne pas en boucle non plus ?

    Merci

  6. #6
    Rédacteur
    Avatar de _Mac_
    Profil pro
    Inscrit en
    Août 2005
    Messages
    9 601
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 9 601
    Points : 12 977
    Points
    12 977
    Par défaut
    Pourquoi veux-tu que la première règle tourne en boucle ? La première règle travaille sur une URL explicite : il faut que l'URL tapée/cliquée par le visiteur ou après réécriture contienne index.php pour que la première règle soit activée. Si l'URL est juste "/toto/" qui appelle derrière index.php parce que tu as DirectoryIndex index.php, la première règle n'est pas activée car la chaîne "/toto/" ne contient pas index.php.

    En revanche, la seconde règle travaille avec le RewriteCond sur le fichier réel correspondant à l'URL : on travaille sur un vrai fichier, en prenant en compte éventuellement DirectoryIndex, donc dans ce cas, si l'URL est "/toto/", on va tomber sur index.php. Mais comme tu as !index.php, ta règle n'est activée que si le vrai fichier appelé n'est pas index.php, comme par exemple "/toto/haha.jpg".

    Est-ce que ça répond à ta question ? Parce qu'en fait, j'avoue ne pas trop comprendre quel est ton problème ou ta question...

    Du détail, du détail, du détail !!!
    Revenons à la source : lisons la documentation et les fichiers de trace, la réponse à notre problème s'y trouve sans doute

  7. #7
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    397
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 397
    Points : 133
    Points
    133
    Par défaut
    Ce sont toutes les deux des RewriteRule.

    Ce que je ne comprends pas, c'est pourquoi
    la 1ère règle travaille sur l'URL explicite
    alors que la 2ème règle travaille sur le fichier réel correspondant à l'URL ?


    Où est la logique ?
    Comment savoir sur quoi on travaille ?


    Merci.

  8. #8
    Rédacteur
    Avatar de _Mac_
    Profil pro
    Inscrit en
    Août 2005
    Messages
    9 601
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 9 601
    Points : 12 977
    Points
    12 977
    Par défaut
    Dans l'absolu, mod_rewrite travaille sur l'URL explicite. Plus exactement, mod_rewrite travaille sur une chaîne de caractères qui est initialisée avec l'URL demandée à Apache, chaîne qui est mise à jour au fur et à mesure des RewriteRule qui sont exécutés.

    Pour ta première règle, mod_rewrite travaille sur l'URL demandée par le navigateur car c'est la première règle (dans l'ordre d'apparition dans le fichier) et qu'il n'y a eu aucun RewriteRule exécuté avant.

    En revanche, pour la seconde règle, je me suis mal exprimé. RewriteRule ne travaille pas sur le fichier réel, c'est RewriteCond qui travaille sur le fichier réel car tu utilises le mot %{REQUEST_FILENAME}. Mais c'est juste un test : est-ce que le chemin complet vers le fichier logiquement appelé ne contient pas la chaîne index.php ? Ensuite, ton RewriteRule qui suit travaille sur l'URL demandée par le navigateur, sauf que tu as un filtre ultra large .+ qui fait que toute URL demandée sera réécrite. Donc pour la seconde règle, c'est une mélange entre une condition basée sur le fichier réel et une réécriture tellement large qu'elle vaut pour tout ou presque.

    Vois la doc standard Apache sur mod_rewrite, il y a un schéma qui me semble bien détailler le fonctionnement de mod_rewrite et qui devrait t'éclairer.

    Du détail, du détail, du détail !!!
    Revenons à la source : lisons la documentation et les fichiers de trace, la réponse à notre problème s'y trouve sans doute

  9. #9
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    397
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 397
    Points : 133
    Points
    133
    Par défaut
    Merci pour ta patience.

    En fait la question est encore plus simple que ça.

    Pourquoi cette règle renvoie "Internal Server Error" quand j'appelle www.example.com/membre/ ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    RewriteRule .+ /membre/ [L]
    Le .htaccess est dans membre.
    La règle ne capture donc rien, aucun caractère.
    Ce qui ne correspond pas à .+ (au moins un caractère).


    Et c'est à ce niveau qu'il ne faut pas me répondre qu'Apache appelle index.php sinon cf règle 1.

  10. #10
    Rédacteur
    Avatar de _Mac_
    Profil pro
    Inscrit en
    Août 2005
    Messages
    9 601
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 9 601
    Points : 12 977
    Points
    12 977
    Par défaut
    Si, la règle capture son propre résultat, donc elle boucle. C'est ce que je disais : ce n'est pas parce qu'on met un [L] qu'on est tranquille : le [L] arrête le cycle de rewrite en cours mais pas la routine complète dont le but est d'aboutir à une URL qui ne déclanche plus aucune règle. Ca donne ça, en gros :
    1. On demande /membre/toto.php
    2. .+ matche /membre/toto.php (plus de 1 caractère), donc ta règle est activée : résultat = /membre/ et fin de la première boucle de réécriture.
    3. Une règle a été activée, il faut voir si la nouvelle URL a besoin d'être réécrite : mod_rewrite reprend donc tes règles depuis le début
    4. .+ matche /membre/ donc ta règle est activée : : résultat = /membre/ et fin de la première boucle de réécriture.
    5. Une règle a été activée, il faut voir si la nouvelle URL a besoin d'être réécrite : mod_rewrite reprend donc tes règles depuis le début
    6. etc.

    D'où qu'on utilise souvent dans le cas d'une règle non spécifique comme la tienne (.+) un RewriteCond pour arrêter la réécriture.

    Du détail, du détail, du détail !!!
    Revenons à la source : lisons la documentation et les fichiers de trace, la réponse à notre problème s'y trouve sans doute

  11. #11
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    397
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 397
    Points : 133
    Points
    133
    Par défaut
    Il y a un point sur lequel je pense que cela fonctionne différemment.
    Ce qui fait que je suis OK jusqu'au point 3, pas après.

    Si le fichier .htaccess est dans le répertoire /membre/, le répertoire en question n'est pas pris en compte dans le matche (ni même le slash /) ?
    En tout cas c'est ce que je vois quand je fais un echo d'une (capture).

    1. On demande /membre/toto.php
    2. .+ matche toto.php (plus de 1 caractère), donc ta règle est activée : résultat = /membre/ et fin de la première boucle de réécriture.
    3. Une règle a été activée, il faut voir si la nouvelle URL a besoin d'être réécrite : mod_rewrite reprend donc tes règles depuis le début
    4. .+ matche "RIEN" donc aucune règle ne doit être activée.
    Qu'en penses-tu ?

  12. #12
    Rédacteur
    Avatar de _Mac_
    Profil pro
    Inscrit en
    Août 2005
    Messages
    9 601
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 9 601
    Points : 12 977
    Points
    12 977
    Par défaut
    Citation Envoyé par dorian53 Voir le message
    Il y a un point sur lequel je pense que cela fonctionne différemment.
    Ce qui fait que je suis OK jusqu'au point 3, pas après.

    Si le fichier .htaccess est dans le répertoire /membre/, le répertoire en question n'est pas pris en compte dans le matche (ni même le slash /) ?
    Effectivement : Apache retire la valeur du RewriteBase au début de l'URL avant traitement (puis le remet éventuellement à la fin de la réécriture), et comme RewriteBase est initialisé à / par défaut, l'URL "/" devient "" (chaîne vide). Et comme le .htaccess se trouve dans le répertoire /membre, ce /membre est également retiré de l'URL, histoire que tous les RewriteXxx travaillent sur des URL relatives au répertoire courant. Donc, finalement, si le .htaccess est dans /membre et que l'URL relative à la racine du site est /membre/, on retire /membre (répertoire du .htaccess) + le RewriteBase, il ne nous reste plus rien.

    Dans mon raisonnement, je partais du principe (mais je ne l'ai pas dit car je pensais que c'était le cas, à vrai dire) que le .htaccess était à la racine du site. Donc finalement, même si on retire le RewriteBase, il reste toujours "membre/" qui vérifie .+.

    Du détail, du détail, du détail !!!
    Revenons à la source : lisons la documentation et les fichiers de trace, la réponse à notre problème s'y trouve sans doute

  13. #13
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    397
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 397
    Points : 133
    Points
    133
    Par défaut
    Citation Envoyé par _Mac_ Voir le message
    Donc, finalement, si le .htaccess est dans /membre et que l'URL relative à la racine du site est /membre/, on retire /membre (répertoire du .htaccess) + le RewriteBase, il ne nous reste plus rien.
    Voilà, si maintenant on re-part d'ici avec les mêmes bases.

    Est-ce que tu sais pourquoi il génère un "Internal Server Error" ?
    Là on est d'accord que logiquement Apache ne devrait entrer dans aucune règle ?

    Je pense qu'il doit malheureusement renvoyer " " blanc quand il n'y a rien à captuer. Non ?

    Merci.

  14. #14
    Rédacteur
    Avatar de _Mac_
    Profil pro
    Inscrit en
    Août 2005
    Messages
    9 601
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 9 601
    Points : 12 977
    Points
    12 977
    Par défaut
    OK, vu mon erreur. Si on active les logs de mod_rewrite, on trouve ceci :
    Citation Envoyé par mod_rewrite
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#ee8ce8/initial] (3) [perdir C:/wamp/www/membre/] strip per-dir prefix: C:/wamp/www/membre/ ->
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#ee8ce8/initial] (3) [perdir C:/wamp/www/membre/] applying pattern '(.+)' to uri ''
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#ee8ce8/initial] (1) [perdir C:/wamp/www/membre/] pass through C:/wamp/www/membre/
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#ee6ce0/subreq] (3) [perdir C:/wamp/www/membre/] strip per-dir prefix: C:/wamp/www/membre/index.php -> index.php
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#ee6ce0/subreq] (3) [perdir C:/wamp/www/membre/] applying pattern '(.+)' to uri 'index.php'
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#ee6ce0/subreq] (2) [perdir C:/wamp/www/membre/] rewrite 'index.php' -> '/membre/?xx=index.php'
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#ee6ce0/subreq] (3) split uri=/membre/?xx=index.php -> uri=/membre/, args=xx=index.php
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#ee6ce0/subreq] (1) [perdir C:/wamp/www/membre/] internal redirect with /membre/ [INTERNAL REDIRECT]
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#2730e08/initial/redir#1] (3) [perdir C:/wamp/www/membre/] strip per-dir prefix: C:/wamp/www/membre/ ->
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#2730e08/initial/redir#1] (3) [perdir C:/wamp/www/membre/] applying pattern '(.+)' to uri ''
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#2730e08/initial/redir#1] (1) [perdir C:/wamp/www/membre/] pass through C:/wamp/www/membre/
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#27390d8/subreq] (3) [perdir C:/wamp/www/membre/] strip per-dir prefix: C:/wamp/www/membre/index.php -> index.php
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#27390d8/subreq] (3) [perdir C:/wamp/www/membre/] applying pattern '(.+)' to uri 'index.php'
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#27390d8/subreq] (2) [perdir C:/wamp/www/membre/] rewrite 'index.php' -> '/membre/?xx=index.php'
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#27390d8/subreq] (3) split uri=/membre/?xx=index.php -> uri=/membre/, args=xx=index.php
    127.0.0.1 - - [28/Jan/2009:15:24:36 +0100] [localhost/sid#643148][rid#27390d8/subreq] (1) [perdir C:/wamp/www/membre/] internal redirect with /membre/ [INTERNAL REDIRECT]
    ...
    Le début se passe comme j'ai décrit mais à la fin, Apache ajoute index.php (parce que DirectoryIndex) et cette nouvelle URL /membre/index.php, issue d'une redirection/réécriture interne, repasse par la moulinette de mod_rewrite, et cette fois-ci, /membre/index.php qui devient après nettoyage index.php valide le filtre .+. CQFD.

    Du détail, du détail, du détail !!!
    Revenons à la source : lisons la documentation et les fichiers de trace, la réponse à notre problème s'y trouve sans doute

  15. #15
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    397
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 397
    Points : 133
    Points
    133
    Par défaut
    Merci de prendre de ton temps pour ces tests.
    On avance dans le raisonnement...

    Par contre maintenant, le problème de la question est déporté car...

    Citation Envoyé par dorian53 Voir le message
    Et c'est à ce niveau qu'il ne faut pas me répondre qu'Apache appelle index.php sinon cf règle 1.
    La règle 1 est la suivante :
    Citation Envoyé par dorian53 Voir le message
    Bonjour,

    Pourquoi cette règle fonctionne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    RewriteRule (.*)index\.php$ /$1 [R=301,L]

    Pourquoi cette règle ne tourne pas en boucle quand elles sont mises toutes les 2 ?
    Citation Envoyé par dorian53 Voir le message
    Voici comment ça fonctionne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    RewriteEngine on
     
    RewriteRule (.*)index\.php$ /membre/$1 [R=301,L]
     
    RewriteCond %{REQUEST_FILENAME} !index.php
    RewriteRule .+ /membre/ [L]

    Mais ma question reste la même, si index.php semble être appelé dans la seconde règle, pourquoi la 1ere règle ne tourne pas en boucle non plus ?

    Merci

  16. #16
    Rédacteur
    Avatar de _Mac_
    Profil pro
    Inscrit en
    Août 2005
    Messages
    9 601
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 9 601
    Points : 12 977
    Points
    12 977
    Par défaut
    Je ne sais pas. J'ai l'impression que le fait de passer de /membre/ à /membre/index.php n'est fait et ne concerne que la seconde règle. Je ne sais pas pourquoi /membre/index.php ne repasse pas depuis le début. C'est comme s'il y avait 2 passes pour chaque règle : une première passe avec l'URL demandée, puis une seconde passe avec l'URL éventuellement complétée par DirectoryIndex si la première passe a échoué.

    Du détail, du détail, du détail !!!
    Revenons à la source : lisons la documentation et les fichiers de trace, la réponse à notre problème s'y trouve sans doute

Discussions similaires

  1. [URL rewriting] Condition avec existence de fichier
    Par Fullvisite dans le forum Apache
    Réponses: 3
    Dernier message: 29/05/2010, 21h17
  2. Réponses: 2
    Dernier message: 13/12/2007, 14h45
  3. [URL Rewriting] Problème avec un paramètre
    Par antitrust56 dans le forum Apache
    Réponses: 11
    Dernier message: 07/11/2007, 18h40
  4. Réponses: 3
    Dernier message: 31/07/2007, 16h40
  5. [URL Rewriting] problème avec sous domaine
    Par Booyakha dans le forum Apache
    Réponses: 1
    Dernier message: 31/07/2007, 16h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo