====== Module requete ======
Nom du fichier : ''%%requete.py%%''
Défini une classe ''Requete'' chargée d’interpréter une requête d'un client reçue par le serveur.
Vous pouvez tester le bon fonctionnement avec le module de test : {{ .:requete.test.py |}}.
===== À quoi ressemblent les requêtes =====
Les requêtes sont toujours de simples textes qui peuvent avoir les formes suivantes :
==== Cas d'une requête GET ====
GET /dossier/sousdossier/test.html HTTP/1.1
Host: localhost:80
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Dans ce cas l’URL demandée est ''%%/dossier/sousdossier/test.html%%''
l’URL peut être plus compliquée. Rien n'empêche d'entrer une URL comme ''%%chose=45-id+74%%''
==== Cas d'une requête POST avec des paramètres ====
POST /dossier/sousdossier/test.html HTTP/1.1
Host: localhost:80
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
x=17&monttexte=blablabla
C'est le cas où l'interface web contient un formulaire permettant à l'utilisateur d'envoyer des données. On utilise une requête POST seulement dans le cas où la requête est susceptible de modifier l'état du serveur (écrire dans la BDD) sinon on utilise une requête GET.
Il existe des requêtes PUT et DELETE mais elles sont moins connues et nous ne les utiliserons pas.
===== Interface de la classe Requete =====
* méthode ''%%__init__(self, str_requete:str)%%'' où ''%%str_requete%%'' est le texte de la requête
* méthode ''%%url(self) -> str%%'' renvoie l’URL complète de la requête,
* méthode ''%%is_GET(self) -> bool%%'' renvoie ''%%True%%'' si la méthode de la requête est GET,
* méthode ''%%is_POST(self) -> bool%%'' renvoie ''%%True%%'' si la méthode de la requête est POST,
* méthode ''%%post_params(self) -> dict%%'' renvoie les paramètres sous forme d'un dictionnaire en cas de requête POST. //Précondition : requête POST//.
Dans l'exemple ci-dessus, le retour serait ''%%{'x':'17', 'montexte':'blablabla'}%%''
* méthode ''%%match(self, pattern:str)%%''. Celle-ci est complexe, je détaille ci-dessous.
==== Méthode match ====
On veut pouvoir définir un schéma -- //pattern// pour une URL générique.
Par exemple le schéma ''%%.html%%''.
* Si l’URL est ''%%dossier/monfichier.html%%'', alors le schéma est vérifié et ''%%nom = 'dossier/monfichier'%%''. La méthode devrait alors renvoyer ''%%{'nom':'dossier/monfichier'}%%''
* Si L’URL est ''%%image.jpg%%'', alors le schéma n'est pas vérifié et la méthode devrait renvoyer ''%%False%%''.
Autre exemple : le schéma ''%%/livre-%%''
* Si l’URL est ''%%/livre-45%%'', alors le schéma est vérifié et ''%%id = '45'%%''. La méthode devrait alors renvoyer ''%%{'id':'45'}%%''
* Si l’URL est ''%%/blabla-18%%'', alors le schéma n'est pas vérifié et la méthode devrait renvoyer ''%%False%%''
Le schéma est donc constitué de parties fixes et de parties ente ''%%<...>%%'' variables qu'il faut récupérer.
Cette méthode nécessite l'utilisation d'**expressions régulières**. Je vous donne ci-dessous un peu d'aide :
# nécessite :
import re
# supposons que pattern = "/livre-"
# et que url = "/livre-475"
regex_tag = "<[^<]*>" # consiste à chercher les <...>
for m in re.finditer(regexTag, pattern): # parcours les <...> trouvés dans pattern
needle = m.group(0) # ex: trouve ""
repl = "(?P"+needle+".*)" # ex: propose de remplacer par "(?P.*)"
pattern = re.sub(needle,repl,pattern) # effectue le remplacement
pattern = "^" + pattern + "$"
# l'expression est devenue : "^/livre-(?P.*)$"
# on peut appliquer l'expression à l'url
retour = re.match(pattern, url)
# en cas d'échec, retour == None
# mais dans notre exemple, c'est un succès :
# "^/livre-(?P.*)$" a bien reconnu "/livre-475" et a extrait id = 475
retour.groupdict()
# cette commande renvoie le résultat sous forme d'un dictionnaire :
# { 'id':'475' }