Beispiel 2: Web-Server mit HTML-Seiten, die per Code erstellt werden.

Dieses Beispiel ergänzt das Beispiel 1. Es wird eine Seite URL "info.html" hinzugefügt, die im Code aufbereitet wird und Informationen über den aktuellen HTTP-Request liefert. Hierzu habe ich den Beispiel-Code aus der Dokumentation des ESPAsyncWebServer, Kapitel Print to response genommen. Dies ist ein Screenshot nach dem Aufruf der Seite mit Firefox:

Ausgabe von 'info.html'

Der zugehörige Programmcode besteht aus knapp 50 Code-Zeilen. Diese kann man natürlich im direkt mit der Web-Server-Klasse "verwursten". Macht man das jedoch mehrfach, blickt man hinterher nicht mehr durch. Deshalb kommt nun die UrsAsyncWebSite-Klasse ins Spiel. Sie erlaubt es, einen "Baukasten" von Web-Sites zu erstellen. Der ESP8266 mit seinem für Mikroprozessoren riesiges Flash und RAM erlaubt es, auch große Projekte umzusetzen. Kapselung ist hier dann eine wichtige Möglichkeit, den Überblick zu behalten.

Eine zweite Seite (URL "hello.html") zeigt, dass der Zugriff auf Membervariablen möglich ist.

Prinzipielle Verwendung

Um einen Web-Server mit Web-Site unter Verwendung von UrsAsyncWebSite zu erstellen, müssen vier Dinge gemacht werden:

  1. Es muss eine Klasse erstellt werden, die von UrsAsyncWebSite abgeleitet ist. Die in dieser Klasse als pure virtual hinterlegten Methoden handleRequest, getUrl und getRewrites müssen dabei überschrieben werden.
  2. Es muss eine Web-Server-Klasse von UrsAsyncWebServer abgeleitet und instanziiert werden. Dies wurde bereits im vorhergehenden Beispiel gezeigt.
  3. Eine Instanz (oder auch mehrere) der Web-Site-Klasse muss als Membervariable der neuen Web-Server-Klasse hinterlegt werden.
  4. Die Instanz muss in der überschriebenen Methode begin der Web-Server-Klasse registriert werden.

1. Die Web-Site-Klassen des Projekts

Das Beispielprojekt beinhaltet zwei von UrsAsyncWebSite abgeleitete Klassen, die den HTML-Code für die Web-Sites bereit stellen.

Konstruktion der Web-Site-Klasse InfoWebSiteClass

class InfoWebSiteClass : public UrsAsyncWebSite {
protected:
  // Handler-Methode, liefert den HTML-Response.
  virtual void handleRequest(AsyncWebServerRequest * request);

  // Liefert die URL für diese Seite.
  virtual String getUrl() { return "info.html"; }

  // Liefert alternative Ressourcen-Bezichnungen.
  virtual String getRewrites() { return "info|inf|about"; }
};

Die Klassendefinition enthält nur drei geschützte virtuelle Methoden, die die entsprechenden pure virtual Methoden der Basis-Klasse überschreiben:

handleRequest im Detail:

Die Methode entspricht im Wesentlichen dem Beispiel Print to response aus der AsyncWebServer-Dokumentation. Deshalb wird diese Methode nur auszugsweise dargestellt.

void InfoWebSiteClass::handleRequest(AsyncWebServerRequest * request) {
  // Response zusammenstellen
  AsyncResponseStream *response = request->beginResponseStream("text/html");
  response->addHeader("Server", "UrsAsyncWebServer");
  response->printf("<!DOCTYPE html><html><head><title>URL: %s</title>", request->url().c_str());

// ...

  response->print("</body></html>");
  // Response absenden
  request->send(response);
}

Konstruktion der Web-Site-Klasse HelloWebSiteClass

class HelloWebSiteClass : public UrsAsyncWebSite {
protected:
  // Individuelle URL für die konkrete Instanz
  String webSiteUrl;

  // Individuelle altenative URLs für die konkrete Instanz
  String webSiteRewrites;

  // Ein beliebiger Text zum einfügen in die Web-Site.
  String webSiteGreeting;

  // Handler-Methode, liefert den HTML-Response.
  virtual void handleRequest(AsyncWebServerRequest * request);

  // Liefert die URL für diese Seite.
  virtual String getUrl() { return webSiteUrl; }

  // Liefert alternative Ressourcen-Bezichnungen.
  virtual String getRewrites() { return webSiteRewrites; }

public:
  // Initialisiert eine neue Instanz von InfoWebSiteClass.
  HelloWebSiteClass(String url, String rewrites, String greeting) :
                    webSiteUrl(url), webSiteRewrites(rewrites), webSiteGreeting(greeting) {}
};

Die Klasse benötigt ein Konstruktor über den die Web-Site-Eigenschaften -wie z.B. die URL- für jede Instanz der Klasse eingestellt werden können.

Anpassungen bei MyWebServerClass

Damit die Seiten auch abrufbar werden, muss die Server-Klasse MyWebServerClass ein wenig angepasst werden.

01: class MyWebServerClass : public UrsAsyncWebServer {
02: protected:
03:   // Überschreibt die Methode 'notFoundHandler' von 'UrsAsyncWebServer'
04:   virtual void notFoundHandler(AsyncWebServerRequest *request);
05: 
06:   InfoWebSiteClass  infoWebSite;
07:   HelloWebSiteClass helloWebSite;
08:   HelloWebSiteClass halloWebSite;
09: 
10: public:
11:   // Initialisiert eine neue Instanz von MyWebServerClass:
12:   MyWebServerClass(int port = 80) : UrsAsyncWebServer(port), 
13:                                     helloWebSite("hello.html", "hello", "Welcome "),
14:                                     halloWebSite("hallo.html", "hallo", "Herzlich willkommen ") {}
15: 
16:   // Startet den Web-Server:
17:   void begin();
18: };

Zeile 4:

Der "notFoundHandler" wird wie im vorhergehenden Beispiel überschrieben.

Zeilen 6..8:

Eine Instanz von InfoWebSiteClass und zwei von HelloWebSiteClass werden als Membervariablen angelegt.

Zeilen 13..14:

Im Konstruktor werden die Variablen der Instanzen von HelloWebSiteClass mit Werten versehen.

In MyWebServerClass::begin müssen die Seiten registriert werden:

void MyWebServerClass::begin() {
  // Web-Sites registrieren (WICHTIG: muss vor serveStatic("/"...) geschehen!)
  registerWebSite(infoWebSite);
  registerWebSite(helloWebSite);
  registerWebSite(halloWebSite);
  
// ...

Wenn alles richtig gemacht wurde, liefern diese Seiten folgenden Output:

Deutscher Text Englischer Text
URL "hallo": Ausgabe des deutschen Textes URL "hello": Ausgabe des englischen Textes

SPIFFS-Dateien

Die Datei "index.html" ist ebenfalls ergänzt wurden. Die neue Variante ist Verzeichnis "data" des Beispiels abgelegt.

Download

Das Beispiel ist als "UrsAsyncWebServerExample2" in der Bibliotheks-ZIP-Datei enthalten.