From eb0302ee487fedcfa6f7d98e067f56e937fccee8 Mon Sep 17 00:00:00 2001 From: denmigda Date: Tue, 12 Dec 2023 17:45:20 +0100 Subject: [PATCH] Add HTTP Server --- Web/X - API JS-DOM/index.md | 4 +- .../index.md | 159 +++++++++++++++++- 2 files changed, 155 insertions(+), 8 deletions(-) diff --git a/Web/X - API JS-DOM/index.md b/Web/X - API JS-DOM/index.md index 15e98a1..c3d3609 100644 --- a/Web/X - API JS-DOM/index.md +++ b/Web/X - API JS-DOM/index.md @@ -282,7 +282,7 @@ function create(tagname: T, else elem.setAttribute(name, value); } - + for(let name in dataset) { const value = dataset[name]; @@ -461,7 +461,7 @@ $ELEM.dispatchEvent( CustomEvent.new($EVENT_TYPE, {"detail": $EVENT_DATA}) ) 💡 Vous pouvez aussi ajouter, au 2Ăšme argument, l'option `bubble: true` pour faire en sorte que l'Ă©vĂ©nement soit bubble, i.e. se propage dans le DOM (par default `bubble: false`). -# Envoyer une requĂȘte REST +# Envoyer une requĂȘte HTTP ```javascript // [JS] Javascript diff --git a/Web/X - Communications Client-Serveur/index.md b/Web/X - Communications Client-Serveur/index.md index 74cc824..b5c788a 100644 --- a/Web/X - Communications Client-Serveur/index.md +++ b/Web/X - Communications Client-Serveur/index.md @@ -160,19 +160,166 @@ Le contenu gĂ©nĂ©rĂ© peut ĂȘtre sous n'importe quel format : de l'HTML, des imag ## Serveur HTTP -Python (x) - Deno (Prog Web) +Un serveur HTTP rĂ©pond aux *requĂȘtes HTTP* du client par une *rĂ©ponse HTTP*. Les requĂȘtes et rĂ©ponses HTTP se composent d'un *en-tĂȘte* (header) contenant les mĂ©ta-donnĂ©es, et d'un *corps* (body) contenant les donnĂ©es Ă©changĂ©es. + +L'en-tĂȘte de la requĂȘte contient ainsi l'URI demandĂ©e et la *mĂ©thode HTTP*. L'en-tĂȘte de la rĂ©ponse contient le *code de status* de la rĂ©ponse (200 si tout c'est bien passĂ©). Cf la section *"Envoyer une requĂȘte HTTP"* de la fiche *API JS/DOM* pour plus de dĂ©tails. + + + +CĂŽtĂ© serveur HTTP, on manipule des routes. Une route reprĂ©sente un ensemble d'URI qui seront traitĂ©es par le mĂȘme gestionnaire. Il peut contenir des paramĂštres e.g. `/dir/$PARAM/foo` qui seront exploitĂ©s par le gestionnaire (handler). + + + +Afin de rendre le code plus lisible, il est frĂ©quent que les frameworks reprĂ©sentent les routes par une arborescence de fichiers. Au dĂ©marrage, le framework va ainsi lire de maniĂšre rĂ©cursive un dossier e.g. `/routes/` et ajouter les diffĂ©rents gestionnaires en fonction des fichiers qui s'y trouvent. Ainsi, le fichiers/dossier `/routes/dir/{PARAMS}/foo` contiendra le gestionnaire Ă  utiliser pour la route `/dir/$PARAM/foo`. + +đŸš© [TODO] : outils network + +### Serveur HTTP (bas niveau) + +```typescript +// [TS] TypeScript +// ExĂ©cuter le fichier : deno run --allow-net --allow-env $FILE + +// @deno-types="npm:@types/express@4" +import express from "npm:express"; +import cors from "npm:cors" + +const app = express(); +app.use(cors()) // CORS - Autorise l'accĂšs Ă  partir d'autres domaines. + +// ConsidĂ©rer que le corps des requĂȘtes est du texte brut. +// .raw() permet d'obtenir des donnĂ©es binaires. +// .json() si le corps des requĂȘtes est systĂ©matiquement du JSON. +app.use(express.text()); + +// --------------------------------------------- +// ---------- ROUTES --------------------------- +// --------------------------------------------- + +// Ajouter une route (mĂ©thode HTTP GET) +app.get($ROUTE, (request, response) => { + + // Affiche les paramĂštres de la requĂȘte GET. + console.log(request.query); + + response.send($DATA); // $DATA est une chaĂźne de charactĂšre. +}); + +// Ajouter une route (mĂ©thode HTTP POST) +app.post($ROUTE, (request, response) => { + + // Affiche le corps de la requĂȘte POST. + console.log(request.body); + + response.send($DATA); +}); + +// Renvoyer du JSON dans la rĂ©ponse +app.get($ROUTE, (request, response) => { + response.json($DATA); // $DATA est un object. +}); + +// Avec un paramĂštre dans la route +app.get("/dir/:param/foo", (request, response) => { + response.send(request.params.param); +}); + +// Retourner un code d'erreur +app.get("*", (request, response) => { + response.status(404).send("Not found"); +}); + +// --------------------------------------------- + +const port = Number(Deno.env.get("PORT")) || 3000; +app.listen(port, () => { + console.log(`Listening on http://localhost:${port}...`); +}); + + +``` + +```python +# [🐍] Python +from aiohttp import web + +# CORS +import aiohttp_cors + +app = web.Application() + +######################################################### +########### ROUTES ###################################### +######################################################### + +routes = web.RouteTableDef() + +# Ajouter une route (mĂ©thode HTTP GET) +@routes.get($ROUTE) +async def myhandler(request): + + # Affiche les paramĂštres de la requĂȘte GET. + print(request.rel_url.query) + + return web.Response(text=$DATA) # $DATA est une chaĂźne de charactĂšres. + +# Ajouter une route (mĂ©thode HTTP POST) +@routes.post($ROUTE) +async def myhandler(request): + + body = await request.text # pour du texte. + body = await request.json # pour du JSON. + print(body) + + return web.Response(text=$DATA) + +# Renvoyer du JSON dans la rĂ©ponse +@routes.get($ROUTE) +async def myhandler(request): + web.json_response($DATA); # $DATA est un dictionaire. + +# Avec un paramĂštre dans la route. +@routes.get("/dir/{param}/foo") +async def myhandler(request): + param = request.match_info.get('param', None) + print(param) + web.Response(text=$DATA) + +# Retourner un code d'erreur +@routes.get("*") +async def myhandler(request): + raise web.HTTPNotFound("Not found") + # ou request.Response(text="Not found", status=404) + +app.add_routes(routes) + +######################################################### + +# CORS - Autorise l'accĂšs Ă  partir d'autres domaines. +cors = aiohttp_cors.setup(app, defaults={ + "*": aiohttp_cors.ResourceOptions( + allow_credentials=True, + expose_headers="*", +        allow_headers="*" + ) +}) + +if __name__ == '__main__': + web.run_app(app) + +``` + + + +### Serveur HTTP (avec arborescence de routes) -=> RequĂȘte HTTP -    => Routes (chemin) -    => 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 API REST est une maniĂšre de concevoir les Ă©changes HTTP 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 API REST est donc implĂ©mentĂ©e par un serveur HTTP. Une requĂȘte REST est composĂ©e de 3 Ă©lĂ©ments :