redaxo / redaxo4

REDAXO 4
https://redaxo.org
41 stars 27 forks source link

Cache-Control Header werden über die .htaccess Datei nicht gesetzt bei Image Manager Bilder #229

Closed ghost closed 10 years ago

ghost commented 10 years ago

Ich habe folgendes bei mir in meiner .htaccess Datei stehen:

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 week"
    ...
    ExpiresByType image/jpg "access plus 1 week"
    ExpiresByType image/jpeg "access plus 1 week"
    ...
</IfModule>

Bei normalen JPEG Bildern wird korrekt folgender Header gesetzt: Cache-Control max-age=604800, public

Bei Bilder aus dem Image Manager wird auf 2 Server aber dieser Header gesetzt: Cache-Control must-revalidate, proxy-revalidate, private

(lokal bei mir passt jedoch alles komischerweise)

Bis jetzt habe ich mir zwar immer mit diesem Patch geholfen, möchte aber endlich wegkommen davon: https://github.com/RexDude/resource_includer/blob/master/install/patch/function_rex_client_cache.inc.php#L137-L143

Hat jemand eine Erklärung wie das sein kann und was man da tun kann? Alternativ: Wäre es nicht sinnvoll einen EP zu haben der aufgerufen wird, nachdem alle Header gesetzt wurden um diese ggf. nochmal manipulieren zu können (dann würde mein Patch wenigstens entfallen), und zwar an dieser Stelle: https://github.com/redaxo/redaxo4/blob/master/redaxo/include/functions/function_rex_client_cache.inc.php#L169

staabm commented 10 years ago

Hi Rudi!

Es ist eine Einstellungssache des Webservers ob er header die vom Skript gesetzt werden überschreiben soll oder nicht. Außerdem kann man im Webserver einstellen welche Einstellungen aus einer .htaccess heraus überhaupt definiert/überschrieben werden dürfen. Kommt also drauf an welchen Webserver du benutzt.

ghost commented 10 years ago

Hi Markus! Danke das wusste ich noch nicht. Aber wie löse ich jetzt konkret mein Problem?

staabm commented 10 years ago

Kommt also drauf an welchen Webserver du benutzt.

;-)

staabm commented 10 years ago

http://httpd.apache.org/docs/current/mod/mod_expires.html#expiresbytype

dort steht Override: Indexes, d.h. in deiner apache config / vhost config muss ein AllowOverride Indexes definiert sein. Im allgemeinen ist übrigens von .htaccess Dateien abzuraten und besser alles direkt im Vhost zu konfigurieren. In Seiten mit sehr viel Traffic schaltet man normalerweise ab, dass Apache nach .htaccess Dateien sucht und diese lädt, da dies unnötiges IO ist.

ghost commented 10 years ago

Dankeschöööön :)

In SelfHTML steht:

Die Anweisung AllowOverride kann nicht innerhalb einer .htaccess notiert werden, sondern wird ausschließlich vom Server-Administrator in der zentralen Konfigurationsdatei vorgegeben.

Und genau das ist das Problem. Ich komme ja als Website-Entwickler der ne neue REDAXO Website auf nen fremden Server hochschiebt gar nicht ran an diese Einstellung :/ Ich brauch also ne Lösung die auf allen Servern funzt so dass auch meine Image Manager Bilder gecacht werden.

staabm commented 10 years ago

AllowOverride kann natürlich nicht in der .htaccess selbst gesetzt werden. Das wäre so, als würde man sich selbst erlauben irgendetwas zu tun ;-). AllowOverride in der Server config definiert was man in einer htaccess tun darf.

Wenn du keinen Zugriff auf die Serverkonfig ist, hast musst du mal den Server support fragen ob sie die AllowOverride Option für Dich setzen.

Wenn wir deinen Patch so in den Core übernehmen würden, würde es trotzdem server geben, die die header des php scripts nicht akzeptieren ;-)

ghost commented 10 years ago

Wenn wir deinen Patch so in den Core übernehmen würden, würde es trotzdem server geben, die die header des php scripts nicht akzeptieren ;-)

Die wären dann aber mies konfiguriert, oder? ;) Da kann man dann wirklich nix machen.

