Autor Beitrag
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 481

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Sa 04.10.08 17:21 
Ich hab da mit den Indys einen kleinen Webserver gebaut, bei dem ich noch ein kleines Problem habe.

Und zwar ändern sich die Daten, die der Server bei Anfrage einer speziellen Seite liefern soll, recht schnell. Der Browser benutzt aber manchmal/oft die alte Seite, die er wohl aus dem Cache nimmt, wenn ich über einen Link auf einer anderen Seite die Seite wieder aufrufe.

Wie kann ich den Browser dazu bringen, dass er bei Klick auf einen Link die Seite dahinter neu lädt und nicht die Daten aus dem Cache nimmt?

_________________
We are, we were and will not be.
Hidden
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2242
Erhaltene Danke: 55

Win10
VS Code, Delphi 2010 Prof.
BeitragVerfasst: Sa 04.10.08 17:26 
Gibt es keinen Befehl, um den Cache zu lehren :?:

_________________
Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 481

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Sa 04.10.08 17:33 
Naja, ich will ja nicht den Cache leeren. Ich will nur, dass der Browser irgendwie merkt, dass da was neues hinter dem Link steckt.

Beispiel: Wenn ich hier im posting.php oben auf den Link zu delphi-forum.de/index.php klicke, dann lädt mein Browser die Startseite vom Forum neu, obwohl ich grade eben noch dadrauf war. Wie kann ich dieses Verhalten mit den Indys nachbauen?

_________________
We are, we were and will not be.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Sa 04.10.08 18:21 
Du musst in der Seite ein Pragma: no-cache mitsenden, um dem Browser mitzuteilen, dass die Seite nicht gespeichert werden soll.

Alternativ kannst Du einen Last-Modified-Header senden, damit der Browser bei Dir nachfragt, wann sich die Seite geändert hat und ob er den Inhalt komplett neu laden soll.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Sa 04.10.08 18:23 
Moin!

user profile iconGausi hat folgendes geschrieben Zum zitierten Posting springen:
Ich will nur, dass der Browser irgendwie merkt, dass da was neues hinter dem Link steckt.
Ich hab das hier in einem älteren PHP-Projekt gefunden:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
<?php

header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Datum aus Vergangenheit
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
// immer geändert
header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache"); // HTTP/1.0
Vielleicht kommst du damit weiter. :nixweiss:

Muss aber im Commandhandler in die Headerdaten gesetzt werden, nicht in den Content, IIRC. :?

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Sa 04.10.08 18:33 
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Moin!

user profile iconGausi hat folgendes geschrieben Zum zitierten Posting springen:
Ich will nur, dass der Browser irgendwie merkt, dass da was neues hinter dem Link steckt.
Ich hab das hier in einem älteren PHP-Projekt gefunden:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
<?php

header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Datum aus Vergangenheit
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
// immer geändert
header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache"); // HTTP/1.0
Vielleicht kommst du damit weiter. :nixweiss:

@user profile iconNarses: Das sind exakt jegliche Header, die man benötigt:

  • Expires sagt an, wann die Gültigkeit der ausgelieferten Seite endet. Da diese Zeit Client-Seitig ausgewertet wird, muss man hier oftmals ein Datum in der Vergangenheit angeben, um eine sofortige Revalidierung zu erreichen. Laut RFC würde hier aber i.d.R. ein Datum in der Zukunft stehen, wann die präsentierte Information abläuft.
  • Last Modified: Datum der letzten Änderung (Laut Server-Zeit). Hier kann z.B. das Datum der letzten Aktualisierung deiner Daten stehen.
  • Cache-Control: Sollte IMHO klar sein.
  • Pragma: Die obsolete Version des Cache-Control-Headers. MUSS Aus Kompatibilitätsgründen angegeben werden, um alle Browser abzudecken.


Zusätzlich kann man auch noch mit ETags rumspielen, das ist aber i.d.R. nicht nötig.

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Muss aber im Commandhandler in die Headerdaten gesetzt werden, nicht in den Content, IIRC. :?

cu
Narses

Der header-Befehl von PHP erzeugt einen Antwort-Header, ist doch klar, dass der nicht im Content-Bereich erscheint. Man kann die oben gesendeten Werte über entsprechende META-http-equiv-Angaben auch noch mal im ausgelieferten Dokument verankern.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 481

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Sa 04.10.08 18:47 
Ok, das ist schonmal was. Mit
AResponseInfo.CustomHeaders.Add('Cache-Control: no-store, no-cache, must-revalidate'); scheint das schon zu funktionieren. Sind die anderen Header unbedingt nötig? Ok, die alte Version des Cache-Dingens sehe ich noch ein, aber sind Expires und Modified auch nötig?

Wäre egal, wenn ich das auch noch einfügen müsste, jetzt geht es ums Verstehen. ;-)

