Comment réorganiser les paramètres d'URL / la chaîne de requête à l'aide d'Apache htaccess?

Sep 18 2020

J'ai des catégories de commerce électronique avec une navigation à facettes (filtrage). Le filtrage peut générer des milliers d'URL (utiles). Je voudrais réduire nr. des URL possibles en affichant toujours certains contenus sur la même URL avec le même ordre des paramètres de chaîne de requête.

D'un point de vue SEO, je pourrais utiliser la balise canonique pour éliminer logiquement les URL dupliquées, mais du point de vue des performances, il serait bien préférable de le résoudre avec RewriteRules.

Exemples d'URL avec le même contenu mais un ordre de paramètres différent:

  • https://example.com/category/subcategory/?filter_manuf=grohe&filter_style=design&filter_family=bauedge&filter_warranty=5y
  • https://example.com/category/subcategory/?filter_style=design&filter_manuf=grohe&filter_warranty=5y&filter_family=bauedge

Ces URL doivent être redirigées vers une URL dans laquelle les paramètres de requête apparaissent toujours dans le même ordre. par exemple:

https://example.com/category/subcategory/?filter_manuf=grohe&filter_family=bauedge&filter_style=design&filter_warranty=5y

Notez que:

  • J'ai plus de 10 critères de filtrage (paramètres de requête)
  • L'ordre des paramètres change en fonction de l'ordre de sélection des filtres de l'utilisateur. Ils peuvent apparaître dans n'importe quel ordre.
  • Seuls les paramètres utilisés apparaissent dans l'URL. Certaines pages ont un ou deux paramètres dans leur URL, d'autres jusqu'à dix ou plus.

Avez-vous une idée de comment y parvenir?

J'ai trouvé quelque chose de prometteur dans cette question, mais je ne peux pas le faire fonctionner:
RewriteCond pour faire correspondre les paramètres de chaîne de requête dans n'importe quel ordre

Réponses

MrWhite Sep 24 2020 at 00:13

mais du point de vue des performances, il serait bien préférable de le résoudre avec RewriteRules.

Du point de vue des performances , il serait bien préférable de résoudre ce problème dans votre application, et non dans .htaccess/ mod_rewrite (ie. RewriteRuleS). Vous voulez toujours être correctement lié à l'URL canonique.

Vous ne voulez certainement pas rediriger l'utilisateur en externe car il applique des filtres afin de "corriger" l'ordre des paramètres d'URL. Les paramètres d'URL doivent être appliqués dans le "correct" pour commencer par votre application.

Le seul moment où il serait avantageux de «rediriger» l'utilisateur est s'il a suivi un lien non canonique tiers (à partir d'un autre site Web ou d'un autre moteur de recherche) et que vous devez résoudre des problèmes potentiels de référencement. Mais même dans ce cas, le code pour corriger l'ordre des paramètres d'URL devrait être beaucoup plus simple (et plus facile à maintenir) s'il est implémenté dans le cadre de la logique de votre application, non .htaccess. Le code pour cela .htaccessest comparativement plus "complexe" (lire: désordonné, potentiellement plus difficile à maintenir, plus sujet aux erreurs, etc.)

Cependant, c'est un problème intéressant et il peut y avoir une occasion où il est préférable (ou nécessaire) de le coder dans .htaccess(ou dans la configuration du serveur Apache) lorsque vous ne pouvez pas le faire facilement dans votre application.

Solution utilisant mod_rewrite dans .htaccess(ou configuration du serveur)