Nein mir geht es nicht darum das ihr den Patch übernehmen, weil der ja auch individuelll ist (bei mir eingestellt auf 1 Woche).

Generell wollte ich halt schauen und verstehen, warum bei Bilder aus dem Image Manager ExpiresByType image/jpg nicht funzt und was man dagegen tun kann.

Als sehr laienhaften Vorschlag könnte ich mir halt einen EP vorstellen, wo ich dann speziell für ($_GET['rex_img_type'] eben den Cache header('Cache-Control: public, max-age=604800'); von Hand drübersetzt. ...und zwar an dieser Stelle: https://github.com/redaxo/redaxo4/blob/master/redaxo/include/functions/function_rex_client_cache.inc.php#L169

Genrell habe ich es hier halt angebracht, weil ja auch andere Leute das Prob haben dürften. D.h. sie setzen ein Cache Header für JPEG Bilder und bei normalen Bildern funzt es aber bei Image Manger Bilder halt nicht ...diese werden wie Html-Dateien behandelt und jedesmal neu heruntergeladen!!

staabm commented 10 years ago

Sollte du nicht im jeweiligen ImageType des ImageManagers diese header() definieren und mitschicken... oft will man ja auch für unterschiedliche Bilder unterschiedliche Header..

ghost commented 10 years ago

Der Übeltäter ist meiner Meinug nach diese Zeile: https://github.com/redaxo/redaxo4/blob/master/redaxo/include/functions/function_rex_client_cache.inc.php#L134

Die ist für Html-Dateien in Ordnung, aber da ja der Image Manager hier auch drüber läuft und es dann eben keine Html Datei mehr ist passt es nicht mehr.

Prinzipiell müsste es fast lauten:

if (isset($_GET['rex_img_type']) || isset($_GET['rex_resize'])) {
  // should be an image file. do nothing. cache control header should be set through .htaccess.
} else {
  // should be a html file. don't cache!
  header('Cache-Control: must-revalidate, proxy-revalidate, private');
}

So jetzt hab ich das gerade getestet und stelle mit erstaunen fest: es wird dann für die Image Manager Bilder gar kein Caching Header gesetzt, obwohl es wegen ExpiresByType image/jpg "access plus 1 week" eigentlich doch lauten müsste: Cache-Control max-age=604800 ???

EDIT: hab meinen letzten Kommentar gelöscht. Lag wohl doch nicht an der session_cache_limiter('none'); :(

gharlan commented 10 years ago

@RexDude Auch wenn dich das jetzt wahrscheinlich nicht wirklich befriedigt, aber zumindest in R5 ist das Caching-Handling schon deutlich verbessert. Ich musste da allerdings recht lange rumtüfteln, und bin mir auch noch nicht ganz sicher, ob es jetzt ganz passt. Jedenfalls bekommen die IM-Bilder dort nicht mehr den Cache-Handler, und Jan hat noch einen neuen "header"-Effekt erstellt, mit dem man unter anderem das Caching pro Bildtyp steuern kann.

session_cache_limiter hat nur Auswirkungen, wenn session_start verwendet wird, was aber ja oft der Fall ist. In R4 wird die Funktion aber glaube ich zu spät aufgerufen (nach session_start), da hat sie gar keine Auswirkung mehr.

So jetzt hab ich das gerade getestet und stelle mit erstaunen fest: es wird dann für die Image Manager Bilder gar kein Caching Header gesetzt, obwohl es wegen ExpiresByType image/jpg "access plus 1 week" eigentlich doch lauten müsste: Cache-Control max-age=604800 ???

Ich bin da jetzt kein Experte, aber falls der Server so konfiguriert ist, dass die .htaccess die Header nicht überschreiben darf, gilt das dann vielleicht auch für "kein Cache-Control"? Weil das ist ja auch eine Aussage, die so gewollt sein kann.

ghost commented 10 years ago

Das klingt schon mal gut für R5, aber ist ja noch ne Weile hin ;)

Also ich fasse jetzt nochmal die Ist-Situation zusammen:

Das hier in der .htaccess:

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 week"
    ...
    ExpiresByType image/jpg "access plus 1 week"
    ExpiresByType image/jpeg "access plus 1 week"
    ...
</IfModule>

liefert bei normalen JPG Bildern korrekt die Header: Cache-Control max-age=604800, public Expires Fri, 15 Nov 2013 14:04:35 GMT

bei Image Manager Bildern: Cache-Control must-revalidate, proxy-revalidate, private ...und kein Expires Header

Nach entfernen dieser Zeile: https://github.com/redaxo/redaxo4/blob/master/redaxo/include/functions/function_rex_client_cache.inc.php#L134 wird gar kein Cache-Control Header mehr angezeigt.

Und nicht mal ExpiresDefault greift hier bei den Image Managern Bildern. Ich versteh das nicht :(

staabm commented 10 years ago

@RexDude du redest jetzt nur von deinem "produktivserver" auf deinem arbeitsrechner geht alles?

ghost commented 10 years ago

Also es sind 2 Produktivserver die sich so verhalten.

Bei meinem lokalen jedoch kommt, eigentlich wie erwartet, das hier für Image Manager Bilder heraus:

Cache-Control must-revalidate, proxy-revalidate, private, max-age=604800 Expires Fri, 15 Nov 2013 14:31:43 GMT

Auch ExpiresDefault greift wenn man ExpiresByType image/jpg weglässt.

staabm commented 10 years ago

ok d.h. prinzipiell gilt auch weiterhin dass du mittels deiner htaccess hier nicht weiterkommst, weil dein server es nicht zulässt.

hast du den anderen vorschlag oben versucht?

Sollte du nicht im jeweiligen ImageType des ImageManagers diese header() definieren und mitschicken... oft will man ja auch für unterschiedliche Bilder unterschiedliche Header..

ghost commented 10 years ago

Ich such ne Lösung wo ich keine Header irgendwo deinieren muss idealerweise. Das wäre doch dann auch nur ein Patch wenn ich dich richtig verstehe...

Ausserdem möchte ich hier darauf Hinweisen das es gut möglich ist, dass Image Manager Bilder nie gecacht werden, selbst wenn man per .htaccess da aber einstellt.

staabm commented 10 years ago

Ich such ne Lösung wo ich keine Header irgendwo deinieren muss idealerweise. Das wäre doch dann auch nur ein Patch wenn ich dich richtig verstehe...

ich meine nicht direkt als "header" sondern eben ein filter im ImageManager der genau solche Dinge tut (cache zeiten festlegen oder eben andere dinge die man via http header machen kann)

Ausserdem möchte ich hier darauf Hinweisen das es gut möglich ist, dass Image Manager Bilder nie gecacht werden, selbst wenn man per .htaccess da aber einstellt.

was meinst du damit?

ghost commented 10 years ago

ich meine nicht direkt als "header" sondern eben ein filter im ImageManager der genau solche Dinge tut (cache zeiten festlegen oder eben andere dinge die man via http header machen kann)

Ist für mich keine befriedigende Lösung. Da kann ich auch bei meinem Patch bleiben ;)

was meinst du damit?

Naja, das REDAXO Websites hier eine Schwachstelle haben (könnten)...was Caching angeht, weil sie Image Manager Bilder immer herunterladen und diese nie gecacht werden. Ist aber nur ne Vermutung momentan, bassierend auf den Erfahrungen die ich mit den 2 Produktivservern gemacht habe.

gharlan commented 10 years ago

Es ist scheinbar richtig, dass in R4 der Client jedesmal die Bilder revalidieren möchte (was der Cache-Header ja auch vorgibt). Hast du USE_ETAG in der master.inc aktiv? Denn dann wird zumindest das Bild nicht jedes mal neu runtergeladen, sondern der Server antwortet dann jeweils mit 304 NOT MODIFIED und der Client nimmt das gecachte Bild.

Optimal ist das trotzdem nicht. Bin mir aber gerade noch nicht ganz sicher, wie dramatisch es ist. Ich weiß nicht, ob ich mich besonders blöd angestellt habe, aber da ich in R5 länger rumtüffteln musste, und immer noch nicht ganz sicher bin, schrecke ich etwas davor zurück, in R4 bei einem Bugfix-Release da jetzt am Verhalten etwas zu ändern, wenn es nicht unbedingt sein muss.

gharlan commented 10 years ago

Kleine Ergänzung: man muss USE_ETAG gar nicht aktivieren, beim IM ist das immer aktiv mit dem 304-Header.

staabm commented 10 years ago

Ist für mich keine befriedigende Lösung. Da kann ich auch bei meinem Patch bleiben ;)

