Come riordinare i parametri URL / la stringa di query utilizzando Apache htaccess?

Sep 18 2020

Ho categorie di e-commerce con navigazione sfaccettata (filtro). Il filtraggio può generare migliaia di URL (utili). Vorrei ridurre nr. di possibili URL mostrando determinati contenuti sempre sullo stesso URL con lo stesso ordine dei parametri della stringa di query.

Da un punto di vista SEO potrei usare il tag canonico per eliminare logicamente gli URL duplicati, ma dal punto di vista delle prestazioni sarebbe molto meglio risolverlo con RewriteRules.

URL di esempio con lo stesso contenuto ma diverso ordine dei parametri:

  • 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

Questi URL devono essere reindirizzati a un URL in cui i parametri della query vengono visualizzati sempre nello stesso ordine. per esempio:

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

Nota che:

  • Ho più di 10 criteri di filtro (parametri query)
  • L'ordine dei parametri cambia in base all'ordine di selezione del filtro dell'utente. Possono apparire in qualsiasi ordine dato.
  • Solo i parametri utilizzati vengono visualizzati nell'URL. Alcune pagine hanno uno o due parametri nel loro URL, altre ne hanno fino a dieci o più.

Hai idea di come ottenerlo?

Ho trovato qualcosa di promettente in questa domanda, ma non riesco a farlo funzionare:
RewriteCond per abbinare i parametri della stringa di query in qualsiasi ordine

Risposte

MrWhite Sep 24 2020 at 00:13

ma dal punto di vista delle prestazioni sarebbe molto meglio risolverlo con RewriteRules.

Dal punto di vista delle prestazioni , sarebbe molto meglio risolverlo nella tua applicazione, non .htaccess/ mod_rewrite (ie. RewriteRuleS). Vuoi sempre collegarti correttamente all'URL canonico.

Certamente non vuoi reindirizzare esternamente l'utente in quanto applica filtri per "correggere" l'ordine dei parametri URL. I parametri URL devono essere applicati nella "corretta" per cominciare dall'applicazione.

L'unico momento in cui sarebbe utile "reindirizzare" l'utente è se ha seguito un collegamento non canonico di terze parti (da un altro sito web o motore di ricerca) ed è necessario risolvere potenziali problemi SEO. Ma anche in questo caso, il codice per correggere l'ordine dei parametri URL dovrebbe essere molto più semplice (e più facile da mantenere) se implementato come parte della logica dell'applicazione, non .htaccess. Il codice per farlo .htaccessè relativamente più "complesso" (leggi: disordinato, potenzialmente più difficile da mantenere, più incline a errori, ecc.)

Tuttavia, è un problema interessante e potrebbe esserci un'occasione in cui è preferibile (o necessario) codificarlo in .htaccess(o nella configurazione del server Apache) quando non sei in grado di farlo facilmente nella tua applicazione.

Soluzione che utilizza mod_rewrite in .htaccess(o configurazione del server)

(Tuttavia, nota i commenti sopra: questo potrebbe non essere quello che dovresti fare.)

Questa è una soluzione ragionevolmente generica che funziona in .htaccess(o nella configurazione del server). Allo stato attuale, funziona su qualsiasi percorso URL. Per farlo funzionare su un singolo percorso URL (ad es. /category/subcategory/, Come indicato nella domanda), modificare il pattern nella RewriteRuledirettiva finale . Per esempio:

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

In alternativa, potresti scrivere un'eccezione in alto per saltare queste regole per determinati URL se devi applicarla a un gruppo di URL e non ad altri. Questo potrebbe essere più ottimale in quanto evita qualsiasi elaborazione non necessaria della stringa di query.

Questo blocco di codice dovrebbe essere posizionato all'inizio del .htaccessfile. (L'ordine conta.)

Questo codice ha il "vantaggio" aggiunto di "disinfettare" anche la stringa di query rimuovendo tutti i parametri URL non definiti (all'inizio dello script).

Poiché non è banale determinare "semplicemente" se i parametri URL originali sono già nell'ordine corretto, lo script esegue il processo di costruzione di una nuova stringa di query con i parametri URL nell'ordine corretto e quindi lo confronta con la query originale stringa per determinare se è necessario un reindirizzamento.

Criteri:

  • Fino a 10 parametri URL
  • Qualsiasi numero di parametri URL può essere visualizzato in qualsiasi ordine
  • I parametri URL vuoti non devono essere inclusi
  • I parametri URL fanno distinzione tra maiuscole e minuscole
  • Funziona per qualsiasi percorso URL
  • URL nomi dei parametri corrispondono al regex [\w-]+(es. a-z, A-Z, 0-9, _E -)
  • I valori dei parametri URL non possono contenere @(a meno che l'URL non sia codificato)
  • @@@ non può apparire da nessuna parte nella stringa di query

Devi semplicemente definire i nomi dei parametri URL nella parte superiore dello script, nell'ordine in cui desideri che siano. Questi sono tenuti in variabili d'ambiente VAR_NAME_01, VAR_NAME_02ecc La parte restante dello script dovrebbe funzionare inalterato a meno che:

  • è necessario aggiungere più parametri URL
  • OPPURE, modifica il carattere utilizzato internamente per delimitare le sezioni nella corrispondenza del modello (attualmente " @").
  • OPPURE, limitare il codice a un percorso URL specifico.

Script:

# 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]

Se hai domande su parti specifiche di questo script, dì nei commenti ...