J'ai un simple RewriteRule, ajoutant une chaîne à certaines URL:
RewriteRule ^labels/([^/]+)/?$ /labels/$1/releases/ [R=301,L,NC]
Les liens sont basés sur des bases de données, et cela fonctionne très bien. Eh bien, à part l'un d'entre eux. Le nom contient ?!
à la fin, disons label?!
.
Les liens générés sont corrects, à savoir:
/labels/label%3F%21
Mais la redirection est appliquée deux fois et ne considère évidemment pas le point d'interrogation codé comme faisant partie de l'URL. Le lien résultant devrait être:
/labels/label%3F%21/releases/
Mais nous obtenons à la place:
/labels/label/releases/?!/releases/
Je peux voir que la règle est effectivement appliquée deux fois, mais je suis sûr que cela peut être facilement résolu si je surmonte mon premier problème: pourquoi les réécriteurs voient-ils le %2F
codé comme un délimiteur de chaîne de requête? Comment puis-je atténuer ce cas?
Merci pour tout indice!
Vous avez besoin du drapeau B
pour échapper à la référence arrière et le NE
(noescape
) pour empêcher le résultat substitution (c'est-à-dire le backreference) étant doublement codé. Par exemple:
RewriteRule ^labels/([^/]+)/?$ /labels/$1/releases/ [B,NE,R=301,L,NC]
Vous devrez vider le cache de votre navigateur, car le précédent (erroné) 301 aura été mis en cache.
Pourquoi les réécriteurs voient-ils le
%2F
codé comme un délimiteur de chaîne de requête?
Légère faute de frappe là je pense ... tu veux dire %3F
. Oui, vous obtenez 2 redirections parce que ...
lorsque vous demandez /labels/label%3F%21
, la RewriteRule
motif correspond au chemin d'URL décodé par%, c'est-à-dire. /labels/label?!
. Selon votre règle, label?!
est alors copié dans la substitution, ce qui entraîne une redirection vers /labels/label?!/releases/
(le ?!
ne sera pas automatiquement recodé). Quel est un chemin URL de /labels/label
et une chaîne de requête de !/releases/
. C'est de là que vient la chaîne de requête.
Sur la demande redirigée, /labels/label
correspond à votre RewriteRule
motif (la chaîne de requête est ignorée à ce stade). Cette fois, label
est copié dans le substitution, pour devenir /labels/label/releases/
. Et ensuite, la chaîne de requête de la demande est transmise à la substitution, pour aboutir à une seconde redirection vers /labels/label/releases/?!/releases/
.
Le drapeau B
échappe au motif capturé. par exemple. label?!
est échappé pour devenir label%3F%21
.
Et le drapeau NE
empêche le %
d’être codé comme %25
(c’est-à-dire qu’il s’agit d’un codage doublement codé de la référence arrière). par exemple. label%3F%21
serait sinon codé en tant que label%253F%2521
.
De côté: mod_rewrite ne code pas automatiquement le premier?
dans le substitution car il est supposé que cela lance la chaîne de requête. Cependant, les ?
suivants seront automatiquement codés. par exemple. Étant donné RewriteRule ^foo$ /bar??? [R,L]
, une demande de /foo
entraîne une redirection vers /bar?%3f%3f
(notez que les deux deuxièmes ?
sont codés en URL, mais le premier ne l'est pas).