Vorteil dabei wäre dass man es konfigurieren kann pro ImageType und außerdem muss man keinen code patchen (was ein enormer vorteil ist)

ghost commented 10 years ago

@gharlan ich bin auch nur am rumtüfftelt grad wegen dem prob. klar sollte es hier keine große änderung gebn in R4. Aber falls es wirklich ein Bug ist, kann man ja nochmal schauen was man da macht...

@staabm Ok, ich setze per Filter eine Cache-Control Header und dann kommt diese Zeile und überschreibt ihn mir wieder: https://github.com/redaxo/redaxo4/blob/master/redaxo/include/functions/function_rex_client_cache.inc.php#L134 Oder?

ghost commented 10 years ago

Hier ist ein sehr gutes Beispiel mit der Problematik. Ein aktueller REDAXO Liebling: http://www.kelterei-rothenbuecher.de/

Wie man sieht werden hier pro Seitenaufruf (Startseite) 30 Anfragen gechickt....vermutlich weil kein Caching eingestellt ist, owbohl ja CSS/JSS und auch normale Bilder anscheiend gecacht werden (diese werden nicht erneut angefragt). Würde man hier nun Cache-Control einstellen, würde es aber nix bringen, weil....siehe weiter oben :)

gharlan commented 10 years ago

Hmm, bei mir funktioniert das Caching der IM-Bilder auf der Seite teilweise. Sprich: teilweise wird nur die (HTML-)Seite neu geladen, teilweise werden auch die Bilder neu angefragt, dann aber mit 304 beantwortet.

