Kurztipp: Modularer Seiten mit dem Tntnet Template-System ecpp

Standard

In aller Regel hat man auf einer Seite immer wiederkehrende Elemente, wie den Kopfbanner, ein Navigation oder eine Fußzeile. Um die DRY-Regel „Don’t repeat yourself“ zu befolgen, müssen wir also ein Weg finden, wie wir diese immer wiederkehrenden Elente auslagern und in die betreffenden Seiten als externe Elemente wieder einbetten. In Tntnet gibt es verschiedenen Möglichkeiten dieses zu tun. Diese beruhen auf zwei grundlegenden Technologien, die ich hier kurz vorstellen möchte.

Einbetten von Code

Die erste Variante ist die, den Code, der sich immer wiederholt, in eine externe ecpp-Datei auszulagern, und den Code per include an die betreffenden Stellen der ecpp-Views einzubetten. Dieses geschieht über:

<%include>src/view/part/head.ecpp</%include>

Hier wird der Code der Datei „src/view/part/head.ecpp“ eingefügt. Beim Übersetzen der ecpp-Datein wird der Code 1:1 an die betreffende Stelle kopiert. Das Verfahren ist sehr simpel.

Der Vorteil ist, dass schon bei dem Übersetzen des Codes fehlende Abhängigkeiten erkannt werden, z.B. wenn die Datei mit dem zu includierenden Code nicht vorhanden ist.

Der Nachteil ist, dass die Komponenten/Dateien keine eigenen Namensräume haben. Das kann dazu führen, dass es zu unerwünschten Nebeneffekten kommt, z.B. wenn zufällig die gleichen variablen Namen verwendet werden. Ein weitere Nachteil ist, dass das Build-System (GNU Make z.B.) nichts von dem Code-Include weiß. Wenn der Code, der includiert wird, von dem Entwickler geändert wird, weiß das Build-System nicht, dass es alle ecpp-Dateien neu übersetzen muss, in denen der Code includiert wurde.  Also muss man händisch ein „make clean“ ausführen, das wiederum für längere Übersetzungszeiten sorgt. Alternativ kann man versuchen, diese Abhängigkeiten mit Tools wie Autotools abzubilden. Das setzt jedoch ein gesteigertes Wissen über das Build-System voraus.

Einbetten von Komponentenausgaben

Ein anderer Weg ist, die Elemente, die man immer auf verschiedenen Seiten einbetten will, als eigenständige Komponenten umzusetzen. Dazu werden die diese Elemente (Menüs, Banner, Fußzeile, etc.) als eigenständige Komponenten übersetzt. Diese werden dann wiederum zur Laufzeit in der Seite aufgerufen und deren Rückgaben werden dann in die (Gesamt-)Ausgabe eingebettet. Das geschieht über diesen Tag:

 <& core_part_head qparam >

„core_part_head“ ist die Komponente die aufgerufen wird. „qparam“ sind die Request-Parameter des Ausrufs, die an die (Teil-)Komponente weitergereicht wird.

Der Vorteil dieses Verfahren ist, dass das Build-System nicht die Abhängigkeiten kennen muss. Ein weitere Vorteil ist, dass die Komponenten völlig autonom sind und sich untereinander nicht in die Quere kommen können.

Ein Nachteil ist, dass bei dem Aufruf der Teil-Komponente die Aufruf-Parameter weitergereicht werden müssen. Ein weiterer Nachteil ist, dass die Verknüpfung nur sehr locker ist, und nicht zur Übersetzungszeit geprüft wird. Das bedeutet, dass bei einem Schreibfehler des Komponentennamen, dies leider erst zur Laufzeit zu einem Fehler führt.

Ein weiteres Merkmal dieser Variante kann man als Vor- und als Nachteil sehen: Die Teil-Komponenten, also Menüs, Banner, Fußzeilen usw. lassen sich direkt aufrufen, wenn man die URL der Teil-Komponente kennt. Im obigen Beispiel „http://domainname.de/core_part_head„. Zu sehen bekommt man dann das Menü oder die Fußzeile oder was auch immer die Teilkomponente ist.

Das ist kein Drama und lässt sich durch rewrite rules abfangen, nur man muss halt daran denken. Etwas fataler könnte es sein, wenn man seine ACLs (Access Control List) URL-Basiert realisiert. Dann könnte es sein, dass sich ein User quasi „unter dem Radar“ Zugang zu Funktionen verschaffen kann, die für ihn nicht gedacht sind.

Weiterführendes: ecpp manpage: http://www.tntnet.org/man7/ecpp.7.html


Creative Commons Lizenzvertrag

Advertisements

Kurztipp: Routing in Tntnet

Standard

Gestern habe ich eine Weile an einem Routing-Problem geknobelt. Für statische Dateien (statisches html, Bilder, css usw.) gibt es in Tntnet die Möglichkeit diese fest einzukompilieren. Das Verfahren ist in einem Howto ganz gut beschrieben: Static files with Tntnet. Ich hatte nur das Problem, dass ich nicht genau wusste, mit welchem Pfad ich die einkompilierte Datei erreichen kann.

Ich habe jetzt herausgefunden, dass man in die .cpp-Datei vom ecppc hinein schauen kann. Dort findet sich dann dieser Abschnitt:


static const char* urls[] = {
  "./src/core/resources/favicon.ico",
  "./src/core/resources/normalize.css",
  "./src/core/resources/tntnet.png",
  "./src/core/resources/tntwebwizard.css",
};

Das sind die Pfade, unter denen die Dateien später zu erreichen sind. Wurden die Ressourcen beispielsweise in der Datei „resources.cpp“ zusammengestellt, würde die Route so aussehen:


    app.mapUrl("^/core/tntnet.png$", "resources")
        .setPathInfo("./src/core/resources/tntnet.png");

Sie ist im Browser unter der URL „http://meineseite.de/core/tntnet.png&#8220; das Bild „tntnet.png“ zu erreichen ist. Unschön ist der relative Pfad. Das sind die Pfade, die vom ecppc-Kompiler übernommen werden, wenn man ihn so aufruft:


ecppc -bb -z -n resources -p -o bulid/resources ./src/core/resources/favicon.ico ./src/core/resources/normalize.css ./src/core/resources/tntnet.png ./src/core/resources/tntwebwizard.css

Mit dem „-I./src/core/resources“-Flag lässt sich das jedoch ändern:


ecppc -bb -z -I./src/core/resources -n resources -p -o bulid/resources favicon.ico normalize.css tntnet.png tntwebwizard.css

Mit dem „-I“-Flag wird der Pfad angegeben, in dem die Sourcen gesucht werden. Deshalb kann der Pfad verkürzt werden. Jetzt sieht das Routing auch besser aus:


    app.mapUrl("^/core/tntnet.png$", "resources")
        .setPathInfo("tntnet.png");

Dieser Umgang mit statischen Inhalten ist jedoch nur für Dinge geeignet, die sich selten ändern. Das Logo einer Website zum Beispiel. Der Vorteil ist, dass die Inhalte extrem schnell ausgeliefert werden, so dass alle Elemente sich in einer Datei befinden und  Hacker nicht so einfach fremde Inhalte unterschieben können.


Creative Commons Lizenzvertrag