Raik: Datei nur herunterladen, wenn modifiziert

Hallo!

aus einer ini-datei (1.98kb) bei sourceforge sollen werte für eine ausgabe auf einem anderen server ausgelesen werden.
ich möchte diese datei aber nur laden, wenn sie geändert wurde und ansonsten die schon geparsten werte aus einer lokalen datei für die seitenerstellung verwenden.
ich bin auf den header "If-Modified-Since" gestossen, habe aber bisher nicht verstanden, wie der angewendet wird.

lohnt sich der aufwand bei der grösse der datei überhaupt, oder kostet der request bis zur response des sf-servers die meiste zeit? (auch wenn mich die anwendung des headers trotzdem interessiert)

freundl. Grüsse aus Berlin, Raik

  1. Hallo Raik,

    ich bin auf den header "If-Modified-Since" gestossen, habe aber bisher nicht verstanden, wie der angewendet wird.

    Er wird gern von Browsern angewendet, die die angeforderte Ressource schon im Cache haben, aber überprüfen wollen, ob sie noch aktuell ist. Dazu kommt dieser "If-Modified-Since" Header in den Request, dem der Timestamp der im Cache befindlichen Ressource folgt. Dann erkennt der Server gleich, "ah, die Fassung von gestern um halb drei hat er schon".
    Hat sich die Ressource seitdem geändert, antwortet der Server ganz normal mit Status 200 und sendet die angeforderte Ressource. Andernfalls antwortet er mit "304 Not Modified" und einem leeren Body, und der Fall ist erledigt. Der Client weiß dann, dass er die gespeicherte Version im Cache weiter benutzen kann.

    lohnt sich der aufwand bei der grösse der datei überhaupt, oder kostet der request bis zur response des sf-servers die meiste zeit? (auch wenn mich die anwendung des headers trotzdem interessiert)

    Bei rund 2k Nutzdaten wäre es wohl ein Overkill, den Mechanismus dafür extra zu implementieren. Da sind die Daten ohne Überprüfung genauso schnell übertragen.

    So long,

    Martin

    1. Hello,

      Hat sich die Ressource seitdem geändert, antwortet der Server ganz normal mit Status 200 und sendet die angeforderte Ressource. Andernfalls antwortet er mit "304 Not Modified" und einem leeren Body, und der Fall ist erledigt. Der Client weiß dann, dass er die gespeicherte Version im Cache weiter benutzen kann.

      Damit der Vorgang aber unter "Normalempfehlung" auch zustande kommt, muss der Server bei Auslieferung der Datei auch einen "Last Modified" mitsenden und darf nicht widersprüchlich eine falsche Cache-Strategie empfehlen.

      Dass Browser sowieso machen, was sie wollen, ist auch klar ...

      Harzliche Grüße vom Berg
      esst mehr http://www.harte-harzer.de

      Tom

      --
      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
      Nur selber lernen macht schlau
      1. n'Abend!

        Damit der Vorgang aber unter "Normalempfehlung" auch zustande kommt, muss der Server bei Auslieferung der Datei auch einen "Last Modified" mitsenden

        Oh, daran hab ich noch gar nicht gedacht. Ich bin stillschweigend davon ausgegangen, dass der Client beim Request im "If-Modified-Since" den Zeitpunkt angibt, zu dem er die Ressource zuletzt abgerufen bzw. angefragt hat.

        Dass Browser sowieso machen, was sie wollen, ist auch klar ...

        Ja, allerdings.
        So long,

        Martin

    2. Hallo, Martin!

      Er wird gern von Browsern angewendet, ...

      ja, soweit war ich in etwa auch schon mit meinen erkenntnissen gekommen.
      was mir jetzt fehlt, ist die richtige syntax.
      ich hab nach beispielen für die anwendung gegoogelt, aber bisher nichts gefunden.
      wie fordere ich die ini-datei bedingt mit if-modified-since an?

      Bei rund 2k Nutzdaten wäre es wohl ein Overkill, ...

      ich weis, ich möchte es aber auch unabhängig davon wissen.

      freundl. Grüsse aus Berlin, Raik

      1. Hallo Raik,

        ja, soweit war ich in etwa auch schon mit meinen erkenntnissen gekommen.
        was mir jetzt fehlt, ist die richtige syntax.

        Ich hab mir mal die HTTP-Spezifikation angesehen - da steht aber nur
         If-Modified-Since: <HTTP-Date>

        Was HTTP-Date genau ist, verraten die Jungs aber nicht so direkt. Also hab ich meinen Firefox mit der HTTP Live-Headers Extension belauscht und ein Beispiel aus einem Request-Header rauskopiert:

        If-Modified-Since: Tue, 31 Aug 2004 17:53:02 GMT

        Das scheint also die richtige Syntax zu sein, aus der man andere Fälle ableiten kann...

        Ciao,

        Martin

        1. Hallo, Martin!

          ... mit der HTTP Live-Headers Extension belauscht ...
            If-Modified-Since: Tue, 31 Aug 2004 17:53:02 GMT

          ja, scheint das gleiche format zu sein, wie bei Last-Modified.
          nun bleibt noch die frage, wie den download anstossen? müsste ja auch per header passieren.
          und muss der "If-Modified-Since"-header vor, oder hinter den download-request?

          freundl. Grüsse aus Berlin, Raik

          1. Hallo Raik,

            If-Modified-Since: Tue, 31 Aug 2004 17:53:02 GMT
            ja, scheint das gleiche format zu sein, wie bei Last-Modified.

            Sieht so aus, ja.

            nun bleibt noch die frage, wie den download anstossen? müsste ja auch per header passieren.

            Ähm, jetzt mus ich mal ganz dumm fragen: Wie gut kennst du dich mit dem HTTP-Protokoll aus? Anscheinend nicht so intensiv.
            Ich würde dir wirklich mal empfehlen, die HTTP Live-Headers im Firefox zu beobachten, da kann man einiges über das Protokoll als solches duch "Zuschauen" lernen.
            Ein typischer HTTP-Request sieht dann z.B. so aus:

            GET / HTTP/1.1
            Host: www.example.net
            User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0
            Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
            Accept-Language: en-us,en;q=0.8,de-de;q=0.5,de;q=0.3
            Accept-Encoding: gzip,deflate
            Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
            Keep-Alive: 300
            Connection: keep-alive

            In dieses ganze Geraffel (nicht alles davon ist zwingend notwendig) könnte man nun die If-Modified-Since-Zeile mit einbauen. Die Reihenfolge spielt dabei AFAIK keine Rolle, solange die erste Zeile mit der Request-Methode (GET) an erster Stelle bleibt.
            Willst du denn deine HTTP-Requests selbst zusammenstellen, oder warum interessiert dich das so brennend?

            So long,

            Martin

            1. Hallo, Martin!

              Ähm, jetzt mus ich mal ganz dumm fragen: Wie gut kennst du dich mit dem HTTP-Protokoll aus? Anscheinend nicht so intensiv.

              nein, nicht wirklich. :-/

              ... solange die erste Zeile mit der Request-Methode (GET) an erster Stelle bleibt.

              und genau da hängt es noch bei mir. ich finde in der php-hilfe gerade keinen weg, den header mit dem get-request zu verbinden. soll heissen, ich weis nicht, mit welcher methode ich die datei anfordern muss, damit dabei der server auch dem header berücksichtigt. mit file() gehts wohl nicht.

              Willst du denn deine HTTP-Requests selbst zusammenstellen, oder warum interessiert dich das so brennend?

              ich will abhängig davon, ob die datei verändert wurde, sie neu laden und parsen, oder die schon geparsten werte aus einer lokal gespeicherten datei verwenden.
              bei grossen dateien würde sich der aufwand ja auch lohnen.

              ich suche auch noch nach einem weg, an die header heranzukommen, die zwischen meinem script und dem sf-server ausgetauscht werden. bisher bekomme ich immer nur die aus der komunikation zwischen meinem browser und meinem script (auf meinem apachen).
              unter http://web-sniffer.net betreibt jemand ein script, dass das kann. wenn ich da nachsehen könnte ...
              aber der wird es nicht veröffentlichen, denke ich.

              freundl. Grüsse aus Berlin, Raik

              1. Hallo,

                [HTTP-Protokoll]

                nein, nicht wirklich. :-/

                macht ja nichts - das, was man *wirklich* braucht, kann man ja immer mal nachlesen. ;)

                und genau da hängt es noch bei mir. ich finde in der php-hilfe gerade keinen weg, den header mit dem get-request zu verbinden. soll heissen, ich weis nicht, mit welcher methode ich die datei anfordern muss, damit dabei der server auch dem header berücksichtigt. mit file() gehts wohl nicht.

                Ah, jetzt geht mir ein Licht auf. Nee, so komfortabel geht's wohl nicht mehr, da müsstest du schon direkt auf Socket-Ebene deine Requests selbst zusammenbauen und auch die Responses entsprechend auswerten (Header und Nutzdaten trennen, Fehlerbehandlung, etc). Scheint mir auch ein Riesenaufwand für so'ne kleine Datei zu sein.

                Aber ich habe neulich ein schönes Beispiel für einen POST-Request mit PHP gesehen, finde ihn aber gerade auf die Schnelle nicht mehr. Im PHP-Manual wird aber im Kapitel über fsockopen() das prinzipielle Vorgehen und der Umgang mit Sockets anhand von ein paar einfachen Beispielen gezeigt.

                Vielleicht hilft dir das ja weiter...
                So long,

                Martin

                1. Hallo, Martin!

                  soweit funktioniert es jetzt:

                    
                  <?php  
                  $sock = fsockopen("http:/bom.sourceforge.net", 80, $errno, $errstr, 30);  
                  if (!$sock) die("$errstr ($errno)\n");  
                    
                  fputs($sock, "GET /bominfo.ini HTTP/1.1\r\n");  
                  fputs($sock, "Host: bom.sourceforge.net\r\n");  
                  fputs($sock, "Connection: close\r\n");  
                  //     optionale Header  
                  # fputs($sock, "Accept-Encoding: gzip\r\n");  
                  # fputs($sock, "Accept: */*\r\n");  
                  # fputs($sock, "Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3\r\n");  
                  # fputs($sock, "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n");  
                  # fputs($sock, "User-Agent: PHP/".phpversion()."\r\n");  
                  //     wahlweise "Last-Modified" oder "ETag" auswerten  
                  # fputs($sock, "If-Modified-Since: Wed, 10 Aug 2005 20:26:52 GMT\r\n");  
                  # fputs($sock, 'If-None-Match: "411108-7f2-42fa630c"'."\r\n");  
                  fputs($sock, "\r\n");  
                    
                  $headers = "";  
                  while ($str = trim(fgets($sock, 128)))  
                    $headers .= "$str\n";  
                    
                  echo "\n";  
                    
                  $body = "";  
                  while (!feof($sock))  
                    $body .= fgets($sock, 128);  
                    
                  fclose($sock);  
                  echo "<pre>".$headers."<hr>".$body."</pre>";  
                  ?>  
                  
                  

                  freundl. Grüsse aus Berlin, Raik