• Ich habe heute das seltsamste Caching-Verhalten eines Browsers dennje erlebt.

    Ich lade eine Hauptseite, die ein Last-Modified mitgibt. Über einen Link gehe ich in eine Unterseite, die dasselbe Last-Modified mitgibt und springe über einen Link wieder zurück. Das Ganze wiederhole ich mehrmals.

    Nun würde man davon ausgehen, dass folgendes passiert:

    • Browser: GET Hauptseite
    • Webserver: 200, da hast du! Last-Modified vor ’ner Stunde.
    • Browser: Ah, super, die nehm ich mal in den Cache.
    • User: Dann klick’ ich mal auf den Link für die Unterseite.
    • Browser: GET Unterseite
    • Webserver: 200, da hast du! Last-Modified vor ’ner Stunde.
    • Browser: Guck an, die nehme ich wieder in den Cache.
    • User: Dann klick ich mal auf den Link für die Hauptseite.
    • Browser: GET Hauptseite, aber nur If-Modified-Since vor ’ner Stunde.
    • Webserver: 304, da hat sich nichts verändert.
    • Browser: Alles klar, dann nehm ich meine Version von eben.
    • User: Ich klicke jetzt wieder auf die Unterseite.
    • Browser: GET Unterseite, aber nur If-Modified-Since vor ’ner Stunde.
    • Webserver: 304, da hat sich auch nichts verändert.
    • … das sollte sich jetzt mit vielen 304s des Servers wiederholen, solange nichts geändert wird.

    Was macht der IE11? Solange ich auf keiner Seite explizit F5 mache, fragt er den Webserver nicht mal mehr, ob eine neue Version der Seite vorliegt. Kein Request! Der IE11 sieht ein 304 vorher wie ein Wahrsager (inkl. mit der Wahrsagern nachgesagten Erfolgsquote).

    Ist da irgendwo eine Fehlkonfiguration? Ist das ein Bug? Oder ist das tatsächlich die Mentalität der IE-Entwickler? Ich kann’s eigentlich kaum glauben, wie man etwas so Fundamentales so fundamental verkacken kann. Ich hab schon von Workarounds gelesen à la ›immer negatives Expiration-Datum mitgeben‹. Muss ich jetzt noch OVER 9000 weitere Header-Zeilen (gibt ja auch noch ETags und Caching-Direktiven) mitgeben, nur damit der IE annähernd wie ein Browser funktioniert?

    • • • – • – – • – –


  • wenn es nicht die einstellung ist, dann weiß ich es auch nicht

    (•) Automatisch


    Willkommen in der IE-Freakshow.

    Schickst du ein Cache-Control: must-revalidate mit?

    Nein, bislang habe ich noch nicht alle Variationen der Caching-Direktiven ausprobiert. Ich denke, das werde ich mal tun müssen.

    • • • – • – – • – –


  • Ist da irgendwo eine Fehlkonfiguration? Ist das ein Bug? Oder ist das tatsächlich die Mentalität der IE-Entwickler? Ich kann’s eigentlich kaum glauben, wie man etwas so Fundamentales so fundamental verkacken kann. Ich hab schon von Workarounds gelesen à la ›immer negatives Expiration-Datum mitgeben‹. Muss ich jetzt noch OVER 9000 weitere Header-Zeilen (gibt ja auch noch ETags und Caching-Direktiven) mitgeben, nur damit der IE annähernd wie ein Browser funktioniert?


    Das ist komplett legitimes Verhalten. Solange du nicht "Cache-Control: no-cache" o.ä. ähnliche Header gesetzt hast, darf der Browser gecachte Requests ohne Revalidierung aus dem Cache präsentieren.

    Das Google Stichwort hier ist Freshness & Stale Responses, das HTTP RFC hat da mehr Informationen. Grundsätzlich gilt, dass wenn du keine Cache-Control-Header angibst, dass der Browser dann Heuristiken anwenden darf um zu bestimmen ob ne Seite Stale ist oder nicht. Solange eine Seite nicht Stale ist, muss der Browser auch nicht mit If-Modified-Since o.ä. revalidieren.

    Wäre auch ziemlich dämlich jedes Mal 100ms Latenz mit Revalidierung zu verschwenden, nur um es dann trotzdem aus dem Cache anzuzeigen. Der Zeitverschwender ist ja heutzutage die Latenz, nicht die Bandbreite.

    Caching ist ein unheimlich komplexes Problem. Der HTTP-Caching-Standard ist ziemlich genial in der Hinsicht, aber er funktioniert halt anders als die meisten das erwarten. Ich hatte bisher leider auch nie die Zeit und Musse mich da wirklich einzulesen, so dass ich keine direkte Empfehlung aussprechen könnte. Spontan glaube ich aber, dass du entweder must-revalidate mit max-age oder gleich no-cache haben willst.

    Nachtrag: Nach etwas durchscrollen glaube ich schon, dass hier ne Heuristik anschlägt.

    Code
    If the response has a Last-Modified header field (Section 2.2 of
       [RFC7232]), caches are encouraged to use a heuristic expiration value
       that is no more than some fraction of the interval since that time.
       A typical setting of this fraction might be 10%.

    Wenn dir das nicht passt, musst du eine explizite Freshness-Angabe machen, mit Cache-Control max-age oder Expires.

    Einmal editiert, zuletzt von gandro (28. April 2015 um 10:49)

  • Ich gebe jetzt wie in Quelle empfohlen Cache-Control: private, must-revalidate, max-age=1 und Expires: -1 mit und es scheint zu funktionieren.


    Der HTTP-Caching-Standard ist ziemlich genial in der Hinsicht, aber er funktioniert halt anders als die meisten das erwarten.

    Das unerwartete Verhalten ist für mich eher der Beweis, dass der Standard nicht genial ist. Was nützt ein Standard, der einige Fälle genau definiert und andere Fälle mit »Macht, was ihr wollt!« abspeist? Heuristik! In einem Standard! Das mag jetzt durch die Möglichkeit, darauf Einfluss zu nehmen, legitimiert werden, aber es bleibt mindestens denkwürdig.

    Ich weiß gerade gar nicht, was mich mehr stört: Das uneinheitliche Verhalten der Browser, die schwammigen Passagen aus dem Standard oder mal wieder allgemein der ganze, unübersichtliche HTTP/1.1-Bloat. Ärgernis schränkt wohl Urteilsvermögen ein. Ich komm nochmal drauf zurück.

    • • • – • – – • – –


  • Selbst schuld

    Kann im Unternehmen leider keinen Einfluss drauf nehmen, was da per Policy verteilt wird. Ich glaube aber, dass die anderen Einstellungen auch nicht zum gewünschten Verhalten geführt hätten.

    • • • – • – – • – –

    Einmal editiert, zuletzt von s4ndwichMakeR (28. April 2015 um 11:57)


  • Ich gebe jetzt wie in Quelle empfohlen Cache-Control: private, must-revalidate, max-age=1 und Expires: -1 mit und es scheint zu funktionieren.


    Expires sollte nicht nötig sein wenn du max-age hast. Vermutlich macht das mehr kaputt als es fixt, weil der Browser jetzt von dir widersprüchliche Informationen kriegt (Die Seite ist noch eine Sekunde lang gültig und diese Seite ist schon nicht mehr gültig). Ausserdem bin ich mir nicht sicher, ob Expires:-1 überhaupt gültiges HTTP ist.

    Warum setzt du "private"? Sind es wirklich userspezifische Daten? Mit deinem Problem hat das ja eigentlich nichts zu tun.

  • Das Cache-Control-Gebiet ist #Neuland für mich und Expire hab ich auch noch nicht gebraucht, weil ich mich einfach erstmal über Last-Modified rangetastet habe.

    • • • – • – – • – –

  • Ich glaube am einfachsten willst du schlicht Cache-Control: no-cache. Der Name ist etwas ungünstig gewählt, aber es erzwingt das von dir im Ursprungsbeitrag skizzierte Verhalten - dem Client ist es dann verboten irgendwelche Heuristiken bzw. generell Fresh Content zu verwenden, sondern er muss jedes mal die Revalidierung mit If-Modified-Since o.ä. durchführen.

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!