Michael Schröpl: Apache / mod_headers: Header von CGI-Skripten umschreiben

Hallo Leute,

ich versuche gerade, den Apache zu überreden, den HTTP-Header eines CGI-Skripts zu modifizieren.

Das dabei verwendete Modul "mod_headers" zeigt sich allerdings ein wenig störrisch für meinen Geschmack (und meine Kenntnisse in C und Apache-API sind zu erbärmlich, mehr als nur einzelne Zeilen im Quelltext zu ändern und zu sehen, was das bewirkt).

Was ich prima hinkriege, ist das Hinzufügen einzelner Header - sowohl durch explizite Angabe als auch durch implizite (auch mod_expires sitzt mit im Boot - mod_headers alleine kann nur statische Header bauen, und das alleine würde mir nur dann reichen, wenn es keine HTTP/1.0-Clients auf dieser Welt gäbe ...).

Was aber nicht so recht klappen will, ist das Entfernen von HTTP-Headern, welche bereits von dem besagten CGI-Skript erzeugt werden.

Dieses Skript generiert u. a. gzip-komprimierte Ausgaben und realtime-Informationen. Deshalb erzeugt es die beiden ziemlich defensiven HTTP-Header

Cache-Control: no-cache
   Expires: Fri, 22 Aug 1997 11:00:00 GMT

und damit ist "Ende Gelände" für jegliches Caching, egal ob im Browser oder im Proxy-Server.

Nun weiß ich selbst allerdings sehr viel genauer, wann sich der Inhalt der erzeugten Ausgaben dafür eignet, gecached zu werden.
Deshalb möchte ich in bestimmten Fällen diese Header umschreiben:

<Location /das/boese/skript>
    Header         unset     "Cache-control:"
    Header         unset     "Expires:"
    ExpiresDefault "access plus 12 hours"
  </Location>

(ExpiresDefault nehme ich, weil ich ExpiresByType nicht nehmen will - den MIME-Typ dieses Skripts weiß ich nicht sicher genug. Es scheint zwar "text/html" zu sein, aber die entsprechende ExpiresByType-Direktive hat keinen Effekt.)
Ich habe unterschiedliche Locations für verschiedene Instanzen des Skripts, welche ich als Apache-Handler an Dokumente unterschiedlicher Caching-Klassen binde.
(Das wirkt dann so ähnlich, als wenn *.shtml ein SSI-Dokument mit Caching-Befugnis wäre und *.ssi ein SSI-Dokument mit echt dynamischen Daten - nur so als Anschauungsbeispiel. Bei mir sind es halt eigene Dokumentklassen.)

Das Ergebnis ist leider für meine Zwecke bisher unzureichend:

  • ExpiresDefault erzeugt zwar brav sein
      "Cache-Control:" (dem ich per Quelltext-Änderung
      in mod_expires noch schnell ein "private," verpaßt
      habe) und ein "Expires:", aber
  • die beiden "Header unset" haben keinerlei erkennbaren
      Effekt.
    "Header unset" angewendet auf Header, welche ich selbst zuvor per "Header set" erzeugt habe, funktioniert allerdings durchaus.
    Bloß an die Header des CGI-Skripts komme ich nicht ran.

Und die "Location" wird auch wirklich betreten, wie ich an den anderen Header-Modifikationen erkennen kann (ich setze u. a. einen Phantasie-Header, nur um genau das überprüfen zu können).

Als Ergebnis entsteht ein HTTP-Header mit _zwei_ Headern jedes dieser beiden Typen ... und den möchte ich den armen Browsern ungerne um die Ohren hauen.

Deshalb nun meine Fragen:

  • Hat jemand vielleicht schon mal erfolgreich
      mod_headers eingesetzt, um den Inhalt der HTTP-Header
      eines CGI-Skripts (!) nachträglich zu beeinflussen?
  • Hat jemand eine Idee, was ich verkehrt mache?

Viele Grüße
      Michael
(der sich bewußt ist, daß dies hier ein exotisches Randgebiet ist ... aber die Hoffnung stirbt zuletzt)

