119 votes

Fonctionnalités cachées de mod_rewrite

Il semble y avoir un nombre décent de mod_rewrite threads qui circulent ces derniers temps avec un peu de confusion sur le fonctionnement de certains aspects. En conséquence, j'ai compilé quelques notes sur les fonctionnalités communes et peut-être quelques nuances ennuyeuses.

Quelles autres fonctionnalités / problèmes communs rencontrez-vous en utilisant mod_rewrite ?

203voto

Owen Points 36009

Où placer les règles de mod_rewrite

mod_rewrite règles peuvent être placés à l'intérieur de l' httpd.conf le fichier, ou au sein de l' .htaccess le fichier. si vous avez accès à l' httpd.conf, plaçant les règles ici offrira un avantage de performance (comme les règles sont traitées une fois, par opposition à chaque fois que l' .htaccess le fichier est appelée).

La journalisation mod_rewrite demandes

la journalisation peut être activé à partir de l'intérieur de l' httpd.conf le fichier (y compris <Virtual Host>):

# logs can't be enabled from .htaccess
# loglevel > 2 is really spammy!
RewriteLog /path/to/rewrite.log
RewriteLogLevel 2

Cas d'utilisation courante

  1. pour canaliser toutes les demandes à un seul point:

    RewriteEngine on
    # ignore existing files
    RewriteCond %{REQUEST_FILENAME} !-f   
    # ignore existing directories
    RewriteCond %{REQUEST_FILENAME} !-d   
    # map requests to index.php and append as a query string
    RewriteRule ^(.*)$ index.php?query=$1 
    

    Depuis Apache 2.4 vous pouvez également utiliser FallbackResource.

  2. la manipulation 301/302 redirections:

    RewriteEngine on
    # 302 Redirect
    RewriteRule ^oldpage.html$ /newpage.html [R=302]  
    # 301 Redirect
    RewriteRule ^oldpage2.html$ /newpage.html [R=301] 
    

    note: redirections externes sont implicitement 302 redirections:

    # this rule:
    RewriteRule ^somepage.html$ http://google.com
    # is equivalent to:
    RewriteRule ^somepage.html$ http://google.com [R]
    # and:
    RewriteRule ^somepage.html$ http://google.com [R=302]
    
  3. forcer SSL

    RewriteEngine on
    RewriteCond %{SERVER_PORT} 80
    RewriteRule ^(.*)$ https://example.com/$1 [R,L]
    
  4. drapeau commun d'utilisation:

    • [R] de forcer une redirection (302)
    • [R=301] forcer une redirection 301
    • [L] arrêter le processus de réécriture (voir la note ci-dessous dans les pièges les plus courants)
    • [NC] casse matchs

    vous pouvez mélanger et assortir les drapeaux:

    RewriteRule ^olddir(.*)$ /newdir$1 [L,NC]
    

Les pièges les plus courants

  1. mélanger mod_alias style redirections mod_rewrite

    # Bad
    Redirect 302 /somepage.html http://example.com/otherpage.html
    RewriteEngine on
    RewriteRule ^(.*)$ index.php?query=$1
    
    # Good (use mod_rewrite for both)
    RewriteEngine on
    # 302 redirect and stop processing
    RewriteRule ^somepage.html$ /otherpage.html [R=302,L] 
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    # handle other redirects
    RewriteRule ^(.*)$ index.php?query=$1                 
    

    remarque: vous pouvez mélanger mod_alias avec mod_rewrite, mais il implique plus de travail que juste de la manipulation de base des redirections comme ci-dessus.

  2. contexte affecte la syntaxe

    au sein d' .htaccess fichiers, un slash n'est pas utilisé dans le modèle:

    # given: GET /directory/file.html
    
    # .htaccess
    # result: /newdirectory/file.html
    RewriteRule ^directory(.*)$ /newdirectory$1
    
    # .htaccess
    # result: no match!
    RewriteRule ^/directory(.*)$ /newdirectory$1
    
    # httpd.conf
    # result: /newdirectory/file.html
    RewriteRule ^/directory(.*)$ /newdirectory$1
    
    # Works in both contexts:
    RewriteRule ^/?directory(.*)$ /newdirectory$1
    
  3. [L] n'est pas la dernière! (parfois)

    au sein de l' .htaccess contexte, [L] de ne pas forcer mod_rewrite pour l'arrêter. il continuera à déclenchement interne des sous-requêtes:

    # processing does not stop here
    RewriteRule ^dirA$ /dirB [L] 
    # /dirC will be the final result
    RewriteRule ^dirB$ /dirC     
    

    notre réécrire journal affiche les détails:

    rewrite 'dirA' -> '/dirB'
    internal redirect with /dirB [INTERNAL REDIRECT]
    rewrite 'dirB' -> '/dirC'
    

    Dans de tels cas [END] doit être utilisé à la place de [L].

21voto

mromaine Points 196

Si vous avez besoin de "bloquer" les redirections / réécritures internes dans le fichier .htaccess, consultez le

 RewriteCond %{ENV:REDIRECT_STATUS} ^$
 

condition, comme discuté ici .

18voto

Sean McMillan Points 5096

Le deal avec RewriteBase:

Vous devez presque toujours définir RewriteBase. Si vous ne le faites pas, Apache devine que votre base est le chemin physique de votre répertoire. Alors commencez par ceci:

 RewriteBase /
 

13voto

mike Points 3565

D'Autres Écueils:

1 - c'est Parfois une bonne idée de désactiver Multivues

Options -MultiViews

Je ne suis pas bien verset sur tous Multivues capacités, mais je sais qu'il bousille mes règles mod_rewrite lorsqu'il est actif, parce que l'une de ses propriétés est d'essayer de "deviner" une extension à un fichier qu'il pense que je suis à la recherche pour.

Je vais vous expliquer: Supposons que vous avez 2 fichiers php de votre site web dir, file1.php et file2.php et vous ajoutez ces conditions et la règle de votre .htaccess :

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ file1.php/$1

Vous supposez que toutes les url qui ne correspond pas à un fichier ou à un répertoire sera saisi par file1.php. Surprise! Cette règle n'est pas respectée pour l'url http://myhost/file2/somepath. Au lieu de cela, vous êtes pris à l'intérieur file2.php.

Ce qui se passe est que Multivues automatiquement deviné que l'url que vous avez réellement voulu, c'était http://myhost/file2.php/somepath et a pris un plaisir de vous y rendre.

Maintenant, vous n'avez aucune idée de ce qui s'est passé et vous êtes à ce point d'interrogation tout ce que vous pensiez que vous saviez sur le mod_rewrite. Vous commencez alors à jouer avec les règles pour essayer de comprendre la logique derrière cette nouvelle situation, mais en plus vous faites des tests les moins de sens.

Ok, En bref si vous voulez mod_rewrite pour travailler d'une façon qui se rapproche de la logique, la désactivation de l'Multivues est un pas dans la bonne direction.

2 - activer FollowSymlinks

Options +FollowSymLinks

Que d'une, je ne connais pas vraiment les détails, mais je l'ai vu mentionné à plusieurs reprises, si juste de le faire.

5voto

DrDol Points 1491

L'équation peut être faite avec l'exemple suivant:

 RewriteCond %{REQUEST_URI} ^/(server0|server1).*$ [NC]
# %1 is the string that was found above
# %1<>%{HTTP_COOKIE} concatenates first macht with mod_rewrite variable -> "test0<>foo=bar;"
#RewriteCond search for a (.*) in the second part -> \1 is a reference to (.*)
# <> is used as an string separator/indicator, can be replaced by any other character
RewriteCond %1<>%{HTTP_COOKIE} !^(.*)<>.*stickysession=\1.*$ [NC]
RewriteRule ^(.*)$ https://notmatch.domain.com/ [R=301,L]
 

Équilibrage de charge dynamique:

Si vous utilisez mod_proxy pour équilibrer votre système, il est possible d'ajouter une plage dynamique de serveur de travail.

 RewriteCond %{HTTP_COOKIE} ^.*stickysession=route\.server([0-9]{1,2}).*$ [NC]
RewriteRule (.*) https://worker%1.internal.com/$1 [P,L]
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X