Albert: HTTP HEAD und Last-Modified

Guten Morgen,

für ein größeres Projekt muss ich einen Crawler in Python Programmieren. Dieser Crawler hat die Aufgaben statische HTML Seiten aus dem Internet zu landen.

Die einmal geladenen Seiten sollen regelmäßig auf "noch erreichbar" und "noch aktuell" hin überprüft werden. Um nicht unnötigen Trafic zu verursachen, will ich für das überprüfen die Request-Methode "HEAD" gebrauchen.

Für den Teil "noch erreichbar" wird das ausreichend sein. Was ist aber mit dem Teil "noch aktuell"? Erste Tests haben ergeben das nicht alle Server im HEAD ein "Last-Modified" haben. Leider weiß ich nicht ob das fehlen dieser HEAD Angaben die Regel ist. Wenn dem so währe, welche Alternativen haben ich dann?

Mit freundlichen Grüßen

Albert

  1. Hi,

    Was ist aber mit dem Teil "noch aktuell"? Erste Tests haben ergeben das nicht alle Server im HEAD ein "Last-Modified" haben. Leider weiß ich nicht ob das fehlen dieser HEAD Angaben die Regel ist. Wenn dem so währe, welche Alternativen haben ich dann?

    Es gibt keine andere Alternative, als bei Fehlen diser Angabe den Inhalt anzufordern und auf Änderungen zu überprüfen.
    Üblich ist Last-Modified nur bei statischen Seiten. Dynamisch erstellte Seiten wären ja stets "neu", da der Server nicht wissen kann, wann die letzten Änderungen vorgenommen wurden. Daher müßte der Header mit dieser Angabe schon vom Script generiert werden, was sich die Ersteller meist jedoch sparen - manche machen dies, wohl auch nur, um Suchmaschinen statische Seiten vorzugaukeln.

    freundliche Grüße
    Ingo

  2. Hallo,

    Was ist aber mit dem Teil "noch aktuell"? Erste Tests haben ergeben das nicht alle Server im HEAD ein "Last-Modified" haben. Leider weiß ich nicht ob das fehlen dieser HEAD Angaben die Regel ist. Wenn dem so währe, welche Alternativen haben ich dann?

    (((fast)))¹ alle dynamisch erstellen Dokumente haben diesen Header genauso wenig wie den Header ETag. Dir wird also nichts übrig bleiben, als das Dokument einzulesen und md5/hash eine Prüfung zu unternehmen.

    Gruß aus Berlin!
    eddi

    1. da müßte sich schon ein Programmierer sich mit der Materie über den Tellerrand der eingentlichen Aufgabenstellung hinweg auch mit den Vorteilen, die HTTP zu bieten hat, beschäftigt und implementeirt haben. Das ist nicht -die Ausnahme-, das ist -Die Ausnahme-.
    1. Lieber eddi,

      Das ist nicht -die Ausnahme-, das ist -Die Ausnahme-.

      wie gut, dass ich das gerade lese, denn genau da bin ich gerade dran. Bisher ist in allen meinen Dokumenten im <head> extra mit drei META-Angaben vorgeschrieben, dass sich der Browser unsere Seiten auf keinen Fall merken (cachen) soll. Was ein Unsinn, wenn ich mir überlege, welche Bandbreite damit vergeudet wird. Egal, ob wir nun immer mehr Breitbandanschlüsse haben, oder nicht. Traffic war und ist immernoch teuer. Also implementiere ich das gerde. Muss mir nur noch die genaue Spec reinziehen.

      Liebe Grüße aus Ellwangen,

      Felix Riesterer.

      1. hi,

        Also implementiere ich das gerde. Muss mir nur noch die genaue Spec reinziehen.

        Sonderlich kompliziert ist es eigentlich nicht.

        Als ich mich damit beschäftigt habe, habe ich HTTP Conditional Get for RSS Hackers als Einstieg gewählt - da wird es schon recht gut beschrieben (für RSS-Feeds, aber geht ja bei allen anderen über HTTP abrufbaren Ressourcen analog).

        Besonders der Vorschlag, für den ETAG einfach ebenfalls die Datumszeichenkette zu verwenden, wie man sie im Last-Modified-Header auch verwendet, ist m.E. recht gut - das erspart einem das Hantieren mit irgendwelchen Hashes, wenn man eigentlich nur auf eine eventuelle Aktulisierung in Bezug auf ein bestimmtes Datum bzw. Zeitstempel prüfen will.

        Ein zusätzlicher Blick in den HTTP/1.1-RFC bzgl. If-Modified-Since, If-None-Match, Last-Modified, ETag & Co. sei natürlich ebenfalls empfohlen, um das genaue Funktionsprinzip besser zu verstehen.

        Aber eigentlich ist es wirklich recht simpel.

        gruß,
        wahsaga

        --
        /voodoo.css:
        #GeorgeWBush { position:absolute; bottom:-6ft; }
        1. Lieber wahsaga,

          Sonderlich kompliziert ist es eigentlich nicht.

          nunja, ich habe mich durch die RFCs gelesen und danach meine header-Funktion eingesetzt. Wo bzw. wie kann ich am einfachsten die HTTP-Header auslesen, die unsere Schulhomepage ausgibt? Lohnt sich da der Einsatz eines eigenen Programms, oder kann ich das auf einer dafür ausgelegten Website testen?

          Als ich mich damit beschäftigt habe, habe ich HTTP Conditional Get for RSS Hackers als Einstieg gewählt - da wird es schon recht gut beschrieben (für RSS-Feeds, aber geht ja bei allen anderen über HTTP abrufbaren Ressourcen analog).

          Muss ich vielleicht mal ansehen, aber ich habe mich bisher gegen ein RSS-Feed für unsere Schulwebsite entschieden.

          Besonders der Vorschlag, für den ETAG einfach ebenfalls die Datumszeichenkette zu verwenden, wie man sie im Last-Modified-Header auch verwendet, ist m.E. recht gut - das erspart einem das Hantieren mit irgendwelchen Hashes, wenn man eigentlich nur auf eine eventuelle Aktulisierung in Bezug auf ein bestimmtes Datum bzw. Zeitstempel prüfen will.

          Das E-Tag habe ich in seiner Bedeutung nicht verstanden, da mir die Erläuterungen in den Specs zu unverständlich waren. Aber vielleicht sollte ich es damit nocheinmal probieren...

          Ein zusätzlicher Blick in den HTTP/1.1-RFC bzgl. If-Modified-Since, If-None-Match, Last-Modified, ETag & Co. sei natürlich ebenfalls empfohlen, um das genaue Funktionsprinzip besser zu verstehen.

          Diese Abschnitte hatte ich verstanden und Last-Modified davon umgesetzt. Bei If-Modified-Since und ETag ist mir nicht klar geworden, wofür ich die genau einsetzen sollte, bzw. welche Information ich mit diesen Headern schicken müsste.

          Aber eigentlich ist es wirklich recht simpel.

          Mit dem "eigentlich" gebe ich Dir absolut Recht. Nur im Detail kann es für Unerfahrene etwas komplex erscheinen, oder gar unverständlich klingen.

          Liebe Grüße aus Ellwangen,

          Felix Riesterer.

          1. hi,

            Wo bzw. wie kann ich am einfachsten die HTTP-Header auslesen, die unsere Schulhomepage ausgibt? Lohnt sich da der Einsatz eines eigenen Programms, oder kann ich das auf einer dafür ausgelegten Website testen?

            Im Firefox sind dafür Extensions wie die Web Developer Toolbar (die dürfte doch bei einem Webseitenersteller vermutlich eh zum Standard-Arbeitswerkzeug gehören?) sehr nützlich - da findest du das unter "Information" -> "View Response Headers".

            Und wenn ich gerade keinen Browser zur Verfügung habe, der mir diese Information anzeigen mag, dann nutze ich dafür den Web Sniffer - oder andere ähnliche Tools, wie auch bspw. HTTP trace, und im self-Umfeld gab's sowas glaube ich auch noch irgendwo, finde ich aber gerade nicht.

            Muss ich vielleicht mal ansehen, aber ich habe mich bisher gegen ein RSS-Feed für unsere Schulwebsite entschieden.

            Wie gesagt, war nur als Beispiel gedacht, und ist ja nicht auf RSS beschränkt, sondern erklärt das Thema eigentlich generell für HTTP-Ressourcen, egal ob nun RSS oder HTML-Dokument.

            Das E-Tag habe ich in seiner Bedeutung nicht verstanden, da mir die Erläuterungen in den Specs zu unverständlich waren.

            Ich muss gestehen, ich auch nicht :-)
            ETag dient wohl mehr dazu, mehrere Entitäten, also Ausprägungen o.ä., einer Ressource zu unterscheiden.
            Das _kann_ wohl auch zur Bewertung der Aktualität der Ressource bzgl. des aktuellen Timestamps dienen, wie im vorliegenden Falle, wenn man eigentlich eine 304 Not Modified-Antwort umsetzen will - es gibt aber wohl noch andere Einsatzgebiete.

            Manche Clients benutzen den Last-Modified-Header, um darauf hin bei der erneuten Anfrage ein If-Modified-Since zu generieren, um zu erfragen, ob sich die Ressource inzwischen gegenüber der gechachten Version verändert hat - manche Clients aber wohl auch den ETag.
            Da wollte ich eigentlich bei Gelegenheit noch mal im Forum nachfragen, wie das mit dem ETag im speziellen aussieht - und ob man ihn implementieren sollte für so eine 304-Sache.
            Bei meinen Tests funktionierte es bei allen Clients mit dem Last-Modified/If-Modified-Since-Gespan - ETag ebenfalls zu implementieren, kann man sich da also u.U. sparen.

            Diese Abschnitte hatte ich verstanden und Last-Modified davon umgesetzt. Bei If-Modified-Since und ETag ist mir nicht klar geworden, wofür ich die genau einsetzen sollte, bzw. welche Information ich mit diesen Headern schicken müsste.

            Last-Modified generierst du beim Ausliefern der Ressource als Response-Header, und If-Modified-Since liefert dir der Client bei einer erneuten Anfrage im Request, wenn er sich erkundigen will, ob er seine gechachte Version weiterhin verwenden, oder die Ressource erneut abrufen soll.
            Hat sich die Ressource zwischenzeitlich - was du anhand der als "Wert" des Request-Headers übermittelten Datumsangabe entscheidest - nicht geändert, antwortest du nur mit einem 304-Header (ohne einen "Body")- andernfalls lieferst du die Ressource wie gewohnt unter einem (üblicherweise) 200-Header aus.
            Will sich der Client damit nicht zufriedengeben, dass du ihm gesagt hast, es habe sich nichts geändert, und er will wirklich die Ressource erneut anfordern, egal ob sie sich mit der Version in seinem Cache deckt - dann wird er eine erneute Anfrage ohne If-Modified-Since stellen - die du dann ganz normal mit Auslieferung der Ressource beantwortest.

            Und ETag, siehe oben - braucht man dafür nach meinem bisherigen Kenntnisstand nicht.

            Kann auch sein, dass das ein Thema bzgl. der Unterschiede zwischen HTTP/1.0 und HTTP/1.1 ist - wie gesagt, vollkommen durchschaut habe ich den Einsatzzweck von ETag auch noch nicht.

            Aber eigentlich ist es wirklich recht simpel.
            Mit dem "eigentlich" gebe ich Dir absolut Recht. Nur im Detail kann es für Unerfahrene etwas komplex erscheinen, oder gar unverständlich klingen.

            Sicher - aber sich damit zu beschäftigen, macht ja auch Spaß, oder?

            gruß,
            wahsaga

            --
            /voodoo.css:
            #GeorgeWBush { position:absolute; bottom:-6ft; }
            1. Lieber wahsaga,

              Im Firefox sind dafür Extensions wie die Web Developer Toolbar (die dürfte doch bei einem Webseitenersteller vermutlich eh zum Standard-Arbeitswerkzeug gehören?) sehr nützlich - da findest du das unter "Information" -> "View Response Headers".

              diese Erweiterung hatte ich bisher nicht... Aber diese Versäumnis habe ich sofort nachgeholt!

              Das E-Tag habe ich in seiner Bedeutung nicht verstanden, da mir die Erläuterungen in den Specs zu unverständlich waren.

              Ich muss gestehen, ich auch nicht :-)

              Wunderbar! Dann fühle ich meine Ehre (als Englisch-Lehrer!) wieder hergestellt, wenn selbst SELFHTML-Devs damit Schwierigkeiten haben. :-)

              ETag dient wohl mehr dazu, mehrere Entitäten, also Ausprägungen o.ä., einer Ressource zu unterscheiden.

              Also Bahnhof mit Bratkartoffeln? "Entitäten" sind mir bei Markup (XML) begegnet... Aber in HTTP-Meldungen? Vielleicht muss ich das aber nicht alles wissen und verstehen, solange ich die notwendigen Header ausliefere. Das würde mein Hirn sehr erleichtern!

              Bei meinen Tests funktionierte es bei allen Clients mit dem Last-Modified/If-Modified-Since-Gespan - ETag ebenfalls zu implementieren, kann man sich da also u.U. sparen.

              Das hört sich doch nach einem praxisorientierten Ratschlag an! Werde mich demnächst genauer mit meinen Headern befassen. Zunächst genügt es mir, dass "Last-Modified" mitgeliefert wird (neben Content-Type).

              [...] If-Modified-Since liefert dir der Client bei einer erneuten Anfrage im Request, wenn er sich erkundigen will, ob er seine gechachte Version weiterhin verwenden, oder die Ressource erneut abrufen soll.

              Auf diesen Fall gehe ich (noch) nicht ein. ist aber geplant. Schließlich will ich ja mit gutem Beispiel für Schul-Homepages vorangehen. ;-)

              Sicher - aber sich damit zu beschäftigen, macht ja auch Spaß, oder?

              Stimmt. Dabei habe ich gesehen, dass entweder mein Firefox, oder aber unser Webserver seiner Zeit vorraus ist: Bei Rechtsklick -> "Seiteninformationen anzeigen" liefert mir mein Browser eine Uhrzeit, die meine Funkuhr nicht bestätigen kann... Test gefällig?

              Liebe Grüße aus Ellwangen,

              Felix Riesterer.

              1. Nachtrag,

                ein Test ergab, dass ich wohl nicht den Unix-Timestamp direkt in den Last-Modified-Header setzen darf, oder wie erkläre ich mir die verschiedenen Angaben?

                Webseite hat eine Debug-Ausgabe:

                $last_modified = filemtime($meine_datei);  
                echo "last Modified: ".date('d - M - Y, H:i:s', $last_modified);
                

                Den Last-Modified-Header gebe ich so aus:
                header('Last-Modified: '.$last_modified);

                Warum sagt mir dann der Firefox unter Seiteninformationen etwas so völlig anderes, als die Debug-Ausgabe? Der Internet-Explorer sagt unter Datei-> Eigenschaften etwas nocheinmal anderes (auch unbrauchbar).

                Habe ich da einen Header vergessen, der das tatsächliche Alter der Datei angibt? Oder ist der völlig unerheblich?

                Liebe Grüße aus Ellwangen,

                Felix Riesterer.

                1. Hallo,

                  ein Test ergab, dass ich wohl nicht den Unix-Timestamp direkt in den Last-Modified-Header setzen darf

                  Wie kommst du darauf, dass du es könntest?

                  http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.29
                  http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1

                  Nimm also ein Datum gemäß RFC 1123, z.B. 'D, d M Y H:i:s \G\M\T'.

                  Mathias

                  1. Lieber Mathias,

                    ein Test ergab, dass ich wohl nicht den Unix-Timestamp direkt in den Last-Modified-Header setzen darf

                    Wie kommst du darauf, dass du es könntest?

                    http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.29
                    http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1

                    tja, da habe ich beim Lesen nicht wirklich mitgedacht. ;-) Wird sofort korrigiert!

                    Danke!

                    Liebe Grüße aus Ellwangen,

                    Felix Riesterer.

              2. hi,

                Wunderbar! Dann fühle ich meine Ehre (als Englisch-Lehrer!) wieder hergestellt, wenn selbst SELFHTML-Devs damit Schwierigkeiten haben. :-)

                Ich nix Dev, ich hier nur Putzen ...

                ETag dient wohl mehr dazu, mehrere Entitäten, also Ausprägungen o.ä., einer Ressource zu unterscheiden.
                Also Bahnhof mit Bratkartoffeln? "Entitäten" sind mir bei Markup (XML) begegnet... Aber in HTTP-Meldungen?

                Wie gesagt, ich würde Entity hier mit "Ausprägung" o.ä. zu übersetzen versuchen. "Dateneinheit", "Funktionseinheit" oder "Instanz" kämen laut dict.leo.org ebenfalls noch in Frage.

                Vielleicht muss ich das aber nicht alles wissen und verstehen, solange ich die notwendigen Header ausliefere. Das würde mein Hirn sehr erleichtern!

                Für die Umsetzung einer 304-Antwort bei nicht veränderten dynamischen Daten wie gesagt m.E. nicht, da reicht die Last-Modified-Geschichte wohl aus.

                [...] If-Modified-Since liefert dir der Client bei einer erneuten Anfrage im Request, wenn er sich erkundigen will, ob er seine gechachte Version weiterhin verwenden, oder die Ressource erneut abrufen soll.
                Auf diesen Fall gehe ich (noch) nicht ein. ist aber geplant.

                Aber das ist doch der eigentliche Sinn und Zweck hinter der Sache?
                Wozu willst du Last-Modified einsetzen, wenn nicht zur Steuerung des Caching-Verhaltens?

                gruß,
                wahsaga

                --
                /voodoo.css:
                #GeorgeWBush { position:absolute; bottom:-6ft; }
                1. Lieber wahsaga,

                  Ich nix Dev, ich hier nur Putzen ...

                  :-) Aha. Und was Du putzen? Böse FONT-Tags? Sorry, wenn ich meine hohe Meinung von Dir so ungeprüft durch Behauptung falscher Tatsachen zum Ausdruck gebracht habe. ;-)

                  [...] If-Modified-Since liefert dir der Client bei einer erneuten Anfrage im Request, wenn er sich erkundigen will, ob er seine gechachte Version weiterhin verwenden, oder die Ressource erneut abrufen soll.
                  Auf diesen Fall gehe ich (noch) nicht ein. ist aber geplant.

                  HA! Auf diesen Fall _gehe_ ich inzwischen ein. Jawohl!

                  Aber das ist doch der eigentliche Sinn und Zweck hinter der Sache?
                  Wozu willst du Last-Modified einsetzen, wenn nicht zur Steuerung des Caching-Verhaltens?

                  Tja, wenn das so klappen würde, wie ich mir das vorgestellt habe...

                  Unsere Schulhomepage besteht im Prinzip aus statischen Seiten, welche aber dynamisch um diverse Elemente ergänzt (z.B. Navigation) ausgeliefert werden. Deshalb möchte ich, dass bei einer Änderung der globalen Navi (deren Änderung ja automatisch jede Seite betrifft) eine Seite auch als "modified" betrachtet wird. Mein Script schafft das auch, aber den Browser kümmert seit dem Fehlen der strengen "Nicht cachen!"-Metatags nicht mehr, ob sich das Dokument inzwischen vielleicht geändert haben könnte, und fragt nur noch seinen Cache.

                  Welchen Header müsste ich da jetzt genau verwenden, damit der Browser jedesmal einen If-Modified-Since bzw. If-None-Match durchführt? Oder ist exakt dieses Verhalten eine User-Einstellung?

                  Mein letzter Versuch war eine Kombination aus "Expires" (mit _derselben_ Datumsangabe wie im "Last-Modified") und "must-revalidate". Die Header scheinen auch korrekt zu arbeiten, jedoch wollen weder mein FF, noch meine IEs davon etwas wissen. :-(

                  Liebe Grüße aus Ellwangen,

                  Felix Riesterer.

                  1. Hi,

                    Welchen Header müsste ich da jetzt genau verwenden, damit der Browser jedesmal einen If-Modified-Since bzw. If-None-Match durchführt? Oder ist exakt dieses Verhalten eine User-Einstellung?

                    Nach meiner Erfahrung macht das der Browser immer dann, wenn er auch einen Last-Modified- bzw. einen ETag-Header bekommen hat! Entweder oder, bzw. ggf. auch beides - es sei denn, der User hat den Browser so konfiguriert, daß der sich gleich aus dem Cache bedient. :)

                    Gruß, Cybaer

                    --
                    Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!
                    1. Lieber Cybaer,

                      Nach meiner Erfahrung macht das der Browser immer dann, wenn er auch einen Last-Modified- bzw. einen ETag-Header bekommen hat! Entweder oder, bzw. ggf. auch beides - es sei denn, der User hat den Browser so konfiguriert, daß der sich gleich aus dem Cache bedient. :)

                      und warum prüft mein Firefox nicht auf Aktualität des Dokuments? Ich dachte Deinen Ausführungen zu entsprechen...

                      Falls Du selbst einmal meine Header testen möchtest, wäre ich dankbar, wenn Du die Ursache für diese Ignoranz des FF fändest. Ich finde sie nicht. Opera prüft übrigens anscheinend anständig nach. IE frage ich nicht, der macht mit dem Caching eh, was er will.

                      Liebe Grüße aus Ellwangen,

                      Felix Riesterer.

                      1. Hi,

                        Falls Du selbst einmal meine Header testen möchtest, wäre ich dankbar, wenn Du die Ursache für diese Ignoranz des FF fändest.

                        Ich denke nicht, daß ich das von hier aus kann. =:-)

                        Aber ich konnte feststellen, daß dein Script zumindest an einer Stelle verbesserungswürdig ist: Mir scheint es, Du fragst ab, ob der Browser einen If-Modified-Since-Header schickt und lieferst dann einen 304er aus. Aber Du lieferst auch einen 304er aus, wenn das Datum gar nicht paßt - Hauptsache Header. =;-)

                        Du solltest schon abfragen, ob die Daten auf dem Server ein *neueres* Datum tragen, als vom Client abgefragt. Wenn der Client einen "alten" Timestamp schickt, und das Script antwortet *immer* mit "OK, hast Du schon", dann erscheint mir das ein wenig übertrieben. ;->

                        Gruß, Cybaer

                        --
                        Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!
                        1. Lieber Cybaer,

                          Aber ich konnte feststellen, daß dein Script zumindest an einer Stelle verbesserungswürdig ist: Mir scheint es, Du fragst ab, ob der Browser einen If-Modified-Since-Header schickt und lieferst dann einen 304er aus. Aber Du lieferst auch einen 304er aus, wenn das Datum gar nicht paßt - Hauptsache Header. =;-)

                          Nunja, ich war etwas zu bequem, die Zeitangabe in einen Timestamp umrechnen zu lassen, um dann sicher überprüfen zu können, ob der übertragene Timestamp veraltet, aktuell oder gar neuer ist, als der Timestamp der Daten auf dem Server. In dem Moment, wo die Timestamps _nicht_ übereinstimmen, ist das Dokument im Cache entweder veraltet, oder es hat einen ohnehin ungültigen Timestamp, und damit bekommt der Browser das komplette Dokument übermittelt.

                          Du solltest schon abfragen, ob die Daten auf dem Server ein *neueres* Datum tragen, als vom Client abgefragt. Wenn der Client einen "alten" Timestamp schickt, und das Script antwortet *immer* mit "OK, hast Du schon", dann erscheint mir das ein wenig übertrieben. ;->

                          Asche auf mein Haupt! Ich hatte eine IF-Bedingung mit "!=" anstatt mit "==" gestellt... klar, dass dabei Mist herauskommt, da sie damit genau das Gegenteil bewirkt. Mit diesem Denkfehler hat der Server nur bei übereinstimmendem Timestamp das Dokument neu ausgeliefert, bei unterschiedlichem Timestamp aber nicht, was ja gerade keinen Sinn hat. Oh, oh, oh! Habe schon eine ganz matschige Birne wegen dieser ganzen Headerei.

                          Liebe Grüße aus Ellwangen,

                          Felix Riesterer.

                      2. Hallo Felix,

                        nun habe ich zwar nicht wirklich Ahnung von dem ganzen Haederkram, mir kamen
                        beim bei deinem Response-Header doch ein paar Fragen?

                        Date: Tue, 11 Apr 2006 17:08:01 GMT

                        Also ausgeliefert um 17:08:01 GMT.

                        Last-Modified: Tue, 11 Apr 2006 17:10:36 GMT

                        Und über zwei Minuten _danach_ geändert?
                        (Ich würde da ganz schön durcheinanderkommen)

                        Expires: Tue, 11 Apr 2006 17:10:36 GMT

                        Also noch zwei Minuten gültig?
                        Warum soll mein Browser dann überhaupt nachfragen?

                        Cache-Control: must-revalidate

                        Der Browser soll sich also strikt daran halten, erst in zwei Minuten zu
                        revalidieren?
                        Wäre da vielleicht auch noch ein Zeitraum sinnvoll (z.B. jede Stunde)?
                        Cache-Control: max-age=3600, must-revalidate

                        Auf Wiederlesen
                        Detlef

                        --
                        - Wissen ist gut
                        - Können ist besser
                        - aber das Beste und Interessanteste ist der Weg dahin!
                        1. Lieber Detlef,

                          Date: Tue, 11 Apr 2006 17:08:01 GMT
                          Also ausgeliefert um 17:08:01 GMT.
                          Last-Modified: Tue, 11 Apr 2006 17:10:36 GMT
                          Und über zwei Minuten _danach_ geändert?
                          (Ich würde da ganz schön durcheinanderkommen)

                          Ich auch. Aber der Server hat bei seinen Werten für filemtime() anscheinend eine andere Zeit (die in der Zukunft zu liegen scheint), als beim Senden der aktuellen Serverzeit. Mir ist das auch nicht ganz klar, aber das muss den Cache-Mechanismus ja nicht unbedingt durcheinanderbringen.

                          Der Browser soll sich also strikt daran halten, erst in zwei Minuten zu
                          revalidieren?
                          Wäre da vielleicht auch noch ein Zeitraum sinnvoll (z.B. jede Stunde)?
                          Cache-Control: max-age=3600, must-revalidate

                          Diesen Vorschlag habe ich in mein Script aufgenommen. Danke!

                          Liebe Grüße aus Ellwangen,

                          Felix Riesterer.

                          1. Hallo Felix,

                            aus deinem aktuellen Header:

                            Expires: Tue, 18 Apr 2006 21:28:08 GMT

                            Hiernach ist die Seite bis zum 18 April gültig, es soll also erst danach
                            kontrolliert werden, ob Seite noch aktuell ist.

                            Cache-Control: max-age=0, must-revalidate

                            ^
                            Hiernach verfällt die Seite schon bei Auslieferung.

                            Was denn nun, gültig bis zum 18 April oder sofort wieder ungültig?
                            Ich weiß nicht, welche Angabe Priorität hat, oder welcher Useragent welcher
                            Angabe die Priorität gibt.

                            Zumindest wirkt es auf mich etwas befremdlich, dass die Seite schon ungültig
                            sein soll, wenn mein Browser sie lädt.

                            Auf Wiederlesen
                            Detlef

                            --
                            - Wissen ist gut
                            - Können ist besser
                            - aber das Beste und Interessanteste ist der Weg dahin!
                            1. Lieber Detlef,

                              Expires: Tue, 18 Apr 2006 21:28:08 GMT
                              Cache-Control: max-age=0, must-revalidate
                                                        ^
                              Hiernach verfällt die Seite schon bei Auslieferung.

                              Was denn nun, gültig bis zum 18 April oder sofort wieder ungültig?
                              Zumindest wirkt es auf mich etwas befremdlich, dass die Seite schon ungültig
                              sein soll, wenn mein Browser sie lädt.

                              meine Vorstellung (und sicherlich auch mangelndes Verständnis der Specs) ist folgende:
                              "Seite gültig bis xyz" soll den Browser veranlassen, nur auf "if-modified-since" zu prüfen, um im Falle das Dokument neu zu laden. Kein Server kann verlässlich wissen, wie lange ein Dokument tatsächlich gültig ist, er kann nur raten/schätzen.
                              "max-age" soll den Browser eine Weile lang zufrieden stellen und die Prüfung auf "if-modified-since" erst nach Erreichen des "max-age" wieder auslösen.

                              Liebe Grüße aus Ellwangen,

                              Felix Riesterer.

                              1. Hallo Felix

                                "Seite gültig bis xyz" soll den Browser veranlassen, nur auf "if-modified-since" zu prüfen, um im Falle das Dokument neu zu laden.

                                ... wenn die Seite laut dieser Angabe nichtmehr gültig ist!

                                Kein Server kann verlässlich wissen, wie lange ein Dokument tatsächlich gültig ist, er kann nur raten/schätzen.

                                Deshalb wird vom Server auch standardmäßig auch kein "Expires" gesendet.
                                (zumindest nicht bei denen auf dem meine statischen Seiten liegen)
                                Wenn du dies aber extra setzt, kann man (bzw. Browser und Proxis) ja davon
                                ausgehen, dass du weißt, was du tust.

                                "max-age" soll den Browser eine Weile lang zufrieden stellen und die Prüfung auf "if-modified-since" erst nach Erreichen des "max-age" wieder auslösen.

                                Ja, genauso, wie "Expires". Ob ich festlege, "Seite gültig bis Zeitpunkt",
                                oder "Seite gültig für Zeitspanne", ist nur eine andere Form der selben
                                Aussage.

                                Und "must-revalidate" weist den Cache an, sich strict an diese Angaben zu
                                halten und keine eigenen Schätzungen darüber anzustellen, ob die Seite
                                wohl noch gültig ist, also beim Fehlen von "Expires" und "max-age" bei jeder
                                Anfrage zu prüfen.

                                Wenn du also willst, dass bei _jedem_ Aufruf geprüft wird, darfst du weder
                                "Expires" noch "max-age" angeben.
                                Was ich allerdings nur bei einer Seite, die sich wirklich im Sekundentakt
                                ändert, eventuell sinnvoll halten würde.

                                Auf Wiederlesen
                                Detlef

                                --
                                - Wissen ist gut
                                - Können ist besser
                                - aber das Beste und Interessanteste ist der Weg dahin!
                                1. Lieber Detlef,

                                  Wenn du also willst, dass bei _jedem_ Aufruf geprüft wird, darfst du weder
                                  "Expires" noch "max-age" angeben.
                                  Was ich allerdings nur bei einer Seite, die sich wirklich im Sekundentakt
                                  ändert, eventuell sinnvoll halten würde.

                                  Tja, was soll ich da sagen! Manche unserer Seiten ändern sich seit dem einige Sekunden zurückliegenden Aufruf, wie z.B. unsere Gästebuch-Seite. Nach der Eintragung soll ja die GB-Seite wieder angezeigt werden, um den neu hinzugekommenen Eintrag im Kontext der bisherigen Einträge anzuzeigen. Das bedeutet, dass sich seit dem letzten Aufruf von wenigen Momenten (die Zeitspanne des Verfassens der neuen Eintragung) diese Seite tatsächlich verändert hat. Um diese aktualisierte Version der Seite anzeigen zu können, soll der Browser eben auf if-modified-since prüfen.

                                  Wenn ich nun den Prüf- und Cache-Mechanismus extra trennen soll, sodass für die GB-Seite konzeptionell ein früheres Verfallsdatum (oder eben ein Fehlen eines solchen) eingerichtet werden soll, als es für die anderen (eher statischen) Seiten gilt, dann denke ich, dass ich dann doch übertreibe. Da unsere Seite nicht im Sekundentakt immer wieder angefordert wird, denke ich, dass eine regelmäßige Prüfung auf Aktualisierung durchaus zu vertreten und sinnvoll ist. Ich kann ja nicht wissen, wann an einer Seite jemand ein Update vorgenommen hat, aber ich möchte, dass dieser Jemand diese Veränderungen in seinem Browser sofort sehen kann, denn sonst erhalte ich Beschwerden, dass die Homepage wieder einmal nicht tue... ;-)

                                  Liebe Grüße aus Ellwangen,

                                  Felix Riesterer.

                          2. Hi,

                            Aber der Server hat bei seinen Werten für filemtime() anscheinend eine andere Zeit (die in der Zukunft zu liegen scheint), als beim Senden der aktuellen Serverzeit.

                            Hmm, aber Du benutzt für den Header schon die Funktion gmdate() und nicht etwa date() inkl. manuellem Setzen von "GMT"?

                            Gruß, Cybaer

                            --
                            Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!
                            1. Lieber Cybaer,

                              Hmm, aber Du benutzt für den Header schon die Funktion gmdate() und nicht etwa date() inkl. manuellem Setzen von "GMT"?

                              doch, bisher kannte ich die Funktion gmdate() nicht, daher habe ich letzteres durchgeführt. Aber das Schöne dieses Forums ist es ja gerade, dass man immer wieder dazulernt. Nun werde ich die date()-Funktion durch gmdate() ersetzen. Ich werde ja sehen, ob sich etwas ändert...

                              Vielen Dank für diese Anregung!

                              Liebe Grüße aus Ellwangen,

                              Felix Riesterer.

                              1. Hi,

                                Ich werde ja sehen, ob sich etwas ändert...

                                Ja, bei gleichen Timestamp eine Verschiebung des Datums im Header um z.Zt. 2 Stunden (1h normale Differenz + 1h Sommerzeit).

                                Gruß, Cybaer

                                --
                                Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!
            2. Hallo,

              Das E-Tag habe ich in seiner Bedeutung nicht verstanden, da mir die Erläuterungen in den Specs zu unverständlich waren.

              ETag dient wohl mehr dazu, mehrere Entitäten, also Ausprägungen o.ä., einer Ressource zu unterscheiden.

              exakt! Der Header "Last-Modified" bestimmt lediglich die letzte Ändereung einer Resource. Folgendes Script würde also zu unerwünsten Verhalten führen:

                
              clearstatcache();  
              $f='robots.txt';  
              $t=filectime($f);  
              $d=fopen($f,'a');  
              fwrite($d,' ');  
              fclose($d);  
              touch($f,$t);
              

              Das _kann_ wohl auch zur Bewertung der Aktualität der Ressource bzgl. des aktuellen Timestamps dienen, wie im vorliegenden Falle, wenn man eigentlich eine 304 Not Modified-Antwort umsetzen will - es gibt aber wohl noch andere Einsatzgebiete.

              Dadurch, daß sich der Header "ETag" beim Beispiel apache aus INode MTime Size zusammensetzt, wird eine Veränderung, die das kleine Script vorgenommen hat, dennoch erkannt. Der Header ist also erheblich verläßlicher.
               Andere Einsatzgebiete sind mir nicht bekannt.

              Manche Clients benutzen den Last-Modified-Header, um darauf hin bei der erneuten Anfrage ein If-Modified-Since zu generieren, um zu erfragen, ob sich die Ressource inzwischen gegenüber der gechachten Version verändert hat - manche Clients aber wohl auch den ETag.

              So z. B. FF und Moz während Opera, IE und links hier weder "If-Modified-Since" oder "If-None-Match" senden.

              ...ETag ebenfalls zu implementieren, kann man sich da also u.U. sparen.

              Da dynamisch generierte Dokumnente mit unterschiedlichen Parametern arbeiten ($_GET,$_POST, etc.) und demzufolge auch unterschiedliche Ausgaben erzeugen, wird es auf ein Ausgabepufferung hinauslaufen müssen. Ist das Dokument soweit erstellt könnte man mit md5 eine Prüfsumme ziehen und diese als Wert des ETag-Headers verwenden. Dumm nur: Den Header Content-MD5 gibt es auch und wird vom Server gebildet, sodaß man sich den Zirkus mit Ausgabepufferung sparen könnte. Er wäre der eindeutigste Anhaltspunkt für die Aktualität eines Dokuments, wird aber von keinem Browser dafür genutzt.

              Beim Gebrauch eines Hashs kommt der eigentliche Vorteil dieses Headers zum tragen. Er ist nicht an eine strikte Formatierung gebunden und kann also aufnehmen, was er will.

              Diese Abschnitte hatte ich verstanden und Last-Modified davon umgesetzt. Bei If-Modified-Since und ETag ist mir nicht klar geworden, wofür ich die genau einsetzen sollte, bzw. welche Information ich mit diesen Headern schicken müsste.

              CLIENT: [Erstanfrage]
              SERVER: Last-Modified: Thu, 09 Mar 2006 17:27:56 GMT
              CLIENT: If-Modified-Since: Thu, 09 Mar 2006 17:27:56 GMT

              CLIENT: [Erstanfrage]
              SERVER: ETag: "1b-40e93326f9f00"
              CLIENT: If-None-Match: "1b-40e93326f9f00"

              Die Mechanismen sind also analog zu einander.

              Gruß aus Berlin!
              eddi

              1. Lieber eddi,

                das war super aufschlussreich! Werde mich, nachdem ich meinen Last-Modified verbessert habe, einmal intensiver dem ETag zuwenden.

                Liebe Grüße aus Ellwangen,

                Felix Riesterer.

              2. hi,

                ETag dient wohl mehr dazu, mehrere Entitäten, also Ausprägungen o.ä., einer Ressource zu unterscheiden.

                exakt!

                Gut - dann kannst du mir vielleicht erklären, was das bedeutet, was ich da schrieb? :-)
                Ich kann mir unter mehreren "Ausprägungen" einer Ressource nämlich so richtig bildhaft auch noch nichts (sinnvolles) vorstellen.

                Der Header "Last-Modified" bestimmt lediglich die letzte Ändereung einer Resource. Folgendes Script würde also zu unerwünsten Verhalten führen: [...]

                Sicher - aber da untergräbst du bewährtes Verhalten ja bewusst.
                Wodurch sollte ich mich veranlasst fühlen, bei einer auf einer statischen Datei basierenden Ressource bei einer Änderung das Änderungsdatum anschließend wieder zurückzusetzen?
                Mir selber Schnitzel ans Knie zu nageln, halte ich für ein wenig erfüllendes Verhalten ...

                Dein Beispiel sehe ich also eher als theoretisches an - du hast zwar recht damit, aber es erscheint mir doch arg praxisfern.

                Dadurch, daß sich der Header "ETag" beim Beispiel apache aus INode MTime Size zusammensetzt, wird eine Veränderung, die das kleine Script vorgenommen hat, dennoch erkannt. Der Header ist also erheblich verläßlicher.

                Das mag auf dein konstruiertes Beispiel zutreffen.
                Wenn ich aber bei dynamisch erstelltem Content anhand des Änderungsdatums die Entscheidung treffen möchte, ob ich mit 304 oder 200 und erneuter Auslieferung der Ressource antworte, sehe ich im ETag keinen Vorteil gegenüber dem Last-Modified.

                So z. B. FF und Moz während Opera, IE und links hier weder "If-Modified-Since" oder "If-None-Match" senden.

                Tun sie nicht?
                Hrmpf, dann kann man sich den Aufwand ja fast sparen ...

                Nicht mal Opera unterstützt Conditional Get in dieser Hinsicht?

                Da dynamisch generierte Dokumnente mit unterschiedlichen Parametern arbeiten ($_GET,$_POST, etc.) und demzufolge auch unterschiedliche Ausgaben erzeugen, wird es auf ein Ausgabepufferung hinauslaufen müssen.

                Ein dynamisch generiertes Dokument kann ja bspw. auch ein RSS-Feed oder eine Weblog-Seite sein.
                Deren Inhalt ändert sich nur, wenn ein neuer Eintrag oder Kommentar hinzugekommen ist.
                Dies kann ich am Scriptanfang aus meiner Datenbank ermitteln - und könnte mit 304 antworten, und mir so den Traffic für das erneute Ausliefern der Daten sparen.

                Klar, gleich "richtiges" Caching zu implementieren, und den RSS-Feed als statische Datei zu erzeugen, wäre natürlich alternative denkbar.

                gruß,
                wahsaga

                --
                /voodoo.css:
                #GeorgeWBush { position:absolute; bottom:-6ft; }
                1. Re:

                  ETag dient wohl mehr dazu, mehrere Entitäten, also Ausprägungen o.ä., einer Ressource zu unterscheiden.

                  Gut - dann kannst du mir vielleicht erklären, was das bedeutet, was ich da schrieb? :-)

                  Die PHP-Funktion stat() liefert eine Reihe von "Ausprägungen" eines Files:

                  Ausgabe stat()           Erklärung                            FileETage-Direktive (apache)

                  [dev] => 772          -> Laufwerk
                      [ino] => 13065        -> inode                                ->  INode
                      [mode] => 33188       -> inode protection mode
                      [nlink] => 1          -> Anzahl der Links
                      [uid] => 1000         -> Benutzer ID des Inhabers
                      [gid] => 100          -> Gruppen ID des Inhabers
                      [rdev] => 0           -> Laufwerkstyp wenn Inode-Laufwerk *
                      [size] => 478         -> Größe in Bytes                       ->  Size
                      [atime] => 1138881639 -> Zeitpunkt des letzten Zugriffs
                      [mtime] => 1144313089 -> Zeitpunkt der letzten Modifizierung  ->  MTime
                      [ctime] => 1144313089 -> Zeitpunkt der letzten Änderung
                      [blksize] => 131072   -> k. A.
                      [blocks] => 8         -> Blockgröße für das Dateisystem I/O *

                  Mir selber Schnitzel ans Knie zu nageln, halte ich für ein wenig erfüllendes Verhalten ...

                  Gut und schön, aber ich habe doch auch schon genug am eigenen Knie (und seit dem Schatz auf ist zusätzlich noch eine Frikadelle am Ohr ;(

                  Dein Beispiel sehe ich also eher als theoretisches an - du hast zwar recht damit, aber es erscheint mir doch arg praxisfern.

                  Ein Szenario sind Archive (tar/zip/rar): Man erstellt sich an seiner Testumgeben ein neues Projekt, verpackt es, läd es auf den Server hoch und entpackt es über das bestehende alte. Dabei hat man aber vergessen dem entpackendem Progamm mitzuteilen, alle Files mit aktuellem timespamp zu erzeugen. Pech nur dann, wenn bestehende Files mit Files im Archiv selbe mtimes aufweisen...

                  Ich weiß, auch das ist konstruiert.

                  Das mag auf dein konstruiertes Beispiel zutreffen.
                  Wenn ich aber bei dynamisch erstelltem Content anhand des Änderungsdatums die Entscheidung treffen möchte, ob ich mit 304 oder 200 und erneuter Auslieferung der Ressource antworte, sehe ich im ETag keinen Vorteil gegenüber dem Last-Modified.

                  Vielleicht können wir uns darauf einigen, daß ETag einer möglichen Softwarekonfiguration "paranoid" entspricht.

                  So z. B. FF und Moz während Opera, IE und links hier weder "If-Modified-Since" oder "If-None-Match" senden.

                  Tun sie nicht?
                  Hrmpf, dann kann man sich den Aufwand ja fast sparen ...
                  Nicht mal Opera unterstützt Conditional Get in dieser Hinsicht?

                  Daß der IE hier mal wieder die Füße hochlegt, statt zu arbeiten, war zu erwarten. Auch von links als Textbrowser kann man sowas nicht wirklich erwarten. Aber das Dein heißgeliebter Opera sich hier auch eine Pause gönnt, hat mich selbst überrascht.

                  Da dynamisch generierte Dokumnente mit unterschiedlichen Parametern arbeiten ($_GET,$_POST, etc.) und demzufolge auch unterschiedliche Ausgaben erzeugen, wird es auf ein Ausgabepufferung hinauslaufen müssen.

                  Ein dynamisch generiertes Dokument kann ja bspw. auch ein RSS-Feed oder eine Weblog-Seite sein.
                  Deren Inhalt ändert sich nur, wenn ein neuer Eintrag oder Kommentar hinzugekommen ist.
                  Dies kann ich am Scriptanfang aus meiner Datenbank ermitteln - und könnte mit 304 antworten, und mir so den Traffic für das erneute Ausliefern der Daten sparen.

                  Da ist bei mir eine Bildungslücke. Beispiel:

                  http://ich.will.net/ja.php?sag=nein
                  http://ich.will.net/ja.php?sag=immernoch+nein
                  http://ich.will.net/ja.php?sag=vielleicht

                  Gehen Browser davon aus, daß es sich um die Resource "ja.php" hantelt, oder ist ihnen schon klar, daß hier die Resourcen "ja.php?sag=nein", "ja.php?sag=immernoch+nein" und "ja.php?sag=vielleicht" vorliegen. (Erster Fall wäre eine Katastrophe und zumindes für Moz gilt Fall zwei.)

                  Gruß aus Berlin!
                  eddi

                  1. hi,

                    Ein Szenario sind Archive (tar/zip/rar): [...]
                    Ich weiß, auch das ist konstruiert.

                    Aber schon ein etwas plastischeres, danke.

                    Da ist bei mir eine Bildungslücke. Beispiel:

                    http://ich.will.net/ja.php?sag=nein
                    http://ich.will.net/ja.php?sag=immernoch+nein
                    http://ich.will.net/ja.php?sag=vielleicht

                    Gehen Browser davon aus, daß es sich um die Resource "ja.php" hantelt, oder ist ihnen schon klar, daß hier die Resourcen "ja.php?sag=nein", "ja.php?sag=immernoch+nein" und "ja.php?sag=vielleicht" vorliegen. (Erster Fall wäre eine Katastrophe und zumindes für Moz gilt Fall zwei.)

                    Der Querystring ist Bestandteil des Request-URIs, und dieser definiert die Ressource _eindeutig_ - ein Client, der hier nicht von "letzterem" ausgehen würde, wäre so grob fehlerhaft, dass er für einen Einsatz im www nahezu unbrauchbar wäre.

                    gruß,
                    wahsaga

                    --
                    /voodoo.css:
                    #GeorgeWBush { position:absolute; bottom:-6ft; }
                  2. hi,

                    Aber das Dein heißgeliebter Opera sich hier auch eine Pause gönnt, hat mich selbst überrascht.

                    Nein, das lässt mir natürlich keine Ruhe :-)

                    Ich hab mir jetzt mal folgendes Testszenario dazu gebastelt:

                    • ein Script, welches:
                        - den aktuellen Timestamp des Requests in eine Session schreibt
                        - die Request-Header mittels getallheaders() in die Session schreibt
                        - den aktuellen Timestamp als sichtbare Kontrollanzeige als HTML-Dokument an den Client schickt
                        - einen Link auf sich selber enthält, um die Ressource erneut "anzufordern"
                        - einen Last-Modified-Header/ und einen ETag-Header zeugt
                        - auf If-Modified-Since/If-None-Match überprüft, und je nachdem nur mit 304 oder 200 (und dabei "aktualisierter" Timestamp-Ausgabe) antwortet

                    • ein Script, welches mir die Session-Daten zur Kontrolle anzeigt

                    Ich lade im Opera mein erstes Script, es gibt mir als (formatierten) Timestamp
                    Sun, 09 Apr 2006 15:36:45 +0200
                    aus.

                    Ich lade mein Session-Kontroll-Script, das gibt mir als Zeitpunkt des letzten Zugriffs auf das erste Script ebenfalls den von diesem in der Session hinterlegten Zeitstempel
                    Sun, 09 Apr 2006 15:36:45 +0200
                    aus.

                    Jetzt klicke ich in meinem ersten Script auf den Link "auf-sich-selber" [1] - und sehe an der Ladeanzeige, dass der Opera eine Anfrage an den Server stellt. Die Kontrollanzeige des Timestamps bleibt bei
                    Sun, 09 Apr 2006 15:36:45 +0200

                    Jetzt lade ich mein Session-Kontroll-Script neu, und bekomme dort als von Script #1 in der Session hinterlegten Timestamp des letzten Zugriffs
                    Sun, 09 Apr 2006 15:37:51 +0200
                    angezeigt.

                    Opera _hat_ also beim Webserver nachgefragt, einen 304 bekommen, und die Anzeige des Dokumentes nicht aktualisiert.
                    Den _Zeitpunkt_ dieser erneuten Anfrage kann ich mit dem anderen Script aus der Session auslesen, und der _hat_ sich verändert.

                    Bei den in die Session geschriebenen Request-Headern tauchen sowohl If-Modified-Since als auch If-None-Match auf.

                    Ich habe es mit den Cache-Einstellungen für "Check documents: Every hour" und "Check documents: Always", bei beiden das gleiche Ergebnis.

                    gruß,
                    wahsaga

                    [1] Wenn ich statt dem Aufruf über den Link explizit per F5 neu lade, _dann_ macht Opera verständlicher Weise kein Conditional GET.

                    --
                    /voodoo.css:
                    #GeorgeWBush { position:absolute; bottom:-6ft; }
                    1. Re:

                      dann teste mal bitte (ohne Session und der gleichen und nur mit "Aktualisieren-Button" des Browsers) http://212.227.99.60/scripte/

                      Gruß aus Berlin!
                      eddi

                      1. hi,

                        dann teste mal bitte (ohne Session und der gleichen und nur mit "Aktualisieren-Button" des Browsers) http://212.227.99.60/scripte/

                        Done. Und nu?

                        Will sagen: Welche Aussagekraft willst du diesem Script zumessen?

                        Selbst wenn ich das über http://web-sniffer.net/ aufrufe, wo ich durch entsprechende Links die explizite Möglichkeit habe, es unter Verwendung von If-Modified-Since oder If-None-Match erneut abzurufen, bekomme ich das Dokument unter einem Status 200 erneut ausgeliefert, von einem 304 keine Spur ...

                        gruß,
                        wahsaga

                        --
                        /voodoo.css:
                        #GeorgeWBush { position:absolute; bottom:-6ft; }
                        1. Re:

                          Done. Und nu?
                          Will sagen: Welche Aussagekraft willst du diesem Script zumessen?

                          Es zeigt alle angelieferten Request-Header an. Bei meinem Opera folgende Header aber _nicht_ gesenden:

                          [HTTP_IF_MODIFIED_SINCE] => Thu, 09 Mar 2006 17:27:56 GMT
                              [HTTP_IF_NONE_MATCH] => "1b-40e93326f9f00"

                          nun habe ich aber auch keinen 8.54 sondern nur Version 8.52...

                          Gruß aus Berlin!
                          eddi

                          1. hi,

                            Will sagen: Welche Aussagekraft willst du diesem Script zumessen?

                            Es zeigt alle angelieferten Request-Header an. Bei meinem Opera folgende Header aber _nicht_ gesenden:

                            [HTTP_IF_MODIFIED_SINCE] => Thu, 09 Mar 2006 17:27:56 GMT
                                [HTTP_IF_NONE_MATCH] => "1b-40e93326f9f00"

                            Warum sollte er auch?

                            Erste Anforderung des Scriptes, mein Browser kennt die Ressource noch gar nicht - kein Grund für ein Conditional GET.

                            OK, zweite Anforderung des Scriptes - ja, jetzt sollte der Browser mindestens einen der Request-Header für ein Conditional GET mitschicken - tut er aber, wie gesagt, eben nicht, wenn ich die Ressouce über [F5] erneut anfordere - weil er dann davon ausgehen darf, dass ich sie wirklich auf jeden Fall neu geladen haben möchte.

                            Da käme jetzt in meinem Beispiel der Link auf die Ressource ins Spiel - der erfordert keinen expliziten Reload.
                            Also schaut mein Browser nach - "hab ich die Seite noch im Cache? Ja, hab ich - also mach' ich mal einen Conditional GET, um mich zu erkundigen, ob sie noch aktuell ist."
                            _Hier_ käme jetzt der 304 ins Spiel.

                            Und da liegt der Knackpunkt, warum du mit deinem Beispielscript nicht nachvollziehen können wirst, ob der Browser das korrekt implementiert hat, oder nicht:

                            Macht mein Browser keinen Conditional GET, weil ich wie oben beschrieben explizit ein neu laden der Ressource angefordert habe - dann bekommst du keinen If-Modified-Since- oder If-None-Match-Header in der Ausgabe deines Scriptes zu sehen - die wären für den Reload fehl am Platze, dürften hier gar nicht auftauchen.

                            Macht mein Browser hingegen einen Conditional GET, und dein Script behandelt diesen korrekt - in dem es eben mit 304 antwortet - dann werden wir die entsprechenden Header in der Ausgabe deines Scriptes trotzdem nicht zu Gesicht bekommen. Eben _weil_ der Browser das Dokument ja gar nicht neu anfordert, sondern jetzt wieder die zuerst - _ohne_ Conditional GET - angeforderte Version des Dokumentes, die sich noch in seinem Cache befindet, erneut anzeigen wird.

                            _Eben deshalb_ habe ich ja bei meinem Testbeispiel zur Kontrolle die Session verwendet, deren aktuelle Werte ich mir über ein zweites Script unabhängig von diesem Request anzeigen lassen kann.

                            Es wäre ja ein Widerspruch in sich, wenn dein Server mir einerseits mit einem 304 Not Modified antworten, und mir _gleichzeitig_ aber aktualisierte Daten - eben die aktualisierte Kontrollausgabe der Header des Conditional GET-Requests - übermitteln wollen würde.

                            Nicht umsonst verlangt HTTP ja auch an dieser Stelle, dass die 304-Antwort keinen Message Body enthalten darf, weil das widersinnig wäre:
                            http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5:

                            The 304 response MUST NOT contain a message-body, and thus is always terminated by the first empty line after the header fields.

                            gruß,
                            wahsaga

                            --
                            /voodoo.css:
                            #GeorgeWBush { position:absolute; bottom:-6ft; }
                            1. Re:

                              Es zeigt alle angelieferten Request-Header an. Bei meinem Opera folgende Header aber _nicht_ gesenden:

                              [HTTP_IF_MODIFIED_SINCE] => Thu, 09 Mar 2006 17:27:56 GMT
                                  [HTTP_IF_NONE_MATCH] => "1b-40e93326f9f00"

                              Warum sollte er auch?

                              Um Traffic zu sparen?!

                              Erste Anforderung des Scriptes, mein Browser kennt die Ressource noch gar nicht - kein Grund für ein Conditional GET.

                              Na vielen Dank; daß bei Erstanfrage keine Konditionen zu erwarten sind, brauchst Du mir nun doch nicht erklären.

                              OK, zweite Anforderung des Scriptes - ja, jetzt sollte der Browser mindestens einen der Request-Header für ein Conditional GET mitschicken - tut er aber, wie gesagt, eben nicht, wenn ich die Ressouce über [F5] erneut anfordere - weil er dann davon ausgehen darf, dass ich sie wirklich auf jeden Fall neu geladen haben möchte.

                              Das hört sich ja fast so an wie: Während der Opera in einem fairen Duell den ausgezeichneten zweiten Platz erringen konnte, mußte sich der Mozilla mit dem vorletzten Platz begnügen ;$

                              Da käme jetzt in meinem Beispiel der Link auf die Ressource ins Spiel - der erfordert keinen expliziten Reload.
                              Also schaut mein Browser nach - "hab ich die Seite noch im Cache? Ja, hab ich - also mach' ich mal einen Conditional GET, um mich zu erkundigen, ob sie noch aktuell ist."
                              _Hier_ käme jetzt der 304 ins Spiel.
                              Und da liegt der Knackpunkt, warum du mit deinem Beispielscript nicht nachvollziehen können wirst, ob der Browser das korrekt implementiert hat, oder nicht:
                              Macht mein Browser keinen Conditional GET, weil ich wie oben beschrieben explizit ein neu laden der Ressource angefordert habe - dann bekommst du keinen If-Modified-Since- oder If-None-Match-Header in der Ausgabe deines Scriptes zu sehen - die wären für den Reload fehl am Platze, dürften hier gar nicht auftauchen.

                              Also fordert man in einem weiteren Tab die Resource erneut an. Und siehe da: Nix - gar nichts - nicht mal ein Eintrag im Serverlog?!
                              Das war aber wieder Hinweis genug mir die Konfiguration anzusehen, und genau da liegt der Hund begraben. Opera kommt mit einer beschissenen Grundeinstellung daher - alle Resourcen erst nach 5 Stunden auf Aktualität zu prüfen...

                              Wie war das noch mal mit Schnitzeln und Knie?

                              Wie dem auch sei, es ist mir nunmehr gelungen auch dem Opera einen If-Header zu entlocken und ich kann nur sagen, diese Software hat mit einigen Modifikationen durchaus das Zeug dazu, sich eines Tages auch als Browser bezeichen zu lassen ;þ

                              Gruß aus Berlin!
                              eddi

                              1. hi,

                                OK, zweite Anforderung des Scriptes - ja, jetzt sollte der Browser mindestens einen der Request-Header für ein Conditional GET mitschicken - tut er aber, wie gesagt, eben nicht, wenn ich die Ressouce über [F5] erneut anfordere - weil er dann davon ausgehen darf, dass ich sie wirklich auf jeden Fall neu geladen haben möchte.

                                Das hört sich ja fast so an wie: Während der Opera in einem fairen Duell den ausgezeichneten zweiten Platz erringen konnte, mußte sich der Mozilla mit dem vorletzten Platz begnügen ;$

                                Warum?
                                Ich finde dieses Verhalten vernünftig.
                                Wenn ich [F5] benutze, will ich einen expliziten Reload.
                                Wenn ich dagegen die Seite über einen Link aufrufe, möchte ich die ggf. bereits gecachte Version bekommen.

                                Das war aber wieder Hinweis genug mir die Konfiguration anzusehen, und genau da liegt der Hund begraben. Opera kommt mit einer beschissenen Grundeinstellung daher - alle Resourcen erst nach 5 Stunden auf Aktualität zu prüfen...

                                Wie gesagt, in meinem Test funktionierte es auch mit der Einstellung, erst nach einer Stunde wieder zu prüfen.
                                Werde ich aber noch mal überprüfen.

                                gruß,
                                wahsaga

                                --
                                /voodoo.css:
                                #GeorgeWBush { position:absolute; bottom:-6ft; }
                                1. Hallo wahsaga,

                                  Warum?
                                  Ich finde dieses Verhalten vernünftig.
                                  Wenn ich [F5] benutze, will ich einen expliziten Reload.

                                  Deswegen spricht ja auch nichts dagegen, wenn der Browser sich mit dem Server in Verbindung setzt. Allerdings ist ein Conditional GET m.M.n. die sinnvollere Alternative, da - falls die Seite sich nicht geändert hat, sie nicht nochmal übermittelt wird und unnötigen Traffic produziert und das außerdem noch Zeit kostet. Was bringt's denn bitteschön, wenn die Seite nochmal über's Netz wandert und der Browser das gleiche vorgesetzt bekommt? Und für den Fall der Fälle (irgendwas läuft gewaltig schief - sowas tritt i.d.R. aber nicht auf) kann man ja noch eine weitere Reload-Stufe einbauen, wie es in den Netscapes bzw. auch Geckos der Fall ist.

                                  Wenn ich dagegen die Seite über einen Link aufrufe, möchte ich die ggf. bereits gecachte Version bekommen.

                                  Ja. Aber bei Aufruf per Link erwarte ich, dass der Server gar nicht kontaktiert wird, im Gegensatz zu einem Reload.

                                  Viele Grüße,
                                  Christian

                                  --
                                  "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                                  1. hi,

                                    Wenn ich [F5] benutze, will ich einen expliziten Reload.

                                    Deswegen spricht ja auch nichts dagegen, wenn der Browser sich mit dem Server in Verbindung setzt. Allerdings ist ein Conditional GET m.M.n. die sinnvollere Alternative,

                                    Ok, stimmt.

                                    Ja. Aber bei Aufruf per Link erwarte ich, dass der Server gar nicht kontaktiert wird, im Gegensatz zu einem Reload.

                                    Warum das?
                                    Ich finde es durchaus sinnvoll, wenn mir beim erneuten Aufruf eines Links ebenfalls die ggf. aktualisierte Version angezeigt wird.

                                    gruß,
                                    wahsaga

                                    --
                                    /voodoo.css:
                                    #GeorgeWBush { position:absolute; bottom:-6ft; }
                                2. Hallo wahsaga,

                                  Ich finde dieses Verhalten vernünftig.
                                  Wenn ich [F5] benutze, will ich einen expliziten Reload.

                                  das sehe ich nicht so. Wenn ich F5 drücke (oder den Reload-Button klicke), dann möchte ich eine *aktuelle* Version der Seite. Dann finde ich es korrekt, wenn mein Browser dann beim Server anfragt: "Ich hab die Fassung von 11:33:16h, hast du was Neueres?" Wenn es keine neuere Fassung gibt, kann sich der Browser meinetwegen gern aus dem Cache bedienen.

                                  Abgesehen davon hat vor allem ein sehr verbreiteter Browser aus Redmond sowieso die Unart, in der (unsinnigen) Defaulteinstellung beim Reload die Seite bevorzugt aus dem Cache zu holen, *ohne vorher anzufragen*, anstatt sie neu anzufordern. Das ist ja vor allem bei unerfahrenen Anwendern oft ein Anlass der Verzweiflung. Wenn man beim IE wirklich einen *expliziten* Reload will, dann braucht's ein Ctrl-F5.

                                  Wenn ich dagegen die Seite über einen Link aufrufe, möchte ich die ggf. bereits gecachte Version bekommen.

                                  Ich nicht. Auch dann möchte ich bitteschön die aktuelle Fassung. Nur in einem einzigen Fall finde ich es sinnvoll, die Seite ohne Nachfrage aus dem Cache zu holen: Beim "Zurück"-Navigieren.

                                  Schönen Tag noch,
                                   Martin

                                  --
                                  You say, it cannot be love if it isn't for ever.
                                  But let me tell you: Sometimes, a single scene can be more to remember than the whole play.
                                  1. hi,

                                    Wenn ich [F5] benutze, will ich einen expliziten Reload.

                                    das sehe ich nicht so.

                                    Ja, ich auch nicht mehr :-)

                                    gruß,
                                    wahsaga

                                    --
                                    /voodoo.css:
                                    #GeorgeWBush { position:absolute; bottom:-6ft; }
              3. Hallo eddi,

                Manche Clients benutzen den Last-Modified-Header, um darauf hin bei der erneuten Anfrage ein If-Modified-Since zu generieren, um zu erfragen, ob sich die Ressource inzwischen gegenüber der gechachten Version verändert hat - manche Clients aber wohl auch den ETag.

                So z. B. FF und Moz während Opera, IE und links hier weder "If-Modified-Since" oder "If-None-Match" senden.

                das stimmt so nicht. Zumindest der IE fragt grundsätzlich mit If-Modified-Since an und gibt sich mit einem 304 zufrieden, wenn er die Ressource im Cache hat. Dabei gibt er AFAIK das Last-Modified-Datum an, falls der Server ihm eins angegeben hat; sonst den Zeitpunkt, zu dem er die Ressource in seinen Cache eingelagert hat.
                Das alles natürlich nur, wenn man das Caching-Verhalten auch vernünftig eingestellt hat, also "every visit to the page".

                Schönen Sonntag noch,
                 Martin

                --
                Ich liebe Politiker auf Wahlplakaten.
                Sie sind tragbar, geräuschlos, und leicht wieder zu entfernen.
                  (Loriot, deutscher Satiriker)
                1. Hi,

                  das stimmt so nicht. Zumindest der IE fragt grundsätzlich mit If-Modified-Since an

                  IIRC nur dann, wenn er entsprechend konfiguriert ist.

                  Man kann ihn (IIRC ;-)) auch so konfigurieren, daß er IMS nur sendet, wenn er beim erstmaligen Aufruf auch ein Last-Modified-Header bekommen hat.

                  Gruß, Cybaer

                  --
                  Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!
  3. Hi,

    Für den Teil "noch erreichbar" wird das ausreichend sein. Was ist aber mit dem Teil "noch aktuell"? Erste Tests haben ergeben das nicht alle Server im HEAD ein "Last-Modified" haben. Leider weiß ich nicht ob das fehlen dieser HEAD Angaben die Regel ist.

    Bei servergenerierten Seiten ist es das (logischerweise).

    2 Funktionen, um Last-Modified- (oder ETag-)Header zu ermitteln und zu setzen, bzw. passend darauf zu reagieren (durch Senden eines entsprechenden Headers nebst Scriptabbruch): Coding: Modified? Not Modified!

    Gruß, Cybaer

    --
    Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!
  4. Hallo,

    für ein größeres Projekt muss ich einen Crawler in Python Programmieren. (..)
    Die einmal geladenen Seiten sollen regelmäßig auf "noch erreichbar" und "noch aktuell" hin überprüft werden.

    Da hat sich übrigens noch etwas dazu in meinen Bookmarks gefunden. Joe Gregorio hat sich vor einiger Zeit aufgemacht, die Python httplib durch eine bessere Bibliothek, httplib2 zu ersetzen. Diese versteht dann u.a. Caching und gestaltet das bequemer für den Benutzer, so dass dieser sich nicht um jeden Kleinkram kümmern muss. Er begleitet die Entwicklung auch mit Artikeln auf xml.com, in denen er die jeweiligen Bestandteile von HTTP ausführlicher vorstellt; bislang erschienen sind:

    Doing HTTP Caching Right
    httplib2: HTTP Persistence and Authentication

    Allerdings: Das Ding befindet sich noch in der Entwicklung. Es gibt zwar Unit Tests, aber noch keine Dokumentation. Ich habe selber noch nicht damit rumgespielt; kann also keine Empfehlung geben. Aber vielleicht möchtest Du Dir die Bibliothek mal genauer anschauen.

    Tim

  5. Hallo Freunde des gehobenen Forumsgenusses,

    Ich habe eine Klasse in PHP geschrieben, die passende Last-Modified- und ETag-Header verschickt und Requests mit IF-Modified-Since- oder If-None-Match-Header korrekt mit 304 Not Modified beantwortet.

    Dazu übernimmt der Konstruktor den Inhalt des Dokumentes als Parameter, bildet einen Hash und trägt die URL, den Hash und die aktuelle Uhrzeit in eine SQL-Tabelle ein:

      
    create table if not exists VCC_data (  
     url varchar(255) primary key,  
     etag varchar(72) not null,  
     last_modified datetime not null  
    );  
    
    

    Außerdem werden eben ETag- und Last-Modified-Header gesetzt.

    Wenn nun diese URL ein zweites Mal aufgerufen wird bildet die Software erneut den Hash des Inhaltes und vergleicht ihn mit dem in der Datenbank. Wenn die beiden nicht identisch sind wird das Datum in der Tabelle auf now() gesetzt und der neue Hash eingetragen (die Programmlogik steckt im Konstruktor von VCacheController.class.php).

    Soweit so gut, nur in der Praxis funktioniert das irgendwie nicht ganz so wie ich mir das vorgestellt habe:

    Wenn ich mit Curl die Produktiv-Seite abrufe bekomme ich immer als Last-Modified den Inhalt des Date-Headers, bei den Unterseiten aber nicht, und das obwohl sich der Zeistempel in der Datenbank nirgends geändert hat, lokal habe ich das Problem nicht.

    Könntet ihr euch das mal angucken:
    http://alexanderbrock.de/ ff.

    Die Software gibs hier:
    VCacheController-0.1beta unter GPL, wenn das alles mal richtig funktioniert schreibe ich da noch eine Benutzerdokumentation zu, im Moment gibt es nur PHPDockumentator-Kommentare.

    Gruß
    Alexander Brock