P.S.: Nein, ich kann _nicht_ einfach das Skript
      umschreiben. Definitiv nicht. Selbst mit UNIX-
      "strings" war in dem Binary nichts zu finden,
      was patchable ausgesehen hätte. :-(

  1. Deshalb nun meine Fragen:

    • Hat jemand vielleicht schon mal erfolgreich
        mod_headers eingesetzt, um den Inhalt der HTTP-Header
        eines CGI-Skripts (!) nachträglich zu beeinflussen?
    • Hat jemand eine Idee, was ich verkehrt mache?

    Hängt möglicherweise an der Reihenfolge der Module?

    P.S.: Nein, ich kann _nicht_ einfach das Skript
          umschreiben. Definitiv nicht. Selbst mit UNIX-
          "strings" war in dem Binary nichts zu finden,
          was patchable ausgesehen hätte. :-(

    Ein Binary ist übrigens kein Script...

    Wie auch immer. Im Zweifelsfall ein Script oder Binary davorschalten, welches das eigentliche CGI selbst fork&exec'd. Ausgabe absaugen und Header veraendern. Im Grunde nichts, was der Apache nicht auch machen wuerde... Unter Unix.

    1. Hi,

      • Hat jemand vielleicht schon mal erfolgreich
          mod_headers eingesetzt, um den Inhalt der HTTP-Header
          eines CGI-Skripts (!) nachträglich zu beeinflussen?
        Hängt möglicherweise an der Reihenfolge der Module?

      Hm, ich nehme die Reihenfolge, welche APACI standardmäßig vorgibt ... ich lade keine Module, ich habe alles fest eincompiliert.

      Im Zweifelsfall ein Script oder Binary
      davorschalten, welches das eigentliche CGI selbst
      fork&exec'd.
      Ausgabe absaugen und Header veraendern.
      Im Grunde nichts, was der Apache nicht auch machen
      wuerde... Unter Unix.

      Das kann ich aber leider auch nicht machen. Das Binary generiert HTML-Code, in welchem Links auf sich selbst hart eincodiert sind. Ich müßte die generierten Dokumente parsen und on the fly umschreiben ... weia.

      Ich kann das Ding auch nicht einfach per exec aufrufen, weil es eine HTTP-Umgebung braucht (u. a. einen Cookie und die üblichen CGI-Environment-Variablen wie PATH_TRANSLATED).
      Ich _kann_ es aus einem eigenen CGI-Skript per LWP::UserAgent aufrufen und ihm diese Umgebung emulieren (das habe ich sogar schon fertig hier herum liegen, es nützt mir bloß wenig), das ist aber ein Riesenaufwand und alles andere als performant ...

      Wenn mod_headers einfach das tun würde, was es laut Handbuch tun soll, wäre ich wunschlos glücklich.
      Ich habe allerdings den Eindruck, daß die von einer CGI-Anwendung (besser? ;-) erzeugten HTTP-Header zum Zeitpunkt des Eingriffs von mod_headers (noch?) nicht im selben Apache-internen Puffer stehen wie diejenigen, welche der Apache selbst hinzufügt ... deshalb funktioniert beispielsweise auch das Verschmelzen von Headern ("Header append") nicht mit diesen Headern, sondern es werden eben Header doppelt erzeugt.

      Viele Grüße
            Michael

      1. Im Zweifelsfall ein Script oder Binary
        davorschalten, welches das eigentliche CGI selbst
        fork&exec'd.
        Ausgabe absaugen und Header veraendern.
        Im Grunde nichts, was der Apache nicht auch machen
        wuerde... Unter Unix.

        Das kann ich aber leider auch nicht machen. Das Binary generiert HTML-Code, in welchem Links auf sich selbst hart eincodiert sind. Ich müßte die generierten Dokumente parsen und on the fly umschreiben ... weia.
        Ich kann das Ding auch nicht einfach per exec aufrufen, weil es eine HTTP-Umgebung braucht (u. a. einen Cookie und die üblichen CGI-Environment-Variablen wie PATH_TRANSLATED).

        Mir faellt zu mod_headers nichts weiter ein, daher mal weiter mit der Alternative:

        Noe. Die Umgebung wird vererbt, dementsprechend muesste das tolle Binary alles richtig ausspucken. Wenn nicht, kannst du auch gezielte Aenderungen vornehmen und dem Teil was vorgaukeln.
        Sogar der STDIN wird vererbt (im Falle von POST-Requests), sollte also alles eigentlich kein Problem sein.

        Voraussetzung: boeses Binary umbenennen/verschieben, Vorschaltscript stattdessen unter der URL abrufbar machen