38. Praktische Übung: Version 18
38.1. Implementierung

Der Ordner [impots/http-servers/13] wird zunächst durch Kopieren des Ordners [impots/http-servers/12] erstellt und anschließend teilweise geändert.
Wir beginnen damit, der Datei [configs/parameters] einen neuen Parameter hinzuzufügen:
…
# token csrf
"with_csrftoken": False,
# bases gérées MySQL (mysql), PostgreSQL (pgres)
"databases": ["mysql", "pgres"],
# préfixe des URL de l'application
# mettre la chaîne vide si on ne veut pas de préfixe ou /préfixe sinon
"prefix_url": "/do",
# url racine du serveur Apache - mettre la chaîne vide pour une exécution en-dehors d'Apache
"application_root": "/impots"
…
Zeile 10: Der Parameter [application_root] steht für den WSGI-Alias des virtuellen Apache-Servers.
Mit diesem Parameter können wir die Anweisung [responses/HtmlResponse] korrigieren, die den Fehler verursacht hat:

…
# now it's time to generate the URL redirection, not forgetting the CSRF token if requested
if config['parameters']['with_csrftoken']:
csrf_token = f"/{generate_csrf()}"
else:
csrf_token = ""
# redirect response
return redirect(f"{config['parameters']['application_root']}{config['parameters']['prefix_url']}{ads['to']}{csrf_token}")
, status.HTTP_302_FOUND
- Zeile 9: Wir haben den Anwendungsstamm an den Anfang der URL des Umleitungsziels angefügt;
Außerdem müssen wir alle Fragmente so korrigieren, dass die darin enthaltenen URLs mit dem Anwendungsstamm (oder dem WSGI-Alias) beginnen:

Das Fragment [v-authentication]
<!-- form HTML - post its values with the [authenticate-user] action -->
<form method="post" action="{{modèle.application_root}}{{modèle.prefix_url}}/authentifier-utilisateur{{modèle.csrf_token}}"
>
<!-- title -->
<div class="alert alert-primary" role="alert">
<h4>Veuillez vous authentifier</h4>
</div>
…
</form>
Das [v-calcul-impot]-Fragment
<!-- form HTML posted -->
<form method="post" action="{{modèle.application_root}}{{modèle.prefix_url}}/calculer-impot{{modèle.csrf_token}}">
<!-- 12-column message on blue background -->
…
</form>
Das [v-liste-simulations]-Fragment
…
{% if modèle.simulations is defined and modèle.simulations|length!=0 %}
…
<!-- simulation table -->
<table class="table table-sm table-hover table-striped">
…
<tr>
<th scope="row">{{simulation.id}}</th>
<td>{{simulation.marié}}</td>
<td>{{simulation.enfants}}</td>
<td>{{simulation.salaire}}</td>
<td>{{simulation.impôt}}</td>
<td>{{simulation.surcôte}}</td>
<td>{{simulation.décôte}}</td>
<td>{{simulation.réduction}}</td>
<td>{{simulation.taux}}</td>
<td><a href="{{modèle.application_root}}{{modèle.prefix_url}}/supprimer-simulation/{{simulation.id}}{{modèle.csrf_token}}">Supprimer</a></td>
</tr>
{% endfor %}
</tr>
</tbody>
</table>
{% endif %}
Das [v-menu]-Fragment
<!-- bootstrap menu -->
<nav class="nav flex-column">
<!-- display a list of links HTML -->
{% for optionMenu in modèle.optionsMenu %}
<a class="nav-link" href="{{modèle.application_root}}{{modèle.prefix_url}}{{optionMenu.url}}{{modèle.csrf_token}}">{{optionMenu.text}}</a>
{% endfor %}
</nav>
Die obigen Fragmente verwenden alle das Modell [model.application_root]. Derzeit existiert der Schlüssel [application_root] nicht in den von den Modellklassen generierten Modellen.

Die Klasse [AbstractBaseModelForView], die die Oberklasse aller Klassen ist, die eine Vorlage generieren, sieht wie folgt aus:
- Zeile 15: Die Methode [update_model] ist dafür zuständig, Folgendes zur View-Vorlage hinzuzufügen:
- Zeile 24: das CSRF-Token;
- Zeile 26: das URL-Präfix;
- Zeile 28: das Anwendungsstammverzeichnis oder den WSGI-Alias;
Die vier untergeordneten Klassen rufen die übergeordnete Klasse mit dem folgenden Code auf:
…
# actions possibles à partir de la vue
modèle['actions_possibles'] = ["afficher-vue-authentification", "authentifier-utilisateur"]
# finition du modèle par la classe parent
super().update_model(modèle, config)
# on rend le modèle
return modèle
- Zeile 6: Jede Unterklasse ruft ihre Oberklasse auf, um das von ihr erstellte Modell zu aktualisieren;
Version 18 ist fertig. Wir verwenden die beiden virtuellen Apache-Server aus Version 17 wieder und passen sie an:

Die beiden [flask-imports-withXX.conf]-Dateien werden an nur einer Stelle geändert:
# dossier du script .wsgi
define ROOT "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/impots/http-servers/13/apache"
# nom du site web configuré par ce fichier
# ici il s'appellera flask-impots-withmysql
# les URL seront du type http(s)://flask-impots-withmysql/path
define SITE "flask-impots-withmysql"
# mettre l'adresse IP 127.0.0.1 pour site SITE dans c:/windows/system32/drivers/etc/hosts
# mettre ici les chemins des bibliothèques Python à utiliser - les séparer par des virgules
# ici les bibliothèques d'un environnement virtuel Python
WSGIPythonPath "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/venv/lib/site-packages"
# Python Home - nécessaire uniquement s'il y a plusieurs versions de Python installées
# WSGIPythonHome "C:/Program Files/Python38"
# URL HTTP
<VirtualHost *:80>
# avec l'alias / les URL auront la forme /{prefixe_url}/action/...
# avec l'alias /impots les URL auront la forme /impots/{prefixe_url}/action/...
# où [prefixe_url] est défini dans parameters.py
WSGIScriptAlias /impots "${ROOT}/main_withmysql.wsgi"
…
</VirtualHost>
# URL sécurisées avec HTTPS
<VirtualHost *:443>
# avec l'alias / les URL auront la forme /{prefixe_url}/action/...
# avec l'alias /impots les URL auront la forme /impots/{prefixe_url}/action/...
# où [prefixe_url] est défini dans parameters.py
WSGIScriptAlias /impots "${ROOT}/main_withmysql.wsgi"
..
</VirtualHost>
- Zeile 12: Wir verwenden nun das Verzeichnis [taxes/http-servers/13/apache].
Wir sind bereit, Version 18 unter Apache zu testen. Die Konfiguration lautet wie folgt:
- Der WSGI-Alias lautet in beiden Konfigurationsdateien für virtuelle Server /impots;
- in der Konfigurationsdatei [configs/parameters] lauten die Parameter wie folgt:
# token csrf
"with_csrftoken": False,
# préfixe des URL de l'application
# mettre la chaîne vide si on ne veut pas de préfixe ou /préfixe sinon
"prefix_url": "/do",
# url racine du serveur Apache - mettre la chaîne vide pour une exécution en-dehors d'Apache
"application_root": "/impots"
Wir starten den Apache-Server und die beiden DBMS. Wir rufen die URL [https://flask-impots-withmysql/impots/do] auf. Die Antwort des Servers lautet wie folgt:

Wir sehen nun die Anmeldeseite, auf die wir in der vorherigen Version nicht zugreifen konnten. Der Rest der Anwendung funktioniert einwandfrei.
Nun testen wir den anderen virtuellen Server. Wir rufen die URL [https://flask-impots-withpgres/impots/do] auf. Die Antwort des Servers lautet wie folgt:

Die Konzepte von WSGI-Aliasen und URL-Präfixen dienen demselben Zweck. Eines dieser beiden Konzepte ist überflüssig. Um Apache-Server-URLs mit der Zeichenfolge [/impots/do] zu versehen, gibt es also drei Möglichkeiten:
1 – [WGSIAlias /impots] und [prefix_url=’/do’];
2 – [WGSIAlias /] und [prefix_url=’/impots/do’];
3 – [WGSIAlias /impots/do] und [prefix_url=’’];
38.2. Konsolentests
Wir verwenden erneut die Client-Konsolentests [http-clients/09]:

- Die Server-URL muss in den Konfigurationen [1] und [3] geändert werden;
- es muss eine Änderung an der [dao]-Schicht vorgenommen werden, damit diese das HTTPS-Protokoll des Apache-Servers unterstützt;
In den [config]-Dateien lautet die Server-URL nun wie folgt:
"server": {
# "urlServer": "http://127.0.0.1:5000",
# "urlServer": "http://127.0.0.1:5000/do",
"urlServer": "https://flask-impots-withmysql/impots/do",
"user": {
"login": "admin",
"password": "admin"
},
"url_services": {
…
}
},
# mode debug
"debug": True,
# csrf_token
"with_csrftoken": False,
- Zeile 4: die neue Server-URL. Zum ersten Mal in diesem Dokument verwendet der Client das HTTPS-Protokoll;
Die Klasse [ImpôtsDaoWihHttpSession] in der [dao]-Schicht entwickelt sich wie folgt:
- In Zeile 26 fügen wir den Parameter [verify=False] hinzu, da der Apache-Server das HTTPS-Protokoll verwendet. Das Modul [requests] (Zeile 19) unterstützt das HTTPS-Protokoll nativ. Standardmäßig überprüft es die Gültigkeit des vom HTTPS-Server gesendeten Sicherheitszertifikats und löst eine Ausnahme aus, wenn das empfangene Zertifikat ungültig ist. Dies ist hier der Fall, da der Apache-Server von Laragon ein selbstsigniertes Zertifikat sendet. Um die Ausnahme zu vermeiden, verwenden wir den Parameter [verify=False], um dem Modul [requests] mitzuteilen, keine Ausnahme auszulösen. [requests] zeigt dann lediglich eine Warnung auf der Konsole an.
Nach diesen Änderungen sollten alle Konsolentests funktionieren.