ghost commented 10 years ago

Also bei mir finden immer 31 Anfragen für die Startseite statt. 29 davon sind IM Bilder und kommen mit einem 303 zurück. Immerhin werden sie dann zumindest nicht erneut runtergeladen. Aber die Anfragen bleiben und minimieren ja auch schon die Ladegeschwindigkeit. Googles Pagespeed wäre hier sicherlich nicht glücklich ;)

Wohingegen das statische Bild hier gecacht wird und erstmal auch nicht angefragt wird: http://www.kelterei-rothenbuecher.de/files/bg-default-header.png

staabm commented 10 years ago

Ok, ich setze per Filter eine Cache-Control Header und dann kommt diese Zeile und überschreibt ihn mir wieder: https://github.com/redaxo/redaxo4/blob/master/redaxo/include/functions/function_rex_client_cache.inc.php#L134 Oder?

ich habe nicht gesagt dass es jetzt schon so geht... es ware mehr ein vorschlag wie man es lösen könnte, wenn man es netsprechend vorsieht ;-)

ghost commented 10 years ago

@staabm ach so einer bist du... ;) :D

ghost commented 10 years ago

Interessant. Wenn man die .htaccess vom html5 boilerplate nimmt kommt das dabei raus für ein IM Bild:

Cache-Control max-age=0 Content-Type text/html; charset=iso-8859-1

https://github.com/h5bp/html5-boilerplate/blob/master/.htaccess

Ich bleib dran... :)

staabm commented 10 years ago

Im Boilerplate wird mit Header gearbeitet, du arbeitest mit ExpireByType,... ich meine diese 2 directiven werden von unterschiedlichen Apache Modulen gehandelt.

ghost commented 10 years ago

@staabm https://github.com/h5bp/html5-boilerplate/blob/master/.htaccess#L481 ;)

ghost commented 10 years ago

Was super strange ist: ich setze diese Zeile hier rein Header set X-UA-Compatible "IE=edge" (als einzigste in der .htaccess) und alle CSS/JS/Fonts/Bilder Dateien bekommen diesen Header ausser das Zeug was über die index.php läuft wie halt der REDAXO Artikel und Image Manager Bilder. Wie kann das sein?

ghost commented 10 years ago

