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.
Les requêtes sont toujours de simples textes qui peuvent avoir les formes suivantes :
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
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.
__init__(self, str_requete:str) où str_requete est le texte de la requêteurl(self) -> str renvoie l’URL complète de la requête,is_GET(self) -> bool renvoie True si la méthode de la requête est GET,is_POST(self) -> bool renvoie True si la méthode de la requête est POST,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'}
match(self, pattern:str). Celle-ci est complexe, je détaille ci-dessous.On veut pouvoir définir un schéma – pattern pour une URL générique.
Par exemple le schéma <nom>.html.
dossier/monfichier.html, alors le schéma est vérifié et nom = 'dossier/monfichier'. La méthode devrait alors renvoyer {'nom':'dossier/monfichier'}image.jpg, alors le schéma n'est pas vérifié et la méthode devrait renvoyer False.
Autre exemple : le schéma /livre-<id>
/livre-45, alors le schéma est vérifié et id = '45'. La méthode devrait alors renvoyer {'id':'45'}/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-<id>"
# 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 "<id>"
repl = "(?P"+needle+".*)" # ex: propose de remplacer par "(?P<id>.*)"
pattern = re.sub(needle,repl,pattern) # effectue le remplacement
pattern = "^" + pattern + "$"
# l'expression est devenue : "^/livre-(?P<id>.*)$"
# 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<id>.*)$" 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' }