Frameworks Web Applications web, API HTTP, Routage

Avant les pages dynamiques

Le premiers servers web se limitaient à servir des fichiers statiques: HTML, images, etc.

CLIENT SERVER GET /index.html HTTP/1.1 HTTP/1.1 200 OK ... index.html
  • L’URL correspond à un chemin dans le système de fichiers du serveur.

Génération statique

  • Les fichiers HTML sont assemblés à partir de plusieurs composants,
  • Ils sont compilés avant d’être chargés sur le serveur

Un exemple moderne

menu.html content.md footer.jade index.html Markdown Pug
  • Markdown : transformation Texte → HTML,
  • Pug : syntaxe simplifiée pour HTML,
  • Perl : langage de programmation générique.

Autre exemple : Ces transparents sont générés statiquement (Markdown + Jekyll).

Web 1.0 : pages dynamiques

La création du document se fait au moment de la requête, à la volée.

GET /app.php HTTP/1.1 HTTP/1.1 200 OK app.php Moteur de Scripting Server d'authentification Database template XML document HTML généré

Le serveur peut :

  • Compiler le document à la volée (comme dans la génération statique),
  • Interagir avec d’autres serveurs (authentification, API, …),
  • Interroger des bases de données.

Web 2.0 : Applications web

Focalisées autour de l’interaction avec l’utilisateur.

GET /users.json HTTP/1.1 HTTP/1.1 200 OK Application Web Server d'authentification Database template XML document JSON généré
  • Les URL ne correspondent plus à des fichiers sur le serveur,
  • Une URL indique une ressource virtuelle, une action,
  • Exécution de l’application web
    • par un serveur web (par ex., Apache+PHP, Tomcat+Java, …),
    • ou par son propre serveur (par ex., Node.js, …).

Frameworks Web

Un framework web est une bibliothèque et une collection d’outils qui facilitent la construction d’applications web.

Quelques composants classiques d’un framework

  • API HTTP(S) : parsing/écriture de requêtes/réponses HTTP,
  • Router : définit la correspondance URL → Code à exécuter,
  • Moteur de templates: génération Modèles → Pages HTML,
  • Stockage volatile: persistance, sessions, memcache,
  • Abstraction de bases de données,
  • Mechanismes de sécurité: injections, XSS, CSRF,
  • Caching, Internationalisation, …

Exemples: Symfony (PHP), Silex (PHP, basé sur Symfony), Zend (PHP), Node.js (JavaScript), io.js (JavaScript), Ruby on Rails (Ruby), Django (Python), Flask (Python), Tornado (Python), Java EE, …

Frameworks étudiés dans ce cours

Silex (PHP)

Micro-framework dérivé de Symfony.

  • Modules : API HTTP, Router, Sessions.
  • Modules optionnels : Moteur de templates (Twig), Abstraction de bases de données (Doctrine), Protections CSRF, Caching, Internationalisation, Mail, …

Node.js + Express (JavaScript)

Micro-framework web écrit en JavaScript (V8).

  • Modules : Server Web, API HTTP, Gestionnaire de paquets (npm).
  • Modules optionnels (développés par la communeauté, distribués via npm) : Router, Middlewares, Sessions, Memcache, Moteurs de templates, Abstraction de bases de données, Protections CSRF, WebSockets, …

API HTTP : Application, requête, réponse

POST /url?a=b HTTP/1.1 Host: www.myhost.com Accept-Language: "fr;en" Content-Type: application/json { "func": "is_prime", "nums": [1,2,3,4,5,6,7,8] } "primes": [2,3,5,7] } { "status": "ok", Content-Type: application/json Content-Length: 40 Set-Cookie: sessid=0A5FD2 HTTP/1.1 200 OK Requête : query string entêtes corps de la requête méthode, url, cookies, ... Réponse : code d'état corps de la réponse entêtes, cookies, ... Application : router moteur de templates sessions interface BD middlewares ...

L’application

Silex (PHP)

require_once 'vendor/autoload.php';
$app = new Silex\Application();

$app->get();      // Le router
$app->post();
$app->match();

$app->run();      // Exécution

Express (Node.js)

var express = require('express');
var app = express();

app.get();        // Le router
app.post();
app.all();

app.listen(80);   // Exécution

L’objet requête

Silex

use Symfony\Component\HttpFoundation\Request;

$app->get('/', function(Request $req) {
	$req->query;      // Query string
	$req->request;    // corps de la requête
	$req->headers;    // entêtes HTTP
	$req->cookies;    // cookies
});

Express

var bodyParser = require("body-parser"), cookieParser = require("cookie-parser");
app.use(bodyParser.urlencoded()).use(cookieParser()); // config

app.get('/', function(req, res) {
	req.query;        // query string
	req.body;         // corps de la requête
	req.headers;      // entêtes HTTP
	req.cookies;      // cookies
});

L’objet réponse (Silex)

use Symfony\Component\HttpFoundation\Response;

Écrire une réponse simple

return 'Hello world';

Envoyer un code d’état et des entêtes

return new Response(404, 'Not Found', headers);

Envoyer un fichier statique

return $app->sendFile('static-file.html');

Faire une redirection

return $app->redirect('/other/path');

Envoyer des données au format JSON

return $app->json( array('a' => 'b') );

L’objet réponse (Express)

Écrire une réponse simple

res.send('Hello world');

Envoyer un code d’état et des entêtes

res.set('Content-Type', 'text/plain');
res.status(404).send('Not Found');

Envoyer un fichier statique

res.sendFile('static-file.html');
res.download('static-attachment.mp3');

Faire une redirection

res.redirect('/other/path');

Envoyer des données au format JSON

res.json({ 'a' : 'b' });

Anatomie de l’application

GET /path/toto/titi $app->get('/path/{v1}/{v2}', function($v1, $v2) { ... } <h1>Hello {{ user }}!</h1> SELECT * FROM user WHERE id=$v1; HTTP/1.1 200 OK <h1>Hello toto!</h1> Router Gestionnaire Template engine Database Réponse

Le router

Le router fait l’association : méthode+URL → code à exécuter

$app->get('/url', function() {...});

Il peut aussi traduire une partie de l’URL en arguments de la fonction

$app->get('/url/{a1}/{a2}', function($a1, $a2) {
	...
});

En Express

app.get('/url/:a1/:a2', function(req, res) {
	console.log(req.params.a1);
});

Lectures

Silex

Express

Fork me on GitHub