Zur Navigation

Code-Blöcke in .htaccess und deren Reihenfolge

1 Martin

Hallo,
wenn mehrere unterschiedliche Sachen in einer .htaccess zusammenkommen, spielt doch auch deren Reihenfolge eine Rolle, oder?

Stimmt die nachfolgende .htaccess für eine Wordpress-Installation so, im Hinblick auf
- die Reihenfolge der sechs "Blöcke"
- sowie den Code zum Cachen (mod_expire) und Komprimieren (mod_deflate)?

Zuerst die Dateien, die aus Sicherheitsgründen gar nicht ausgeliefert werden sollen (xmlrpc.php und readme), dann serverseitige deflate-Komprimierung und mod_expire-caching und schließlich 301-redirect und Wordpress-Standard-Code.

Zuerst Komprimierung und dann Caching oder umgekehrt?

# xmlrpc.php deaktivieren zwecks sicherheit
<Files "xmlrpc.php">
Order allow,deny
Deny from all
</Files>

# Kein Zugriff auf Dateien mit WP-Version
<FilesMatch "(liesmich.html|readme.html|liesmich.txt|readme.txt|licence.txt)">
Order deny,allow
Deny from all
</FilesMatch>

# Serverseitige deflate-Komprimierung
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain text/html text/xml text/css text/javascript text/rtf
AddOutputFilterByType DEFLATE application/javascript application/x-javascript application/msword
</IfModule>

# Browser-Caching durch mod_expires
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg image/jpeg image/gif image/png image/x-icon "access plus 1 month"
ExpiresByType video/mp4 audio/mpeg audio/mp4 "access plus 1 month"
ExpiresByType text/css text/rtf text/javascript "access plus 2 weeks"
ExpiresByType application/pdf application/zip application/msword "access plus 1 month"
ExpiresByType application/javascript application/x-javascript "access plus 2 weeks"
</IfModule>


# Keine php-Fehlermeldungen mit Serverpfad, verursacht Fehler 500 bei DF!
# Geht bei DF aber über php-ini-Einstellungen im Kunden-Menue
# php_flag display_errors off

#301-redirect: page.html zu page
RewriteRule ^([\w-]+)\.html$ http://www.domain.de/$1 [R=301,L]

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

Martin

05.06.2015 11:50

2 Jörg Kruse

Ich habe das grad mal getestet:

#301-redirect: page.html zu page
RewriteRule ^([\w-]+)\.html$ http://www.domain.de/$1 [R=301,L]
# Kein Zugriff auf Dateien mit WP-Version
<FilesMatch "(liesmich.html|readme.html|liesmich.txt|readme.txt|licence.txt)">
Order deny,allow
Deny from all
</FilesMatch>

Auch in dieser Reihenfolge wird http://www.domain.de/liesmich.html nicht erst weitergeleitet, sondern erhält sofort eine Fehlermeldung 403.

Relevant ist wohl die Anordnung der Direktiven ein und desselben Moduls innerhalb der htaccess Datei, z.B. zweier RewriteRules. Die Reihenfolge von Direktiven verschiedener Module (hier: mod_access und mod_rewrite) regelt der Apache anscheinend intern.

06.06.2015 14:37

3 Martin

Danke für die "praktisch orientierte" Mühe.

Also lediglich bei Rewrites (auch Redirects?) ist es wirklich wichtig, ansonsten sollte es - bei einem vernünftig konfigurierten Server - keine Rolle spielen.

Gibt es andere Gründe, z.B. Performance oder Sicherheit, die gewisse Reihenfolgen nahelegen?

Martin

06.06.2015 19:42

4 Martin

Offenbar hat sich ab Apache 2.3.7 etwas beim deflate geändert. Es gehört jetzt zum Modul mod_filter: http://httpd.apache.org/docs/2.4/mod/mod_filter.html#addoutputfilterbytype

Für neuere Versionen wäre es also offenbar so richtig:
# Serverseitige deflate-Komprimierung
<IfModule mod_filter.c>
AddOutputFilterByType DEFLATE text/plain text/html text/xml text/css text/javascript text/rtf
AddOutputFilterByType DEFLATE application/javascript application/x-javascript application/msword
</IfModule>



Martin

06.06.2015 23:58

5 Käptn Blaubär

Zitat von Martin
Offenbar hat sich ab Apache 2.3.7 etwas beim deflate geändert. Es gehört jetzt zum Modul mod_filter: http://httpd.apache.org/docs/2.4/mod/mod_filter.html#addoutputfilterbytype

Nein, mod_filter und mod_deflate sind (auch weiterhin) zwei Module.

Dort steht ja auch:
The following example uses the DEFLATE filter, which is provided by mod_deflate.

