@ -116,27 +116,63 @@ L'un des objectifs des développeur Web est de dessiner la page Web le plus tôt
# Le serveur Web
# Le serveur Web
Nginx/Apache2/Live Server vs Deno => pourquoi séparer (statique vs dynamique ! CORS !) ?
Jusqu'à présent, nous utilisions *Live Server*, via *Visual Studio Code*, afin de tester notre site Web. Cela est bien utile lors de la phase de développement, mais n'est pas adapté pour la phase de production, lorsque le site Web sera mis sur un serveur afin d'être accessible via Internet.
Command line
Il existe des serveurs Web, e.g. Apache, Nginx, qui offrent de nombreuses fonctionnalités et de possibilités de configurations :
BDD API/FileAPI
- réécritures d'URL/redirections ;
! Jamais faire confiance client
- transfert du flux / reverse proxy ;
=> Routes (chemin)
- vérification des droits d'accès / authentification ;
=> body / url
- gestion des caches ;
=> Serveur Python/JS/TS
- cgi/fastcgi ;
- etc.
La distribution du contenu statique est relativement simple, le serveur lit les fichiers, puis les envoie au client. Bien évidemment, peut gérer des fonctionnalités plus avancées comme mettre les fichiers en RAM pour les distribuer plus rapidement, vérifier les droits d'accès aux fichiers (dont authentifications), réécrire les URL, transmettre la requête à un autre serveur, personnaliser l'en-tête de la réponse HTTP, etc.
Pour du contenu dynamique, i.e. généré sur demande par le serveur, il existe plusieurs façons de procéder :
- *CGI :*le serveur Web execute le fichier au lieu de transmettre son contenu au client. Il écrit sur l'entrée standard le corps de la requête, et transmet la sortie standard au client. Cette technique est simple mais peu performante.
- *fastCGI :*analogue au CGI, mais plus performant. Un ou plusieurs processus s'executent en contenu et communiquent avec le serveur Web via des sockets IPC, des sockets TCP, ou via des tubes nommés. C'est notamment ce qui est communément utilisé pour PHP, Ruby on rails, etc.
- *implémenter son propre serveur* qui répondra aux requêtes des clients. Le serveur peut alors supporter plusieurs protocoles en sus de HTTP, e.g. des WebSockets, des sockets TCP, etc. Il peut être implémenté dans n'importe quel langage (e.g. Python, JavaScript, shell), et a donc accès à toutes leurs fonctionnalités et bibliothèques.
- *rediriger le flux* vers un autre serveur (reverse proxy). Quasi-identique à la solution précédente, il a l'avantage de pouvoir bénéficier des fonctionnalités du serveur Web (authentification, cache, etc), ainsi que d'éviter des problèmes de *Same Origin Policy* (SOP).
Le contenu généré peut être sous n'importe quel format : de l'HTML, des images, du texte brut, des données binaires, du JSON, etc. Cependant, il est préférable de séparer la structure de la page Web (HTML/CSS/JS/Images, etc.), des données dynamiques du site Web, cela pour plusieurs raisons :
- la *mise en cache facilitée* de la structure de la page Web statique ;
- *améliore la lisibilité* du code de votre site Web (notamment si la partie dynamique utilise une APIREST) ;
- *découpler la structure de la page Web des données*, permettant ainsi de formatter les données afin de pouvoir facilement les réutiliser pour d'autres usages tout en évitant qu'une modification de la structure de la page Web ne casse tout.
**⚠** Vous ne devez **<u>*JAMAIS*</u>** faire confiance client. En effet, il est très aisé d'envoyer des données arbitraires au serveur. Vous devez ainsi *<u>**SYSTÉMATIQUEMENT**</u>* vérifier la validité des données envoyées par le client (format, valeurs, autorisations, etc).
## Serveur HTTP
Python (x) - Deno (Prog Web)
=> Requête HTTP
=> Requête HTTP
## API REST
=> Routes (chemin)
Une API REST est une manière de concevoir les échanges entre le client et le serveur de sorte à les uniformaliser, les rendre plus compréhensibles, et faciliter les opérations de tests et de déboguages.
=> body / url
=> Serveur Python/JS/TS
## API REST
Une API REST est une manière de concevoir les échanges entre le client et le serveur de sorte à les uniformaliser, les rendre plus compréhensibles, et faciliter les opérations de tests et de déboguages.
Une requête REST est composée de 3 éléments :
Une requête REST est composée de 3 éléments :
@ -146,8 +182,6 @@ Une requête REST est composée de 3 éléments :
- le *corps de la requête* contenant des données envoyées au serveur.
- le *corps de la requête* contenant des données envoyées au serveur.
Une API REST supporte 5 méthodes HTTP :
Une API REST supporte 5 méthodes HTTP :
- *GET :* lire la ressource.
- *GET :* lire la ressource.
@ -160,9 +194,7 @@ Une API REST supporte 5 méthodes HTTP :
- *DELETE :* supprimer une ressource.
- *DELETE :* supprimer une ressource.
L'URI/route des ressources doivent suivre le même format. On appelle *collection* une ressource qui est elle-même un ensemble de ressources. La modification d'une ressource est effectuée de la sorte :
L'URI/routes des ressources doivent suivre le même format. On appelle *collection* une ressource qui est elle-même un ensemble de ressources. La modification d'une ressource est effectuée de la sorte :
- `GET /$COLLECTION/` : obtenir la liste des ressources de la collection.
- `GET /$COLLECTION/` : obtenir la liste des ressources de la collection.
@ -176,8 +208,6 @@ L'URI/routes des ressources doivent suivre le même format. On appelle *collecti
- `DELETE /$COLLECTION/$ID` : supprimer la ressource d'identifiant `$ID` appartenant à la collection.
- `DELETE /$COLLECTION/$ID` : supprimer la ressource d'identifiant `$ID` appartenant à la collection.
Le corps de la requête et de la réponse REST sont usuellement au format JSON, mais peuvent utiliser n'importe quel format (potentiellement déterminé par la requête REST) :
Le corps de la requête et de la réponse REST sont usuellement au format JSON, mais peuvent utiliser n'importe quel format (potentiellement déterminé par la requête REST) :
- URLSearchParams ;
- URLSearchParams ;
@ -190,13 +220,11 @@ Le corps de la requête et de la réponse REST sont usuellement au format JSON,
- etc.
- etc.
Les API REST sont *sans état*, c'est à dire que le serveur n'enrigistre pas l'état de la connexion/session HTTP. L'état est stocké côté client et les données nécessaires sont inclues dans la requête REST.
Les API REST sont *sans état*, c'est à dire que le serveur n'enrigistre pas l'état de la connexion/session HTTP. L'état est stocké côté client et les données nécessaires sont inclues dans la requête REST.
Le fait de ne pas stocker d'état côté serveur permet d'éviter certaines attaques DoS de clients malicieux qui ouvriraient des connexions/sessions HTTP afin de surcharger le serveur. Cela permet aussi de mettre en cache la réponse à certaines requêtes REST, ainsi que de plus facilement répartir l'APIREST sur plusieurs serveur en limitant les problématiques de synchronisations.
Le fait de ne pas stocker d'état côté serveur permet d'éviter certaines attaques DoS de clients malicieux qui ouvriraient des connexions/sessions HTTP afin de surcharger le serveur. Cela permet aussi de mettre en cache la réponse à certaines requêtes REST, ainsi que de plus facilement répartir l'APIREST sur plusieurs serveur en limitant les problématiques de synchronisations.
Pour les opérations de tests et de débogues, le fait qu'il n'y a pas d'état stocké signifie qu'une même requête REST produira le même effet, quel que soit l'état de la connexion/session. Cela permet aussi de mieux comprendre les échanges entre le client et le serveur.
Pour les opérations de tests et de débogues, le fait qu'il n'y a pas d'état stocké signifie qu'une même requête REST produira le même effet, quel que soit l'état de la connexion/session. Cela permet ainsi de mieux comprendre les échanges entre le client et le serveur.
## Websocket
## Websocket
@ -208,7 +236,6 @@ Contrairement aux WebSockets, les *Server Send Events* ne permettent qu'une comm
Le principe est très simple, il s'agit d'une requête et d'une réponse HTTP normales, à l'exception que la réponse HTTP est maintenue en vie (`keep-alive`) et est écrite petit à petit (`text/event-stream`). Le corps de la réponse suit le format suivant :
Le principe est très simple, il s'agit d'une requête et d'une réponse HTTP normales, à l'exception que la réponse HTTP est maintenue en vie (`keep-alive`) et est écrite petit à petit (`text/event-stream`). Le corps de la réponse suit le format suivant :
```
```
event: $EVENT_NAME
event: $EVENT_NAME
data: $DATA
data: $DATA
@ -222,8 +249,6 @@ data: $DATA
Côté client, l'utilisation est très simple, il suffit d'écouter des événements d'un `EventSource`.
Côté client, l'utilisation est très simple, il suffit d'écouter des événements d'un `EventSource`.