Es handelt sich hier übrigens um einen 1&1 Server. Kann es irgendwie sein, dass in der Servekonfig abgestellt wurde das Stuff (oder genauer gesagt Header in dem Fall) für PHP Dateien gesetzt werden dürfen?

staabm commented 10 years ago

vllt http://stackoverflow.com/questions/2139699/set-http-header-for-all-php-scripts-via-htaccess-file ?

ghost commented 10 years ago

funzt leider net. hab das hier probiert:

AddType text/html .php
AddType image/jpg .php
AddType image/jpeg .php

Header set X-UA-Compatible "IE=edge"
ghost commented 10 years ago

Der zweite Server wo das net funzt ist auch 1&1 sehe ich gerade...

ghost commented 10 years ago

Also Jungs...

Das erste Prob, nämlich das die Header für PHP Dateien nicht gesetzt werden, scheint ein 1und1 Problem zu sein. Was mich nur wundert: das hätte doch jemand schon mal merken müssen? Auch über eine Google Suche habe ich nix finden können. Ich habe meine Tests auch isoliert von der REDAXO Umgebung. Immer das gleiche: PHP Dateien bekommen keine Header verpasst. Bei anderen Servern (GN2, DF, WebHostOne) ist das nicht so. Hier verhält sich alles so, wie man es erwartet. Vermutlich müsste ich hier mal den 1und1 Support kontaktieren deswegen wenn sonst hier keiner eine Idee hat an was das Verhalten liegen könnte.

Das zweite Prob is aber die besagte Zeile hier https://github.com/redaxo/redaxo4/blob/master/redaxo/include/functions/function_rex_client_cache.inc.php#L134 die Eben dazu führt, dass auch Image Manager Bilder so einen Cache Header erhalten: Cache-Control must-revalidate, proxy-revalidate, private was dann zu den ständigen Anfragen führt für die IM Bilder (wenn ich das richtig sehe). Und setzt man hier ExpireByType ein (auf einem gescheiten Server ;)) so lautet die Zeile dann: Cache-Control must-revalidate, proxy-revalidate, private, max-age=604800 was eigentlich wiedersprüchlich ist, oder?

Vermutlich wäre deshalb folgender Patch ganz sinnvoll:

if (isset($_GET['rex_img_type']) || isset($_GET['rex_resize'])) {
  // should be an image file. do nothing. cache control header should be set through .htaccess.
} else {
  // should be a html file. don't cache!
  header('Cache-Control: must-revalidate, proxy-revalidate, private');
}

Der Rest liegt nun an euch... ;) Cheers!

ghost commented 10 years ago

Evtl. müsste auch dieses session_cache_limiter('none'); in den else Zweig mit rein, weiss ich aber nicht. Der Wert none scheint hier übrigens auch gar nicht vorzukommen: http://php.net/manual/de/function.session-cache-limiter.php

ghost commented 10 years ago

Ich glaube jetzt die beste Lösung für Prob Nr.2 gefunden zu haben: https://github.com/RexDude/resource_includer/commit/65fdd6c8fd6f16a5d5d1045b848aa9000cc81daf

gharlan commented 10 years ago

Das Problem ist halt, gibt es Addons (oder Templates/Module), die rex_send_file/resource/content verwenden und explizit dieser Header brauchen und darauf vertrauen, dass er gesendet wird? Oder ist das eindeutig als Bug anzusehen?

ghost commented 10 years ago

Wie gesagt: es gibt mMn keine Chance für IM Bilder einen Cache-Control Header zu senden, weder über die .htaccess Datei noch in einem Addon oder per EP. Und das ist für mich definitiv ein Bug, weil ich nicht will das meine IM Bilder den Cache-Control Header von einer Html Datei bekommen, sprich nicht gecacht werden und auch prinzipiell (wenn ich das richtig sehe) immer angefragt werden (siehe weiter oben.)

Ich denke für andere Addons etc. sollte die Änderung keine große Auswirkung haben. die sitemap.xml und robots.txt von SEO42 z.B. läuft eh nicht über rex_send_content und bringt ausserdem ihre eigenen Cache-Control Header mit. Würde diese Dateien aber über rex_send_content laufen würde hier REDAXO wieder die gesetzten Cache-Control Header ändern, wo mit wir wieder beim erwähnten Bug wären ;)