fragen stichworte

Mod_rewrite ersetzt Unterstriche (oder Bindestriche) in Opencart

Ich übertrage eine E-Commerce-Site in einen neuen Warenkorb. Aus irgendeinem Grund wurden auf der alten Site Bindestriche für Kategorien verwendet, jedoch für Produkte.

Die vollständige URL eines Produkts sieht also folgendermaßen aus:

http://www.example.com/Engineering-Common-Bricks/65mm_Class_B__Solid_Engineering_Brick__Price_Each

Der neue Warenkorb verwendet Bindestriche für alles, sodass ich eingehende URLs wie die oben genannten umschreiben muss:

http://www.example.com/Engineering-Common-Bricks/65mm-Class-B--Solid-Engineering-Brick--Price-Each

Ich weiß, dass es viel Material zum Umschreiben von Unterstreichungen in Bindestriche gibt, aber keines davon scheint für mich zu funktionieren.

Ich verwende Opencart, das bereits vorhandene Regeln zum Umschreiben enthält. Diese stören möglicherweise die neuen Regeln, die ich hinzufügen möchte.

Der vorhandene .htaccess lautet wie folgt:

Options +FollowSymlinks

# Prevent Directoy listing 
Options -Indexes

# Prevent Direct Access to files
<FilesMatch "\.(tpl|ini|log)">
 Order deny,allow
 Deny from all
</FilesMatch>

# SEO URL Settings
RewriteEngine On
# If your opencart installation does not run on the main web folder make sure you folder it does run in ie./becomes/shop/

RewriteBase/
RewriteRule ^sitemap.xml$ index.php?route=feed/google_sitemap [L]
RewriteRule ^googlebase.xml$ index.php?route=feed/google_base [L]
RewriteRule ^download/(.*)/index.php?route=error/not_found [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !.*\.(ico|gif|jpg|jpeg|png|js|css)
RewriteRule ^([^?]*) index.php?_route_=$1 [L,QSA]

Jede Hilfe oder Anweisung wird dankbar angenommen.


Aktualisieren der .htaccess gemäß Esas Antwort auf Folgendes:

Options +FollowSymlinks
Options -Indexes

<FilesMatch "\.(tpl|ini|log)">
 Order deny,allow
 Deny from all
</FilesMatch>

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^_]*)_([^_]*_.*) $1-$2 [N]
RewriteRule ^([^_]*)_([^_]*)$/$1-$2 [L,R=301]

RewriteBase/
RewriteRule ^sitemap.xml$ index.php?route=feed/google_sitemap [L]
RewriteRule ^googlebase.xml$ index.php?route=feed/google_base [L]
RewriteRule ^download/(.*)/index.php?route=error/not_found [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !.*\.(ico|gif|jpg|jpeg|png|js|css)
RewriteRule ^([^?]*) index.php?_route_=$1 [L,QSA]

Funktioniert gut für:

http://example.com/this_is_a_category

Apache stürzt jedoch ab:

http://example.com/this_is_a_category/this_is_a_product

antworten

Da RewriteRules Übereinstimmungen mit regulären Ausdrücken anstelle von Ersetzungen sind, ist die erste Zeile in

RewriteRule ^([^_]*)_([^_]*_.*) $1-$2 [N]
RewriteRule ^([^_]*)_([^_]*)$/$1-$2 [L,R=301]

wird nicht wiederholt. Daher benötigen Sie für jede Unterstriche eine Zeile, z.

RewriteRule ^(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)$/$1-$2-$3-$4-$5-$6-$7 [R=301,L]
RewriteRule ^(.*)_(.*)_(.*)_(.*)_(.*)_(.*)$/$1-$2-$3-$4-$5-$6 [R=301,L]
RewriteRule ^(.*)_(.*)_(.*)_(.*)_(.*)$/$1-$2-$3-$4-$5 [R=301,L]
RewriteRule ^(.*)_(.*)_(.*)_(.*)$/$1-$2-$3-$4 [R=301,L]
RewriteRule ^(.*)_(.*)_(.*)$/$1-$2-$3 [R=301,L]
RewriteRule ^(.*)_(.*)$/$1-$2 [R=301,L]

ersetzt 1-5 Unterstriche und führt zu

/Engineering_Common_Bricks/65mm_Class_B-Solid-Engineering-Brick-Price-Each

Für 9 ersetzt man also ein paar Zeilen nach oben. Das Muster wird gleich sein, aber die längeren Ausdrücke müssen zuerst stehen.

Dies ersetzt jedoch alle Unterstriche durch Bindestriche (und Weiterleitungen nach dem letzten), sodass Sie keine Dateinamen mit Unterstrichen verwenden dürfen. Sie können dies auch verhindern, indem Sie vor diesen Regeln eine RewriteCond-Direktive hinzufügen:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^_]*)_([^_]*_.*) $1-$2 [N]
RewriteRule ^([^_]*)_([^_]*)$/$1-$2 [L,R=301]

