Alternativen zum Perl Modul CGI.pm

Aus verschiedenen Gründen wurde CGI.pm aus dem Core entfernt, es ist Anforderungen moderner Webanwendungen nicht mehr gewachsen.

Viele Jahre diente mir das Modul CGI.pm als ein treuer Begleiter beim Entwickeln tausender Webanwendungen, obwohl ich es lediglich zum Parsen von URL-Parameten einsetzte und ungezählte weitere Funktionen dieses Moduls gar nicht nutzte, wie z.B. Funktionen zur Ausgabe von HTTP-Headers und HTML.

Es zeigt sich recht bald, dass direkte Ausgaben von HTTP-Headers und HTML aus einer Perl-Funktion heraus nur noch selten gebraucht werden, oft ist es zweckmäßiger, eine Response als Template zu puffern und unmittelbar vor der Ausgabe auf STDOUT in Richtung Webserver zu rendern. Über die Phase der Pufferung läuft der gesamte CODE in einem try{}-Block um mögliche Exceptions auffangen zu können. Tritt eine Exception auf, wird der bis dahin mit Daten befüllte Puffer verworfen und eine Response zur gezielten Ausgabe der Fehlemeldung erzeugt, konkret ist der dafür verwendete Content-Type stets text/plain, auch dann, wenn im Puffer bereits ein völlig anderer Content-Type, z.B. application/pdf vorliegt.

Auch an der nächsten Frage: In welchem Objekt sollen HTTP Header und Response gepuffert werden? scheitert die Planung, dafür eine Instanz der Klasse CGI einsetzen zu wollen. Vielmehr ergeben sich aus dieser Planung heraus Anforderungen an ein eigenes Objekt, das in der Lage sein muss, die Zusammenstellung der Daten für eine HTP-Response (Header, Body,..) zu puffern und über eigene Methoden verfügt, diese Daten auszugeben. Natürlich ist es hierfür zweckmäßig, HTML-Dokumente in bestimmte Bereiche aufzuteilen, z.B. in einen Kopf-, Body- und Footerbereich sowie Bereiche in denen die Navigation eingebaut ist. Und selbstverständlich muss die Instanz eines Frameworks auch in der Lage sein, HTML-Dokumente zu erzeugen, die anders aufgeteilt sind.

Es spricht also alles für objektorientierte Ansätze und eine eigene Framework-Instanz, im Wesentlichen kommt noch eine wichtige Anforderung hinzu: Die Instanz welche die Response erzeugt, muss auch in der Lage sein, Request-Parameter verarbeiten zu können. Das bedeutet, insbesondere hinsichtlich der Integration von Webservices, AJAX, Remote-Procedure-Call usw., dass neben den bisher unterstützen Content-Types wie application/x-www-form-urlencoded und multipart/form-data eine ganze Reihe weiterer zu unterstützender Enctypes hinzukommen und spätestens hier heißt es Abschied nehmen von CGI.pm (beispielsweise ist es nicht möglich an PUT bzw. POST-Daten zu gelangen wenn einer der hier genannten Enctypes gesendet wurde).

Der Standard CGI/1.1

Im Wesentlichen beschreibt dieser Standard unabhängig vom gesendeten Enctype, über welche Kanäle ein Webserver die Daten weiterzureichen hat. Unter dem Common Gateway sind hierzu die Standard Ein- und Ausgabekanäle STDIN und STDOUT zu verstehen. Sobald also ein HTTP-Client Daten im Message-Body des Requests sendet, hat er dazu im Request-Header Content-Length die Anzahl der gesendeten Bytes zu deklarieren. Diese Angabe setzt der Webserver in eine Umgebungs-Variable CONTENT_LENGTH, so dass ein nachgelagerter Prozess die Daten bytegenau aus STDIN lesen kann. In der Regel spielt sich dieser Vorgang ab bei der Request-Methode POST oder PUT, es ist jedoch jedem HTTP-Client freigestellt, beim Senden von Daten im Message-Body eine beliebig andere Request-Methode zu verwenden oder gar namentlich zu benennen.

Neben dem Message-Body und ebenfalls unabhängig von der Request-Methode kann ein HTTP-Client Daten an den Request-URL hängen. Diese Daten setzt der Webserver in eine weitere Umgebungs-Variable mit dem Namen QUERY_STRING. In der Regel entsprechen Daten im QUERY_STRING dem Enctype application/x-www-form-urlencoded und sind prozentkodiert. Da Leerzeichen in einem URI nicht zulässig sind, ist der QUERY_STRING vom URL-Path mittels ? getrennt. Und neben der Prozentkodierung eines Leerzeichen als %20 kann es auch als + Zeichen kodiert sein.

Die bis hier gemachten Ausführungen verdeutlichn die Vielfalt der Datenübertragung in einem Request. Hinzu kommt, dass ein HTTP-Client weitere Daten auch in speziellen Request-Headers senden kann. Aber auch proprietäre Header setzt der Webserver in Umgebungs-Variablen, so findet sich ein Request-Header x-param in der serverseitigen Umgebungs-Variable HTTP_X_PARAM wieder. In Perl schließlich findet sich die gesamte Serverumgebung im Hash %ENV. Dieser Vielfalt war das Perl-Modul CGI.pm noch nie gewachsen, weil es vom Standard CGI/1.1 abweichende Abhängigkeiten zwischen Enctype und Request-Method beim Parsen mit sich brachte.

Alternativen zu CGI.pm entwickeln

Die Anforderungn lassen sich in einem Satz formulieren: Unabhängig vom im Request-Header deklarierten Content-Type und ebenso unabhängig von der Request-Methode muss es möglich sein, sowohl auf die im Message-Body als auch auf etwaige im URI übermittelten Daten zugreifen zu können.

Nicht die Request-Methode sondern der übermittelte Content-Type legt fest, wo serverseitig die Daten zu erwarten und wie sie zu parsen sind. Beispielsweise teilt ein proprietärer Content-Type: application/body+query dem Server mit, dass sich im Message-Body eine Binary befindet und im URI ein ganz normaler HTTP QUERY_STRING.


Anbieter: nmq​rstx-18­@yahoo.de, die Seite verwendet funktionsbedingt einen Session-Cookie und ist Bestandteil meines nach modernen Aspekten in Perl entwickelten Frameworks.