Question

Nous avons une application PHP avec un schéma d'URL dynamique qui nécessite des caractères à coder pour cent, même « caractères non réservés » comme des parenthèses ou aphostrophes qui ne sont pas réellement nécessaires à coder. URL qui à coder les applications Deems la « mauvaise » façon sont canonisés puis redirigés vers le « droit » de l'encodage.

Mais Google et d'autres agents utilisateurs canoniser pour cent codage / décodage différemment, ce qui signifie quand Googlebot demande la page, il vous demandera l'URL « mauvais », et quand il récupère une redirection vers l'URL « droit », volonté Googlebot refuser de suivre la redirection et refusera d'indexer la page.

Oui, c'est un bug sur notre fin. Les spécifications HTTP exigent que les serveurs traitent pour cent codé et des caractères non réservées pour cent non-codés de manière identique. Mais régler le problème dans le code de l'application est droit non simple, alors j'espérais éviter un changement de code en utilisant une règle de réécriture Apache qui assurerait que les URL sont codées « correctement » du point de vue de l'application , ce qui signifie que apopstrophes, entre parenthèses, etc. sont tous codés pour cent et que les espaces sont codés comme + et non %20.

Voici un exemple, où je veux réécrire la première et se retrouver avec la deuxième forme:

  • www.splunkbase.com/apps/All/4.x/Add-On/app:OPSEC+LEA+for+Check+Point+ (Linux)
  • www.splunkbase.com/apps/All/4.x/Add-On/app:OPSEC+LEA+for+Check+Point+%28Linux%29

Voici une autre:

  • www.splunkbase.com/apps/All/4.x/app:Benford's+Law+Fraud+Detection+Add-on
  • www.splunkbase.com/apps/All/4.x/app:Benford%27s+Law+Fraud+Detection+Add-on

Voici une autre:

  • www.splunkbase.com/apps/All/4.x/app:Benford%27s%20Law%20Fraud%20Detection%20Add-on
  • www.splunkbase.com/apps/All/4.x/app:Benford%27s+Law+Fraud+Detection+Add-on

Si l'application ne voit que la deuxième forme de ces URL, il ne sera pas envoyé de Google Redirections et sera en mesure d'indexer la page.

Je suis un débutant avec les règles de réécriture, et il était clair de mon lecture du

Était-ce utile?

La solution

La solution peut effectivement être assez simple, mais il ne fonctionnera que dans Apache 2.2 et plus tard en raison de l'utilisation de la balise B drapeau . Je ne sais pas si oui ou non il faut bien soin de tous les cas (il est vrai que je suis un peu sceptique, il ne comporte pas plus de travail que cela), mais je suis porté à croire qu'il devrait par le code source.

Gardez à l'esprit aussi que la valeur de REQUEST_URI est pas mis à jour par des transformations mod_rewrite, donc si votre application repose sur cette valeur pour déterminer l'URL demandée, les modifications apportées ne seront pas visibles de toute façon.

Les bonnes nouvelles sont que cela peut être fait en .htaccess, vous avez la possibilité de quitter la configuration principale intacte si cela fonctionne mieux pour vous.

RewriteEngine On

# Make sure this is only done once to avoid escaping the escapes...
RewriteCond %{ENV:REDIRECT_STATUS} ^$
# Check if we have anything to bother escaping (likely unnecessary...)
RewriteCond $0 [^\w]+
# Rewrite the entire URL by escaping the backreference
RewriteRule ^.*$ $0 [B]

Alors, pourquoi est-il nécessaire d'utiliser le drapeau B au lieu de laisser échapper mod_rewrite automatiquement l'URL réécrite? Lorsque mod_rewrite échappe automatiquement l'URL, il utilise ap_escape_uri (qui a apparemment été transformé en une macro pour ap_os_escape_path pour une raison quelconque ...), une fonction qui échappe à un sous-ensemble limité de caractères. Le drapeau de B, cependant, utilise une fonction interne du module appelé escape_uri, qui est calqué sur PHP de urlencode fonction .

La mise en œuvre de escape_uri dans le module suggère que les caractères alphanumériques et caractères de soulignement sont laissés en l'état, les espaces sont convertis en +, et tout le reste est converti en son équivalent échappé. Cela semble être le comportement que vous voulez, on peut donc supposer qu'il devrait fonctionner.

Sinon, vous avez la possibilité de mettre en place un programme externe RewriteMap qui pourrait manipuler vos URL entrantes dans le format correct. Cela nécessite la manipulation de la configuration Apache cependant, et un script renégat pourrait causer des problèmes pour le serveur dans l'ensemble, donc je ne considère pas une solution idéale si elle peut être évitée.

Autres conseils

mod_rewrite n'est pas le meilleur outil pour faire ce genre de travail. Parce qu'avec mod_rewrite vous ne pouvez remplacer une quantité fixe d'occurrences à la fois. Mais il est possible:

RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?\ ]*)%20([^?\ ]*)
RewriteRule ^ /%1+%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?'\ ]*)'([^?'\ ]*)
RewriteRule ^ /%1\%27%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?(\ ]*)\(([^?(\ ]*)
RewriteRule ^ /%1\%28%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?)\ ]*)\)([^?)\ ]*)
RewriteRule ^ /%1\%29%2 [R=301,NE]

Il remplacera un %20, ', ( ou ) à un moment et répond avec une redirection 301. Donc, si un chemin d'URL contient 10 caractères qui doit être remplacé, il a besoin de 10 réoriente de le faire.

Étant donné que cela pourrait ne pas être la meilleure solution, il est possible de faire tous les remplacements, sauf la dernière interne en utilisant N drapeau et seul le dernier remplacement de l'extérieur avec une redirection:

RewriteCond %{THE_REQUEST} ^[A-Z]+\ /(([^?%\ ]|%(2[1-9a-fA-F]|[013-9][0-9a-fA-F]))*)%20(([^?%\ ]|%(2[1-9a-fA-F]|[013-9][0-9a-fA-F]))*%20[^?\ ]*)
RewriteRule ^ /%1+%4 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?\ ]*)%20([^?\ ]*)[?\ ]
RewriteRule ^ /%1+%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?'\ ]*)'([^?'\ ]*'[^?\ ]*)
RewriteRule ^ /%1\%27%2 [N,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?'\ ]*)'([^?'\ ]*)[?\ ]
RewriteRule ^ /%1\%27%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?(\ ]*)\(([^?(\ ]*\([^?\ ]*)
RewriteRule ^ /%1\%28%2 [N,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?(\ ]*)\(([^?(\ ]*)[?\ ]
RewriteRule ^ /%1\%28%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?)\ ]*)\)([^?)\ ]*\)[^?\ ]*)
RewriteRule ^ /%1\%29%2 [N,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?)\ ]*)\)([^?)\ ]*)[?\ ]
RewriteRule ^ /%1\%29%2 [R=301,NE]

Mais en utilisant la N drapeau peut être dangereux car il n'incrémente pas le compteur de récursivité interne et peut donc facilement conduire à une récursion infinie.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top