Works fine for:

http://example.com/this_is_a_category

But causes Apache to crash on:

http://example.com/this_is_a_category/this_is_a_product

Um dieses Problem zu beheben, müssen Sie lediglich das Flag DPI (Discard Path Info) zur ersten RewriteRule -Direktive hinzufügen:

RewriteRule ^([^_]*)_([^_]*_.*) $1-$2 [N,DPI]
RewriteRule ^([^_]*)_([^_]*)$/$1-$2 [L,R=301]

Der "Apache-Absturz" wird durch eine endlose -Schreibschleife verursacht. Das Flag N bewirkt, dass der Regelsatz wiederholt wird (was in diesem Szenario erforderlich ist, um alle Striche eines der Unterstriche zu ersetzen). Die Pfadinformationen aus der ursprünglichen Anforderung werden jedoch bei jeder Iteration (je nach Entwurf) an die neu geschriebene URL angehängt ).

Im ersten Beispiel gibt es mit nur einem Pfadsegment keine zusätzlichen Pfadinformationen, sodass nichts angehängt wird. Das zweite Beispiel enthält jedoch zusätzliche Pfadinformationen, nämlich /this_is_a_product (alles nach dem ersten Pfadsegment, das keinem physischen Dateisystempfad zugeordnet ist) - das selbst Unterstriche enthält. Das ist das Problem. Jede Iteration der Schleife ersetzt nur einen Unterstrich, aber jede Iteration der Schleife hängt auch 3 weitere (in diesem Beispiel) an! Daher ist es niemals möglich, alle Unterstriche (Takt Eins) zu ersetzen!

Wenn Sie die Protokollierung zum erneuten Schreiben aktivieren, wird im Fehlerprotokoll Folgendes angezeigt:

/this_is_a_category/this_is_a_product
/this-is_a_category/this_is_a_product/this_is_a_product
/this-is-a_category/this_is_a_product/this_is_a_product/this_is_a_product
/this-is-a-category/this_is_a_product/this_is_a_product/this_is_a_product/this_is_a_product
/this-is-a-category/this-is_a_product/this_is_a_product/this_is_a_product/this_is_a_product/this_is_a_product
:

Wie Sie sehen, gerät dies sehr schnell außer Kontrolle. Standardmäßig wird er nach 32.000 Iterationen (!) Angehalten, aber dem Server gehen wahrscheinlich die Ressourcen vorher aus. daher der Absturz. Auf Apache 2.4.8 und höher können Sie die Anzahl der Iterationen begrenzen, z. N=10 - Obwohl dies Ihr Problem nicht lösen wird, wird der Server nicht mehr abstürzen!

AFAIK, das DPI -Flag (Apache 2.2.12+) wurde speziell zur Lösung dieses Problems erstellt. Die ursprünglichen Pfadinformationen werden von der umgeschriebenen URL verworfen, sodass sie nicht jedes Mal erneut angefügt werden. Dadurch wird die endlose Umschreibungsschleife verhindert.

Referenz: