T-Rex: PHP Anfrage als Bild beantworten

Moin,

Etwas peinliche Sache. Hab das ganze schonmal gefragt, aber die Lösung scheint nicht mehr zu funktionieren.
http://forum.de.selfhtml.org/archiv/2011/9/t207102/

Aber das ganze mal etwas einfacher formuliert.
Ich möchte ein Bild anfragen. Die Anfrage soll auf ein PHP Script umgeleitet werden (via htaccess kein ding). PHP soll das Bild zurück liefern und sich via Header als Bild "tarnen" (soweit auch kein Problem).
Das Problem das ich aktuell habe ist, dass Bild wird nicht vom Browser gecached. Ich erhalte immer eine 200 HTTP Code. Ich möchte aber einen 304 Code, damit das Bild nicht ständig übertragen wird.

Ich habe zwar wie man dem Link entnehmen kann einige Cache Header gesetzt, die greifen jedoch alle nicht, weshalb ich das Thema bitte von Grundauf besprechen würde. Deshalb die Annahme ich setze keinen Header außer den richtigen für das Bild. Bei einem Gif ist das:
header( "Content-type: image/gif" );

Gruß
304
T-Rex

  1. Lieber T-Rex,

    Ich erhalte immer eine 200 HTTP Code. Ich möchte aber einen 304 Code, damit das Bild nicht ständig übertragen wird.

    wenn ein Client mit GET die Resource anfragt, beantwortet Dein Script sinnvoller Weise mit "200 OK". Sollte jedoch ein Client mit HEADER anfragen, wie reagiert Dein Script dann? Kann es diese beiden HTTP-Requests unterscheiden?

    Liebe Grüße,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
    1. Hast du mal ein Beispiel bitte? Ich steh gerade etwas auf dem Schlauch.

      Gruß
      Danke
      T-Rex

      1. Hi,

        Hast du mal ein Beispiel bitte? Ich steh gerade etwas auf dem Schlauch.

        Wie Der Martin schon sagte - wenn dein Script die Daten mit einem “Last-Modified” Response-Header ausliefert, dann wird der Browser beim nächsten Request, wenn er die Gültigkeit der Ressource prüfen will, einen “If-Modified-Since” Request-Header mitschicken.

        Den analysierst du in deinem Script (Wie greift man mit PHP auf Request-Header zu? -> Google!), und entscheidest auf Grund der darin gemachten Datumsangabe, ob die Version, die der Client im Cache hat, noch aktuell ist – wenn ja, antwortet dein Script mit 304 Not Modified und ohne Daten zu senden; andernfalls, 200 OK plus Daten, wie „normal“.

        MfG ChrisB

        --
        RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
        1. Das ist natürlich eine Idee. Einzige Problem der Apache liefert mir diese Angabe nicht. Local könnte ich es bestimmt irgendwie/irgendwann hinbekommen. Da unser toller Chef aber gerade beim Webserver spart (ist ja nur die komplette Firma von abhängig), habe ich auf diesen keinen Zugriff :(.

          Deshalb fällt diese Lösung weg, oder kann man das umgehen?

          Weil ich denk mir... ein normales Bild (also ohne htaccess und php) wird als 200 ausgeliefert wenn noch nicht im cache und als 304, wenn im cache. Man müsste doch eine php Script einfach nur perfekt als Bild tarnen, dann erledigt der Browser dass doch von selbst?

          Gruß
          umgangener
          T-Rex

          1. Hallo,

            Das ist natürlich eine Idee. Einzige Problem der Apache liefert mir diese Angabe nicht.

            ähm, wieso der Apache? Du generierst die Daten doch per PHP, also sorgst du selbst auch für die Daten. Dein Script sollte in der Lage sein zu ermitteln, wann die Daten, aus denen das Bild erzeugt wird, zuletzt geändert wurden (z.B. anhand von File Timestamps). Diesen Zeitpunkt gibst du dann imast-Modified-Header deiner Response aus.

            Weil ich denk mir... ein normales Bild (also ohne htaccess und php) wird als 200 ausgeliefert wenn noch nicht im cache und als 304, wenn im cache. Man müsste doch eine php Script einfach nur perfekt als Bild tarnen, dann erledigt der Browser dass doch von selbst?

            Nein! Das Script selbst muss doch entscheiden, ob bei einem Conditional Request die Daten neu generiert und gesendet werden müssen, oder mit einem schnellen 304er abgewinkt werden.
            Es sei denn, du willst auf den Holzhammer-Cache kommen, also dass der Browser für eine Weile gar nicht mehr nachfragt. Ja, auch das sollte mit einem ordnungsgemäßen Last-Modified- und einem Expires-Header zu machen sein. Und einem Browser, der aufgrund seiner Konfiguration auch cachen "will".

            Ciao,
             Martin

            --
            Bis du einen Prinzen findest, musst du viele Frösche küssen.
            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
            1. ähm, wieso der Apache? Du generierst die Daten doch per PHP, also sorgst du selbst auch für die Daten. Dein Script sollte in der Lage sein zu ermitteln, wann die Daten, aus denen das Bild erzeugt wird, zuletzt geändert wurden (z.B. anhand von File Timestamps). Diesen Zeitpunkt gibst du dann imast-Modified-Header deiner Response aus.

              Der Apache leitet den "HTTP_IF_MODIFIED_SINCE" Value weiter oder setzt ihn. Dazu muss man beim Apache http.conf die Zeile "LoadModule expires_module modules/mod_expires.so" hinzufügen bzw. den Kommentar ("#") wegnehmen. Ohne dieses Modul kommt das "HTTP_IF_MODIFIED_SINCE" im PHP nicht an. Und um das zu machen muss man Zugriff auf den Server haben und das habe ich leider nur begrenzt :(. Deshalb fällt die Möglichkeit mit "HTTP_IF_MODIFIED_SINCE" wahrscheinlich aus.

              Gruß
              Zugriffsloser
              T-Rex

              1. Hallo,

                Der Apache leitet den "HTTP_IF_MODIFIED_SINCE" Value weiter oder setzt ihn. Dazu muss man beim Apache http.conf die Zeile "LoadModule expires_module modules/mod_expires.so" hinzufügen bzw. den Kommentar ("#") wegnehmen. Ohne dieses Modul kommt das "HTTP_IF_MODIFIED_SINCE" im PHP nicht an.

                sorry, das war mir nicht bekannt, und mit so einer Gemeinheit hätte ich auch nicht gerechnet (ist auch für mich nicht nachvollziehbar).

                Es gibt aber einen User-Kommentar im PHP-Manual, der beschreibt, wie man über einen Umweg doch drankommt.
                Ich hab's allerdings nicht ausprobiert.

                Ciao,
                 Martin

                --
                Lieber eine gesunde Verdorbenheit als eine verdorbene Gesundheit.
                Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
          2. Hi,

            Weil ich denk mir... ein normales Bild (also ohne htaccess und php) wird als 200 ausgeliefert wenn noch nicht im cache und als 304, wenn im cache. Man müsste doch eine php Script einfach nur perfekt als Bild tarnen, dann erledigt der Browser dass doch von selbst?

            Nein, das Script selber macht ja die Ausgaben wie zusätzliche HTTP Response Header.

            Man könnte natürlich das Bild aber auch gleich als richtige Bilddatei auf Platte ablegen, wenn es längerfristig benötigt wird – und dann per Rewriting nur dann auf das PHP-Script verweisen, wenn es die angeforderte Bilddatei noch nicht auf Platte gibt.

            MfG ChrisB

            --
            RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
            1. Man könnte natürlich das Bild aber auch gleich als richtige Bilddatei auf Platte ablegen, wenn es längerfristig benötigt wird – und dann per Rewriting nur dann auf das PHP-Script verweisen, wenn es die angeforderte Bilddatei noch nicht auf Platte gibt.

              WOAH... auf so eine Idee hab ich gewartet. Die ist genial! Ironischerweise mach ich das mit anderen Datein wie css und js schon. Beim Bild hab ich mich aber anscheinend zu sehr auf das php script versteift.

              Das probier ich mal. Danke!

              Gruß
              der ChrisB anknutschende
              T-rex

  2. Hallo,

    Ich habe zwar wie man dem Link entnehmen kann einige Cache Header gesetzt, die greifen jedoch alle nicht, weshalb ich das Thema bitte von Grundauf besprechen würde. Deshalb die Annahme ich setze keinen Header außer den richtigen für das Bild. Bei einem Gif ist das:
    header( "Content-type: image/gif" );

    beim Request sind insgesamt drei Fälle zu unterscheiden: Der Client kann
    a) die Ressource "ganz normal" anfordern, dann bekommt er sie im Erfolgsfall mit Status 200.
    b) die Ressource "bedingt" anfordern, indem er den Header If-Modified-Since mit dem Timestamp der
       im Cache gespeicherten Ressource mitsendet; der Server antwortet dann reguär mit 200, wenn die
       vom Client angegebene Version "veraltet" ist, oder mit 304 und Content-Length 0, wenn er meint,
       dass die vom Client gecachte Version noch gültig ist.
    c) die Ressource aus dem Cache holen, ohne überhaupt beim Server anzufragen - etwa weil der Cache-
       Header vom letzten Request gemeldet hat, dass diese Ressource noch lange gültig sein wird.

    Da spielen also beide Seiten, Server und Client, eine wichtige Rolle. Der Server sollte dem Client die nötigen Angaben machen (Expires), damit der beim nächsten Request im Voraus entscheiden kann, und der Client muss, wenn er entsprechend konfiguriert ist, dem Server mitteilen, dass er die Ressource nicht zwangsläufig neu laden möchte. Im Opera kann man das unter Tools/Preferences/Advanced/History/Check documents bzw. .../Check images einstellen, im Firefox finde ich's gerade nicht (vermutlich wieder eine von den Einstellungen, die nur über about:config erreichbar sind).

    So long,
     Martin

    --
    Der Professor sitzt beim Essen in der Mensa. Ein Student setzt sich ihm unaufgefordert gegenüber.
    Professor: Seit wann essen denn Schwein und Adler an demselben Tisch?
    Student:   Na gut, dann flieg' ich eben zum nächsten Tisch.
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    1. Das klingt alles logisch. Danke erstmal für deine Antwort.
      Ein kleiner Test wegen dem Expire wäre doch in etwa sowas:
      <?php
         //--- setze Expiredate auf 24.12.2012
         echo "test";
      ?>

      Beim ersten Anfragen kommt 200. Bis Weihnachten fragt der Client nicht mehr beim Server an, sofern die Seite im Cache liegt? Ist das so richtig?

      Gruß
      Weihnachtsmann
      T-Rex

      1. Hi,

        Das klingt alles logisch. Danke erstmal für deine Antwort.
        Ein kleiner Test wegen dem Expire wäre doch in etwa sowas:
        <?php
           //--- setze Expiredate auf 24.12.2012
           echo "test";
        ?>

        Beim ersten Anfragen kommt 200. Bis Weihnachten fragt der Client nicht mehr beim Server an, sofern die Seite im Cache liegt? Ist das so richtig?

        wenn er so konfiguriert ist, ja. Bedenke, dass das ganze Caching und die entsprechenden HTTP-Header dazu immer nur Empfehlungen sind. Der Client KANN cachen, muss aber nicht.

        So long,
         Martin

        --
        Er war ein Mann wie ein Baum. Sie nannten ihn Bonsai.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(