Deine beiden Anweisungen funktionieren also nur dann, wenn beide Module verfügbar sind: mod_filter und mod_deflate.

07.06.2015 21:04

6 Jörg Kruse

Also lediglich bei Rewrites (auch Redirects?) ist es wirklich wichtig

Die Redirect Direktive ist Teil von mod_alias. Wenn eine htaccess Datei bereits mod_rewrite Rules enthält, würde ich auch alle Weiterleitungen mit mod_rewrite realisieren. Redirects und RewriteRules lassen sich schlecht miteinander kombinieren.

Eine Änderung in Apache 2.4 betrifft noch die Zugangskontrolle, siehe auf der Upgrading-Seite unter "Access control":

http://httpd.apache.org/docs/2.4/upgrading.html#run-time

Die beiden ersten Blöcke deiner htaccess Datei müssen dann entsprechend angepasst werden, sofern nicht mod_access_compat aktiviert ist.

08.06.2015 09:33 | geändert: 08.06.2015 09:34

7 Martin

Als ich meine .htaccess schrittweise angepasst habe, habe ich zunächst nur den Zugang für die beiden "deny-Blöcke" auf "Require all denied" geändert (neu in Apache 2.4).

Das hat funktioniert.

Dann habe ich als Zweites nur das Browser-Caching ergänzt und bekam "500 Scriptfehler". Ohne diesen Code funktioniert es wieder.

Was soll hier falsch sein:

# Browser-Caching 
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/x-icon "access plus 1 year"
ExpiresByType image/jpg image/jpeg image/gif image/png "access plus 1 month"
ExpiresByType video/mp4 audio/mpeg audio/mp4 "access plus 1 month"
ExpiresByType text/css text/rtf text/javascript "access plus 2 weeks"
ExpiresByType application/pdf application/zip application/msword "access plus 1 month"
ExpiresByType application/javascript application/x-javascript "access plus 2 weeks"
</IfModule>

Die default-Zeile ist nicht zwingend, an der kann es nicht liegen.

Martin

08.06.2015 15:14

8 Martin

Hat sich aufgeklärt: Für jeden MIME-Typ muss eine eigene Zeile erstellt werden.

Jetzt bleibt noch eine Sache bei der deflate-Komprimierung offen, die - wie hier vorgeschlagen - dank Angabe beider Module zwar grundsätzlich funktioniert.

Es bleibt aber laut Pagespeed, dem Online-Tool von Google, als Einziges eine bestimmte JS-Datei außen vor, die nicht komprimiert wird, obwohl ich alle relevanten MIME-Typen für JavaScript angegeben habe:
application/javascript, application/x-javascript und text/javascript.

Die nicht erfasste Datei lautet ".../themes/headway/library/blocks/navigation/js/selectnav.js?ver=4.2.2" und scheint mit dem Navigationsblock des Themes zu tun zu haben.
Warum wird sie wohl nicht erfasst?

Martin

08.06.2015 20:13

9 Jörg Kruse

Zur Analyse würde ich die Datei direkt im Browser aufrufen und mir die HTTP-Header anzeigen lassen. Für letztes gibt es Addons, für Firefox beispielsweise "Live HTTP Headers", oder auch Seiten wie diese:

http://viewdns.info/httpheaders/

09.06.2015 10:25

10 Martin

Wenn ich die Datei direkt aufrufe im Browser, wird mir der Code angezeigt.
Dann gehe ich im FF auf "Extras - Web-Entwicker - Netzwerkanalyse"

Ich lade die Seite nochmal neu und bekomme dann eine Zeile mit Basisinfos. Klicke ich auf die Zeile, erhalte ich detaillierte Head-Daten:

Content-Encoding: gzip
Conten-Type: application/javascript (dieser steht explizit in der .htaccess)
...
Accept-Encoding: gzip, deflate

Das sieht so aus, als ob das ganz normal komprimiert würde, oder?
Offenbar macht PageSpeed einen Fehler und erkennt die Komprimierung bei dieser Datei nicht...


Mein Theme gäbe mir übrigens die Möglichkeit, die Versions-Variablen "?ver=4.2.2" bei solchen JS- und CSS-Dateien (insgesamt acht) wegzulassen. Das soll gut fürs Cachen bzw. Ladezeit sein.

Bei einer Caching (expire)-Zeit von ein oder zwei Wochen wäre das aber wohl keine gute Idee, weil bei neuen Versionen dann einige Rückkehr-Besucher die gecachten Dateien laden. Macht so eine Option dann nur Sinn, wenn man extrem kurze expire-Times festlegt?

Martin

09.06.2015 16:04