_________________
We are, we were and will not be.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Sa 04.10.08 19:04 
Der Expires-Header gibt wie oben geschrieben an, bis wann eine Seite gültig ist. Angenommen, man erlaubt dem Browser die Seite zu cachen, dann würde der Browser erst nach erreichen des Expires-Headers wieder beim Server nachfragen, ob sich was geändert hat. Nun gibt es bei dieser Anfrage zwei Möglichkeiten:

  1. Der Browser sendet den alten Last-Modified-Header in einer "If-Modified-Since"-Anfrage (oder den Expires-Header, wenn kein Last-Modified vorhanden ist) und erfährt, dass sich trotz Ablauf der Antwortgültigkeit nichts geändert hat: Der Browser zeigt seinen bisherigen Content weiter an, fragt aber bei jedem weiteren Aufruf beim Server immer erneut an, wann sich wieder was geändert hat. Der Server sendet in seiner Antwort KEINEN Content-Bereich mit, da der Client diesen ja eh bereits kennt
  2. Der Browser sendet einen If-Modified-Since-Header und bekommt vom Server mitgeteilt, dass eine neuere Version verfügbar ist. In diesem Fall sendet der Server auch gleich die neue Version des Dokuments. Der Browser übernimmt diese Information in seinen Cache, sofern er erlaubt ist, dies zu tun.


Warum sollte man nun diese Header nutzen: Da man im Idealfall Content sparen kann UND die Rechenzeit, um die Antwort zu generieren. Daher sollte man, wenn ein Neuaufbau der Seite nur in unregelmäßigen Abständen nötig ist, das Caching von HTTP nutzen, wenn dies möglich ist ...

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 481

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Sa 04.10.08 19:29 
Um den Traffic gehts mir eher weniger. Das sind in der Regel weniger als 10kb, und wenn man halbwegs was in der Birne hat, nutzt man die Funktion nur im LAN. Der Zugriff nur nach Passworteingabe tut da auch noch was bei.
Um die Serverleistung auch nicht - das Ding ist sowieso eigentlich für nur einen Nutzer ausgelegt - wäre vollkommen unsinnig, wenn 10 Leute gleichzeitig an dem Player rumfummeln. ;-)

Und zu deinen Erklärungen: Der untere Teil in Narses' Auflistungen verbietet dem Browser (so wie ich das verstehe), den Cache zu nutzen. - Wozu also dann die Modified/Expires-Header?

Oder sind das einfach zwei Möglichkeiten, das Problem zu lösen? Das eine etwas eleganter, das andere mit Gewalt?

_________________
We are, we were and will not be.
Yogu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Sa 04.10.08 19:37 
phpBB3 regelt den Download der Anhang-Dateien so:

ausblenden PHP-Code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
  // let's see if we have to send the file at all
  $last_load   =  isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? strtotime(trim($_SERVER['HTTP_IF_MODIFIED_SINCE'])) : false;
  if (strpos(strtolower($browser), 'msie 6.0') === false)
  {
    if ($last_load !== false && $last_load <= $stamp)
    {
      if (@php_sapi_name() === 'CGI')
      {
        header('Status: 304 Not Modified'true304);
      }
      else
      {
        header('HTTP/1.0 304 Not Modified'true304);
      }
      // seems that we need those too ... browsers
      header('Pragma: public');
      header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + 31536000));
      exit();
    }
    else
    {
      header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $stamp) . ' GMT');
    }

Das mit IE6 verstehe ich nicht, wahrscheinlich kann der das ganze nicht, aber sonst ist der Code ganz verständlich. Das exit(); heißt, dass die Datei nicht versendet werden soll, danach kommt nämlich der eigentliche Dateitransfer.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Sa 04.10.08 19:48 
@Yogu: Der IE6 hat einen Bug bei der Behandlung der Cache-Header, wenn nicht die richtigen Statuscodes gesendet werden, daher die Sonderbehandlung. Da wird nix andres gemacht, als explizit einen HTTP-Status 304 zu senden, der besagt, dass sich nix verändert hat.

@Gausi: Wieso nicht ;-) Collaborative Music Listening :mrgreen:

Zu der Geschichte Expires vs. Cache Control:
Übergeordnet sind zuerst einmal die Pragma- und Cache-Control-Direktiven, die angeben ob überhaupt, und wenn ja, was gecacht werden darf. Darauf aufbauend müssen, wenn der Cache verwendet wird, informationen über die Gültigkeitsdauer, bzw. evtl. nötige Updates eingetragen werden, was mit Hilfe der Last-Modified\Expires-Header geschieht.

Nun zum Problem: Leider interpretieren nicht alle Browser alle Header immer unter allen Umständen korrekt (siehe IE6 ;-)). Daher sollte man i.d.R. alle Header senden, um ein Fallback zu haben, wenn die Interpretation eines einzelnen Header-Wertes einmal fehlschlagen sollte.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.