(Cependant, notez les commentaires ci-dessus - ce n'est peut-être pas ce que vous devriez faire.)

Il s'agit d'une solution raisonnablement générique qui fonctionne dans .htaccess(ou dans la configuration du serveur). En l'état, cela fonctionne sur n'importe quel chemin d'URL. Pour le faire fonctionner sur un seul chemin d'URL (par exemple /category/subcategory/, comme indiqué dans la question), modifiez le modèle dans la RewriteRuledirective finale . Par exemple:

RewriteRule ^category/subcategory/$ %{REQUEST_URI}?%{ENV:NEW_QUERY_STRING} [NE,R=302,L]

Vous pouvez également écrire une exception en haut pour ignorer ces règles pour certaines URL si vous devez l'appliquer à un groupe d'URL et pas à d'autres. Cela peut être plus optimal car cela évite tout traitement inutile de la chaîne de requête.

Ce bloc de code devrait aller vers le haut de votre .htaccessfichier. (L'ordre compte.)

Ce code a l'avantage supplémentaire qu'il "nettoie" également la chaîne de requête en supprimant tous les paramètres d'URL qui ne sont pas définis (en haut du script).

Comme il n'est pas simple de déterminer "simplement" si les paramètres d'URL d'origine sont déjà dans le bon ordre, le script passe par le processus de construction d'une nouvelle chaîne de requête avec les paramètres d'URL dans le bon ordre, puis compare cela à la requête d'origine string afin de déterminer si une redirection est nécessaire.

Critères:

  • Jusqu'à 10 paramètres d'URL
  • N'importe quel nombre de paramètres d'URL peut apparaître dans n'importe quel ordre
  • Les paramètres d'URL vides ne doivent pas être inclus
  • Les paramètres d'URL sont sensibles à la casse
  • Fonctionne pour n'importe quel chemin URL
  • Les noms de paramètres URL correspondent à l'expression rationnelle [\w-]+(ie. a-z, A-Z, 0-9, _Et -)
  • Les valeurs de paramètre d'URL ne peuvent pas contenir @(sauf si une URL est encodée)
  • @@@ ne peut apparaître nulle part dans la chaîne de requête

Il vous suffit de définir les noms des paramètres d'URL en haut du script, dans l'ordre que vous souhaitez qu'ils soient. Ceux - ci ont lieu dans les variables d'environnement VAR_NAME_01, VAR_NAME_02etc. Le reste du script devrait fonctionner sans modification , sauf:

  • vous devez ajouter plus de paramètres d'URL
  • OU, modifiez le caractère utilisé en interne pour délimiter les sections dans la correspondance de modèle (actuellement " @").
  • OU, limitez le code à un chemin d'URL spécifique.

Scénario:

# Define the "name" of each URL parameter
# The numeric order determines the order of the resulting URL parameter list.
# Comment out any URL parameters that are not required.
SetEnvIf ^ ^ VAR_NAME_01=one
SetEnvIf ^ ^ VAR_NAME_02=two
SetEnvIf ^ ^ VAR_NAME_03=three
SetEnvIf ^ ^ VAR_NAME_04=four
SetEnvIf ^ ^ VAR_NAME_05=five
SetEnvIf ^ ^ VAR_NAME_06=six
SetEnvIf ^ ^ VAR_NAME_07=seven
SetEnvIf ^ ^ VAR_NAME_08=eight
SetEnvIf ^ ^ VAR_NAME_09=nine
SetEnvIf ^ ^ VAR_NAME_10=ten

###############################################################################
# Shouldn't need to modify directives below here...

RewriteEngine on
Options +FollowSymLinks

# -----------------------------------------------------------------------------
# Read each URL parameter (if any) and store in corresponding env var

RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_01} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_01:%2]

RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_02} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_02:%2]

RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_03} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_03:%2]

RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_04} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_04:%2]

RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_05} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_05:%2]

RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_06} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_06:%2]

RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_07} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_07:%2]

RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_08} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_08:%2]

RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_09} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_09:%2]

RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_10} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_10:%2]

# -----------------------------------------------------------------------------
# Construct new query string
# Only with URL parameters that are not empty

RewriteCond %{ENV:VAR_VALUE_01} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:VAR_NAME_01}=%{ENV:VAR_VALUE_01}]

RewriteCond %{ENV:VAR_VALUE_02} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_02}=%{ENV:VAR_VALUE_02}]

RewriteCond %{ENV:VAR_VALUE_03} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_03}=%{ENV:VAR_VALUE_03}]

RewriteCond %{ENV:VAR_VALUE_04} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_04}=%{ENV:VAR_VALUE_04}]

RewriteCond %{ENV:VAR_VALUE_05} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_05}=%{ENV:VAR_VALUE_05}]

RewriteCond %{ENV:VAR_VALUE_06} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_06}=%{ENV:VAR_VALUE_06}]

RewriteCond %{ENV:VAR_VALUE_07} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_07}=%{ENV:VAR_VALUE_07}]

RewriteCond %{ENV:VAR_VALUE_08} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_08}=%{ENV:VAR_VALUE_08}]

RewriteCond %{ENV:VAR_VALUE_09} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_09}=%{ENV:VAR_VALUE_09}]

RewriteCond %{ENV:VAR_VALUE_10} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_10}=%{ENV:VAR_VALUE_10}]

# -----------------------------------------------------------------------------
# Trim "&" prefix from the NEW_QUERY_STRING
RewriteCond %{ENV:NEW_QUERY_STRING} ^&(.+)
RewriteRule ^ - [E=NEW_QUERY_STRING:%1]

# Compare with existing QUERY_STRING to determine whether it's in the correct order already
# If different then redirect...
RewriteCond %{QUERY_STRING}@@@%{ENV:NEW_QUERY_STRING} !^(.+)@@@\1
RewriteRule ^ %{REQUEST_URI}?%{ENV:NEW_QUERY_STRING} [NE,R=302,L]

Si vous avez des questions concernant des parties spécifiques de ce script, dites simplement dans les commentaires ...