Skip to content

Instantly share code, notes, and snippets.

@yostane
Last active May 18, 2021 11:01
Show Gist options
  • Select an option

  • Save yostane/fcf387d92409b5f872dff226ac866be9 to your computer and use it in GitHub Desktop.

Select an option

Save yostane/fcf387d92409b5f872dff226ac866be9 to your computer and use it in GitHub Desktop.
bie2 1922 fsjs
"use strict";
const http = require("http");
// Cet exercice utilise le module http de nodejs
// documentation: https://nodejs.org/api/http.html et https://www.w3schools.com/nodejs/nodejs_http.asp
/**
* créer un serveur nodejs qui affiche dans la console les champs suivants de la requête client: url, headers, method
* Le serveur répond au client avec une réponse http dont le coprs contient la date à laquelle il a reçu la requete
* Documentation: https://nodejs.org/api/http.html#http_class_http_incomingmessage
*/
const serverQ1 = http.createServer((req, res) => {
console.log("url", req.url);
console.log("headers", req.headers);
console.log("method", req.method);
res.end();
});
serverQ1.listen(10001);
/** Appeler le serveur en lui passant différentes valeurs de header, path et method
* astuce: utiliser un client REST comme le REST Client de VSCode ou Postman
* -> voir requests.http
*/
/**
* Ecrire un serveur nodejs qui traite les url au format /:n où n est un entier, puis affiche la valeur de n la console
* Le serveur répond au client avec une réponse http dont le corps contient la valeur n
* Le serveur répond au client avec un statut 400 (correspond à un Bad Request) si l'url ne respecte pas le format
* Les urls avec plus d'un '/' ne sont pas autorisées
* Exemples d'appels au serveur: http://localhost:port/10, http://localhost:port/265
* astuce: fonction parseInt "/10"
*/
const serverQ3 = http.createServer((req, res) => {
const splits = req.url.split("/");
// /hello/12 -> split('/') -> ["", "hello", 12]
const n = parseInt(splits[1]);
if (splits.length > 2 || isNaN(n)) {
res.writeHead(400, "param is not a number or incorrect url");
res.end();
return;
}
console.log(n);
res.end(splits[1]);
});
serverQ3.listen(10003);
/**
* Ecrire un serveur nodejs qui récupère les url au format /:route où 'route' est une chaine de caractères
* Selon la valeur de 'route' le serveur répond au client avec le corps suivant:
* 'hello' => '<h1>hello</h1>'
* 'index.html' => '<html><body><h1>welcome</h1></body></html>'
* 'about' => '<html><body><h1>a propos</h1></body></html>'
* 'data' => '{ "server" : "nodejs" }' avec un header "Content-type" valué à "application/json"
* autre route => '<html><body><h1>Cette page n'existe pas</h1></body></html>' et un status 404
* Exemples d'appels au serveur: http://localhost:port/apropos, http://localhost:port/hello
*
*/
const serverQ4 = http.createServer((req, res) => {
const splits = req.url.split("/");
if (splits.length > 2) {
res.writeHead(404, "incorrect url"); //écrit la première ligne de la réponse
res.end("<html><body><h1>Cette page n'existe pas</h1></body></html>");
return;
}
switch (splits[1]) {
case "hello":
res.end("<h1>hello</h1>");
break;
case "index.html":
res.end("<html><body><h1>welcome</h1></body></html>");
break;
case "about":
res.end("<html><body><h1>a propos</h1></body></html>");
break;
case "data":
res.setHeader("Content-type", "application/json");
res.end('{ "server" : "nodejs" }');
break;
default:
res.writeHead(404, "incorrect url");
res.end("<html><body><h1>Cette page n'existe pas</h1></body></html>");
break;
}
});
serverQ4.listen(10004);
"use strict";
const fsp = require("fs/promises");
const fs = require("fs");
const http = require("http");
/**
* Créer un fonction qui prend en paramètre le cehmin d'un fichier et qui affcihe son contenu textuel
* astuce: voir module node "fs"
* https://www.w3schools.com/nodejs/nodejs_filesystem.asp
* Créer un fichier "static/index.html" et utiliser la fonction pour afficher le contenu du fichier
*/
function readFile(Path) {
fs.readFile(Path, "utf8", (err, data) => {
if (err) {
console.error(err);
return;
}
console.log(data);
});
}
readFile("static/index.html");
/**
* Créer un fonction qui prend en paramètre le chmin d'un fichier et qui affcihe son contenu textuel
* astuce: voir module node "fs/promise"
* https://www.codota.com/code/javascript/modules/fs%2Fpromises, https://www.codota.com/code/javascript/functions/fs-promise/readFile
* Créer un fichier "static/about.html" et utiliser la fonction pour afficher le contenu du fichier
*/
async function readFilePromiseAsync(path) {
const readValuPromise = fsp.readFile(path, "utf8");
const data = await readValuPromise;
console.log(data);
console.log(readValuPromise);
}
readFilePromiseAsync("static/about.html");
/**
* Créer un serveur qui donne une réponse différente selon l'url:
* /index.html -> répond avec le conteu du fichier index.html stocké dans le dossier serveur 'static/index.html'
* /about.html -> répond avec le conteu du fichier about.html stocké dans le dossier serveur 'static/about.html'
* /styles/style.css -> répond avec le conteu du fichier style.css stocké dans le dossier serveur 'static/style.css'
* /scripts/main.js -> répond avec le conteu du fichier style.css stocké dans le dossier serveur 'static/main.js'
* ! index.html doit importer "styles/style.css" et "scripts/main.js".
* ! Faites en sorte que le clic que une balise dans index.html appelle une méthode dans main.js
* /api/fibo -> répond avec un terme n de fibonacci. n étant un nombre alétoire entre 7 et 42
* /api/fibo/:n -> répond avec le terme n de fibonacci
* /api/fibo/:n1/:n2 -> réponde avec un json avec ce format { 'n1': F(n1), 'n2': F(n2) }.
* Par exemple: /api/fibo/10/1 => { '10': 55, '1': 1 }
* astuce: utiliser string.split('/') pour séparer les parties de l'url
*
* Le fichier main.js est exécuté par le client ou serveur ?
* Le fichier main.js est hébérgé chez le client ou le serveur ?
*
* /api/fibo, /api/fibo/:n, /api/fibo/:n1/:n2 sont appelés des endpoints ou des verbes
*/
async function getFileContentAsync(path) {
const readValuPromise = fsp.readFile(path, "utf8");
return await readValuPromise;
}
function getRandomInteger(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
function getFibonacci(n) {
let numberOne = 0;
let numberTwo = 1;
let sum = 0;
for (let i = 2; i <= n; i++) {
sum = numberOne + numberTwo;
numberOne = numberTwo;
numberTwo = sum;
}
return numberTwo;
}
function handleNaNError(res) {
res.writeHead(400, "NaN");
res.end();
}
const serverQ3 = http.createServer(async (req, res) => {
switch (req.url) {
case "/index.html":
const data = await getFileContentAsync("static/index.html");
res.end(data);
return;
case "/about.html":
res.end(await getFileContentAsync("static/about.html"));
return;
case "/styles/style.css":
res.setHeader("Content-type", "text/css");
res.end(await getFileContentAsync("static/style.css"));
return;
case "/scripts/main.js":
res.setHeader("Content-type", "text/javascript");
res.end(await getFileContentAsync("static/script.js"));
return;
case "/api/fibo":
const fibo = getFibonacci(getRandomInteger(7, 42));
res.end(`${fibo}`);
return;
}
const splits = req.url.split("/");
switch (splits.length) {
case 4:
const n = parseInt(splits[3]);
if (isNaN(n)) {
handleNaNError(res);
return;
}
res.end(`${getFibonacci(n)}`);
return;
case 5:
const n1 = parseInt(splits[3]);
const n2 = parseInt(splits[4]);
if (isNaN(n1) || isNaN(n2)) {
handleNaNError(res);
return;
}
res.setHeader("Content-type", "application/json");
res.end(
`{ "${n1}" : ${getFibonacci(n1)} , "${n2}" : ${getFibonacci(n2)} }`
);
return;
}
// api
res.writeHead(404);
res.end();
});
serverQ3.listen(10013);
/**
* Optimiser le serveur précédent en évitant de recalculer les termes de fibonacci déjà calculés
*/
const suiteFibo = [0, 1];
function calculerFiboOpti(n) {
if (suiteFibo[n] != undefined) {
console.log("valeur en cache");
return suiteFibo[n];
}
for (let i = suiteFibo.length; i <= n; i++) {
suiteFibo[i] = suiteFibo[i - 1] + suiteFibo[i - 2];
}
return suiteFibo[suiteFibo.length - 1];
}
const serverQ4 = http.createServer(async (req, res) => {
if (req.url === "/api/fibo") {
const fibo = calculerFiboOpti(getRandomInteger(7, 42));
res.end(`${fibo}`);
return;
}
const splits = req.url.split("/");
switch (splits.length) {
case 4:
const n = parseInt(splits[3]);
if (isNaN(n)) {
handleNaNError(res);
return;
}
res.end(`${calculerFiboOpti(n)}`);
return;
case 5:
const n1 = parseInt(splits[3]);
const n2 = parseInt(splits[4]);
if (isNaN(n1) || isNaN(n2)) {
handleNaNError(res);
return;
}
res.setHeader("Content-type", "application/json");
res.end(
`{ "${n1}" : ${calculerFiboOpti(n1)} , "${n2}" : ${calculerFiboOpti(
n2
)} }`
);
return;
}
// api
res.writeHead(404);
res.end();
});
serverQ4.listen(10014);
/**
* Ecrire un serveur nodejs avec le module http
* Le serveur créé au démarrage un tableau vide qui s'appelle 'data'
* Le serveur effecture le routage suivant:
* méthode POST et url '/number/:n' => Ajoute n à un tableau d'entiers mémorisé côté serveur
* méthode GET et url '/numbers' => Répond avec le contenu de data sous forme d'un tableau json
* méthode DELETE et url '/numbers/:i' => supprimer l'élément i du tableau data (utiliser splice)
*/
// expression régulière: permet de qualifier une familles de chaines de caractères avec une seule expression
// /number/464, /number/545464 => regexp : début(^) puis /(\/) number /(\/) suivi d'une sueccession de chiffres (\d+) et fin($)
// () => groupe de capture
const regExpNumber = /^\/number\/(\d+)$/;
const regExpNumbers = /^\/numbers\/(\d+)$/;
console.log(
regExpNumber.test("/number/545464"),
regExpNumber.test("/toto"),
regExpNumber.test("/number/"),
regExpNumber.test("/number/564/54545")
);
const data = [];
const serverQ5 = http.createServer(async (req, res) => {
const url = req.url;
if (req.method === "POST" && regExpNumber.test(url)) {
const match = url.match(regExpNumber);
const n = parseInt(match[1]);
data.push(n);
res.end();
} else if (req.method === "GET" && url === "/numbers") {
res.end(JSON.stringify(data));
} else if (req.method === "DELETE" && regExpNumbers.test(url)) {
const match = regExpNumbers.exec(url);
const number = parseInt(match[1]);
// pautre méthode pour supprimer -> data = data.filter ((item) => item != number);
let numberIndex = data.indexOf(number);
if (numberIndex > -1) {
data.splice(numberIndex, 1);
res.end(`the element at index ${numberIndex} has been deleted`);
} else {
res.end("element doesn't exist in the array");
}
} else {
res.writeHead(404);
}
});
serverQ5.listen(10015);
/**
* Définir une classe StaticFileProvider qui prend en paramètre du constructeur un chemin vers un dossier qu'on appelera basePath
* Dans cette classe, définir une méthode getFileContent
* qui prend en paramètre un chemin vers un fichier qu'on apperla filePth.
* Cette méthode retourne le contenu du fichier contenu dans le chemin 'basePath/filePath' ou 'undefined' si le fichier n'existe pas
* Exemple: soit l'arborescence suivante:
* - webcontent
* - index.html
* - styles
* - style.css
* - data
* - students.csv
* ! Utiliser les librairies fs et / ou fsp
*
* Ce code permet d'afficher du contenu présent dans le dossier "webcontent":
* const sfp = new StaticFileProvider("webcontent")
* console.log(await sfp.getFileContent("index.html"));
* console.log(await sfp.getFileContent("styles/style.css"));
*
* Ce code permet d'afficher du contenu présent dans le dossier "data":
* const sfp = new StaticFileProvider("data")
* console.log(await sfp.getFileContent("students.csv"));
* ! console.log(await sfp.getFileContent("teachers.csv")); -> doit afficher "undefined"
*/
class StaticFileProvider {
constructor(basePath) {
this.basePath = basePath;
}
async getFileContent(filePath) {
try {
return await fsp.readFile(`${this.basePath}/${filePath}`, "utf8");
} catch (error) {
return undefined;
}
}
}
class StaticFileProviderCallback {
constructor(basePath) {
this.basePath = basePath;
}
getFileContent(filePath, callback) {
fs.readFile(`${this.basePath}/${filePath}`, "utf8", (error, data) => {
if (error) {
callback(undefined);
} else {
callback(data);
}
});
}
}
async function runExo6() {
console.log("exo6 start");
const sfp = new StaticFileProvider("static");
const content = await sfp.getFileContent("about.html");
console.log("exo6 about", content);
console.log("exo6 style", await sfp.getFileContent("style/style.css"));
console.log("exo6 yann", await sfp.getFileContent("yann.toutcourt"));
console.log("exo6 end");
const sfp2 = new StaticFileProviderCallback("static");
sfp2.getFileContent("about.html", (data) => {
console.log("exo6 callback", data);
})
}
runExo6();
/**
* * Le but de cet exo est de montrer une façon de faire un serveur de fichiers statiques
* Dans cet exercice, on va créer un serveur de fichiers basqiue avec le module http
* Créer un serveur node et une instance de StaticFileProvider pour le chemin "static".
* Faire en sorte que le serveur retourne au client le résultat de StaticFileProvider.getFileContent(req.url)
* Si getFileContent retounr undefined -> alors le serveur répond par un statut 404
*
* Mettre des fichiers html, css, images et js dans de dossier avec la structure suivante:
* - static
* - index.html
* - styles
* - style.css
* - scripts
* - main.js
* - images
* - bidet.png
*
* Lacer le serveur et faites en sorte d'afficher tous les éléments dans le dossier "static"
*/
const serverQ7 = http.createServer(async (req, res) => {
const fsp = new StaticFileProvider("static");
const resultat = await fsp.getFileContent(req.url);
if (resultat === undefined) {
res.writeHead(404);
res.end();
} else {
res.end(resultat);
}
});
serverQ7.listen(10017);
/**
* Reprendre l'exercice précédent avec le routage suivant:
* /api/fibo -> répond avec un terme n de fibonacci. n étant un nombre alétoire entre 7 et 42
* /api/fibo/:n1/:n2 -> répond avec un json avec ce format { 'n1': F(n1), 'n2': F(n2) }.
* autres routes: résultat de StaticFileProvider.getFileContent(req.url). Initialiser le StaticFileProvider sur "static" (car repris de l'exo)
* Si getFileContent retounr undefined -> alors le serveur répond par un statut 404
*
* Dans le fichier html, créer un bouton qui va afficher dans la page le résultat des appels vers
* /api/fibo et /api/fibo/:n1/:n2. n1 et n2 sont générés aléatoirement par le client lors du click sur le bouton
*/
function getRandomChoose(max, min) {
return Math.floor(Math.random() * (max - min) + min);
}
function getNumberFibo() {
let n = getRandomChoose(7, 42);
let pre1 = 1;
let pre2 = 0;
let result = 0;
for (let i = 0; i < n; i++) {
result = pre1 + pre2;
pre2 = pre1;
pre1 = result;
}
return result;
}
function getNumberFiboWithParam(n) {
let pre1 = 1;
let pre2 = 0;
let result = 0;
for (let i = 0; i < n; i++) {
result = pre1 + pre2;
pre2 = pre1;
pre1 = result;
}
return result;
}
const serverQ8 = http.createServer(async (req, res) => {
const sfp = new StaticFileProvider("api");
const regExpFibo = /^\/fibo\/(\d+)\/(\d+)/
const adr = req.url.split('/')
if (req.url === "/api/fibo") {
const data = JSON.stringify(getNumberFibo());
res.end(data);
} else if (regExpFibo.test(req.url)) {
const match = regExpFibo.exec(req.url);
const n1 = match[1];
const n2 = match[2];
const rand1 = getNumberFiboWithParam(n1);
const rand2 = getNumberFiboWithParam(n2);
const jsonfix = `{ '${n1}' : ${rand1}, '${n2}' : ${rand2} }`;
res.end(JSON.stringify(jsonfix));
} else {
const sfp1 = new StaticFileProvider("static");
let data = await sfp1.getFileContentFirst(adr[1]);
if (data == undefined) {
res.writeHead(404);
}
res.end(data);
}
})
serverQ8.listen(10018);
"use strict";
/**
* Ecrire un script nodejs qui affiche un nombre aléatoire avec Math.random
* Les nombres retournées sont dans quel intervalle
*/
console.log(Math.random()); //intervalle entre 0 et 1
/**
* Ecrire un script nodejs qui affiche la partie entière d'un nombre aléatoire, multiplié par 100
* (astuce utiliser Math.floor)
*/
console.log(Math.random() * 100);
/**
* Ecrire un script nodejs qui affiche la partie entière d'un nombre aléatoire, multiplié par 100
* et on lui additionne 5
*/
console.log(Math.floor(Math.random() * 100 + 5));
/**
* ! Sans chercher sur internet
* Créer une fonction qui retourne un nombre aléatoire compris entre une valeur min et max passés en paramètre
*/
function getRandomNumber(min, max) {
return Math.random() * (max - min) + min;
}
console.log(getRandomNumber(1, 8));
/**
* ! Sans chercher sur internet
* Créer une fonction qui retourne un nombre entier aléatoire compris entre une valeur min et max passés en paramètre
*/
function getRandomInt(min, max) {
return Math.floor(getRandomNumber(min, max));
}
console.log(getRandomInt(1, 8));
/**
* ! Sans chercher sur internet
* Ecrire une fonction qui retourne le terme n de la suite de fibonacci. n est un entier alétoire entre 7 et 42.
* La fonction ne prend aucun paramètre.
* F(0) => 0, F(1) => 1 et F(n) = F(n-1) + F(n-2) pour n >= 2
* Afficher le résultat de deux exécutions de cette fonction.
*/
// méthode 1 (mieux)
function getFibonacci() {
const n = Math.floor(Math.random() * (42 - 7) + 7);
let numberOne = 0;
let numberTwo = 1;
let sum = 0;
for (let i = 2; i <= n; i++) {
sum = numberOne + numberTwo;
numberOne = numberTwo;
numberTwo = sum;
}
return numberTwo;
}
console.log("Résultat à la position n : " + getFibonacci());
console.log("Résultat à la position n : " + getFibonacci());
// méthode 2 (moins optimisée)
function calculerFibo() {
const suiteFibo = [0, 1];
const n = getRandomInt(42, 7);
for (let i = 2; i <= n; i++) {
suiteFibo[i] = suiteFibo[i - 1] + suiteFibo[i - 2];
}
return suiteFibo[suiteFibo.length - 1];
}
console.log(calculerFibo());
console.log(calculerFibo());
"use strict";
const ipRegExp = /^(\d{1,3}\.){3}(\d{1,3})$/;
const ip = "192.168.255.254";
console.log(ipRegExp.test(ip));
const m = ip.matchAll(ipRegExp);
console.log(m);
http://localhost:10001
###
POST http://localhost:10001
###
http://localhost:10001/hello
###
http://localhost:10001/
mon-header: 100
Accept-Encoding: "utf8"
###
DELETE http://localhost:10001/1020/js
mon-header: 100
Accept-Encoding: "utf8"
###
http://localhost:10003/123/1231
###
http://localhost:10003/1
###
http://localhost:10003/154216651
###
http://localhost:10003/dsfsd
###
http://localhost:10003
###
http://localhost:10004
###
http://localhost:10004/index.html
###
http://localhost:10004/data
###
http://localhost:10004/styles/style.css
###
http://localhost:10013/api/fibo
###
http://localhost:10013/api/fibo/2
###
http://localhost:10013/api/fibo/nacci
###
http://localhost:10013/api/fibo/5/9
###
http://localhost:10014/api/fibo
###
http://localhost:10014/api/fibo/2
###
http://localhost:10014/api/fibo/nacci
###
http://localhost:10014/api/fibo/5/9
###
http://localhost:10015/numbers
###
POST http://localhost:10015/number/42
###
delete http://localhost:10015/numbers/42
###
delete http://localhost:10018/fibo/12/66
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment