Développement Web 2 Bertrand Estellon Aix-Marseille Université April 1, 2014 Nodejs Nodejs Introduction Introduction Nodejs est une plateforme : permettant d écrire des applications; basée sur le langage JavaScript (et l interpréteur de Chrome); adaptée à la programmation de serveur Web; Exemple : var http = require('http'); httpcreateserver(function (req, res) { reswritehead(200, {'Content-Type': 'text/plain' resend('hello World\n'); )listen(8888, '127001'); consolelog('server running at http://127001:8888/'); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 1 / 436 Nodejs Nodejs Les modules Les modules Pour organiser votre programme, vous pouvez définir des modules : var tools = require('/toolsjs'); consolelog( 'Aire = ' + toolscirclearea(4)); Le fichier toolsjs : var PI = MathPI; moduleexportscirclearea = function (r) { return PI * r * r; Exécution : $ node examplejs Server running at http://127001:8888/ Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 315 / 436 Nodejs Les modules Nodejs Installation de modules Pour télécharger et installer des modules, vous pouvez utiliser npm : $ npm install express npm http GET https://registrynpmjsorg/express La commande npm cherche un répertoire node_modules présent dans un répertoire se trouvant entre le répertoire courant et la racine; Le module est installé dans le répertoire node_modules trouvé; Il est accessible dans tous les sous-répertoires du répertoire courant; On a accès au module installé à l aide la fonction require; moduleexportsrectanglearea = function (w, h) { return w*h; Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 316 / 436 appget('/ttxt', function(req, res){ ressend('t'); applisten(8080); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 317 / 436
Nodejs Nodejs Quelques API Quelques API Un certain nombre de fonctions sont fournies dans nodejs : voir http://nodejsorg/api (je vous laisse parcourir les API) Exemple avec STDIO : consolelog('count: %d', count); consoleinfo('info: %s', info); consoleerror('erreur : Truc == null'); consolewarn('attention : variable Truc contient null'); Exemple avec Net : var net = require('net'); var server = netcreateserver(function (socket) { consolelog(socketremoteaddress); socketend("bye\n"); serverlisten(8888, function() { consolelog('go!'); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 318 / 436 Nodejs Nodejs Répondre à une demande Vous pouvez répondre à des requêtes par des callbacks : var count = 0; appget('/count', function(req, res) { ressend(""+count); count++; applisten(8080); Nodejs Nodejs Introduction est un framework pour construire des applications Web en Node Installation : > npm install express npm http GET https://registrynpmjsorg/express Création d une application : Après avoir configuré l application, on commence à écouter sur un port : applisten(8080); consolelog('nous écoutons sur le port 8080'); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 319 / 436 Nodejs Nodejs Accès aux paramètres Vous pouvez également accéder aux paramètres de la requête HTTP : var count = 0; /* */ appget('/set', function(req, res, next) { var value = reqquery['value']; if (!value) return next(new Error("value required!")); count = parseint(value); ressend("ok"); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 320 / 436 applisten(8080); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 321 / 436
Nodejs Nodejs Contenus statiques Nodejs Nodejs Les sessions Pour distribuer le contenu d un répertoire : appuse(expressstatic( dirname + '/public')); appuse('/static', expressstatic( dirname + '/static')); applisten(8080); Utilisation des sessions : appuse(expresscookieparser('zhizehgiz')); appuse(expresssession()); appget('/', function(req, res){ if (reqsessioncount) { reqsessioncount++; else { reqsessioncount = 1; ressend(""+reqsessioncount); applisten(8080); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 322 / 436 Nodejs Nodejs Les paramètres Les paramètres : var users = [{name:"joe",age:21,{name:"bob",age:22]; appget('/user/:user', function(req, res, next){ var user = users[reqparamsuser]; if (!user) return next(new Error("bad user id!")); reswritehead(200, {'Content-Type': 'application/json' ressend(jsonstringify(user)); applisten(8080); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 324 / 436 Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 323 / 436 Nodejs Nodejs Les sequences Les sequences : appuse(expresscookieparser('zhizehgiz')); appuse(expresssession()); appget('/auth', function(req, res, next) { if (reqquery["password"]=="toto") reqsessionauth = true; ressend("ok"); function restrict(req, res, next) { if (!reqsessionauth) next(new Error("Unauthorized")); else next(); /* */ Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 325 / 436
Nodejs Nodejs Nodejs Les sequences Les sequences (suite) : /* */ appget('/auth', function(req, res, next) { /* */ function restrict(req, res, next) { /* */ appget('/t', restrict, function(req, res, next) { ressend("t"); appget('/h', restrict, function(req, res, next) { ressend("h"); Nodejs Templates avec ejs Il est possible d utiliser un langage proche de PHP pour générer les pages : appengine('html', require('ejs') express); appset('views', dirname + '/views'); appset('view engine', 'html'); var users = [{name:"joe",age:21,{name:"bob",age:22]; appget('/', function(req, res){ resrender('users', { users: users, applisten(8080); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 326 / 436 Nodejs Nodejs Templates avec ejs applisten(8080); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 327 / 436 Nodejs Nodejs Templates avec Jade Le fichier usershtml : <!doctype html> <html> <head> <title>example</title> </head> <body> Users : <ul> <% for (i in users) { %> <li><%= users[i]name %> : <%= users[i]age %></li> <% %> </ul> </body> </html> Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 328 / 436 Il est possible d utiliser un langage proche de PHP pour générer les pages : appset('views', dirname + '/views'); appset('view engine', 'jade'); var users = [{name:"joe",age:21,{name:"bob",age:22]; appget('/', function(req, res){ resrender('users', { users: users, applisten(8080); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 329 / 436
Nodejs Nodejs Templates avec Jade Nodejs Nodejs MySQL MySQL var mysql = require('mysql'); Le fichier usershtml :!!! 5 html head title Example body Users : ul for user in users li #{username : #{userage var connection = mysqlcreateconnection( { host : 'localhost', user : 'username', password : 'password', database : 'database' connectionconnect(); var query = 'SELECT * FROM users'; connectionquery(query, function(err, rows) { if (err) throw err; for (var i in rows) consolelog(rows[i]name +" "+rows[i]age); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 330 / 436 Nodejs Nodejs MySQL var mysql = require('mysql'); MySQL var connection = mysqlcreateconnection(/* */); connectionconnect(); var id = 3; var query = 'SELECT * FROM users WHERE id =?'; connectionquery(query, [id], function(err, rows) { if (err) throw err; for (var i in rows) consolelog(rows[i]name +" "+rows[i]age); connectionend(); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 332 / 436 connectionend(); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 331 / 436 Nodejs SocketIO Introduction Nodejs SocketIO SocketIO est un module qui permet de mettre en place (ou de simuler) une connexion bidirectionnelle entre un client et un serveur Techniques utilisées (en fonction de la disponibilité): WebSocket Technologie Flash AJAX long polling AJAX multipart streaming Forever Iframe JSONP Polling Navigateurs supportés : Internet Explorer 55+, Safari 3+, Google Chrome 4+, Firefox 3+, Opera 1061+, iphone Safari, ipad Safari, Android WebKit, WebOs WebKit Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 333 / 436
Nodejs SocketIO Introduction Nodejs SocketIO Nodejs SocketIO Le serveur Nodejs SocketIO Serveur Notifications Association de WebSocket et de : var app = require('express')(); var server = require('http')createserver(app); var io = require('socketio')listen(server); appget('/', function (req, res) { ressendfile( dirname + '/clienthtml'); /* Configuration du serveur */ serverlisten(8080); Notification de la connexion d un nouveau client : iosocketson('connection', function (socket) { /* socket représente la connexion entre le client et le serveur */ Notification de la déconnexion d un client : socketon('disconnect', function () { /* */ Notification de la réception d un message : socketon('msgname', function(data) { /* */ Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 334 / 436 Nodejs SocketIO Le serveur Nodejs SocketIO Serveur Messages Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 335 / 436 Nodejs SocketIO Le client Nodejs SocketIO Client Ajout du script : Envoyer un message via un socket : socketemit('msgname', data); Envoyer un message à tous les autres sockets (à l exception de ce socket) : socketbroadcastemit('msgname', data); Envoyer un message à tous les sockets : iosocketsemit('msgname', data); <script src="/socketio/socketiojs"></script> Connexion : var socket = ioconnect('http://localhost:8080'); Envoyer un message au serveur : socketemit('msgname', data); Écouter un type de message provenant du serveur : socketon('msgname', function (data) { /* */ Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 336 / 436 Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 337 / 436
Nodejs SocketIO Premier exemple Nodejs SocketIO Premier exemple Contenu du fichier indexhtml : <!doctype html> <html> <head> <script src="/socketio/socketiojs"></script> <script src="jqueryminjs"></script> <script src="indexjs"></script> </head> <body> <div id="time"></div> <input id="format"></input> <button id="changeformat">changer le format</button> </body> </html> Nodejs SocketIO Premier exemple Nodejs SocketIO Premier exemple Contenu du fichier indexjs : $(document)ready(function() { var socket = ioconnect('http://localhost:8080'); socketon('time', function (data) { $("#time")text(datatime); $("#changeformat")click(function() { socketemit("format", { format : $("#format")val() Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 338 / 436 Nodejs SocketIO Premier exemple Nodejs SocketIO Premier exemple Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 339 / 436 Nodejs SocketIO Premier exemple Nodejs SocketIO Premier exemple Initialisation de la connexion : Code du serveur : var server = require('http')createserver(app); var io = require('socketio')listen(server); appuse('/', expressstatic( dirname + '/static')); /* Initialisation de la connexion */ serverlisten(8080); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 340 / 436 var dateformat = require('dateformat'); var format = "h:mm:ss"; iosocketson('connection', function (socket) { setinterval(sendtime, 1000, socket); socketon('format', function (data) { format = dataformat; function sendtime(socket) { var now = new Date(); socketemit('time', { time : dateformat(now, format) Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 341 / 436
Nodejs SocketIO Jeu de Morpion Nodejs SocketIO Morpion Client <!DOCTYPE html> <html> <head> <script src="jqueryminjs"></script> <script src="/socketio/socketiojs"></script> <script src="indexjs"></script> <style><!-- style --></style> </head> <body> <div id="c00" class="cell"></div> <!-- --> <div id="c22" class="cell"></div><br> <div id="message" class="message"></div><br/> </body> </html> Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 342 / 436 Nodejs SocketIO Jeu de Morpion Nodejs SocketIO Morpion Client $(function() { socketon('play', play); socketon('timetoplay', function () { $("#message")text("à vous de jouer"); socketon('wait', function () { /* */ socketon('lost', function () { /* */ socketon('win', function () { /* */ socketon('draw', function () { /* */ for (var i = 0; i < 3; i++) for (var j = 0; j < 3; j++) initcell(i,j); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 344 / 436 Nodejs SocketIO Jeu de Morpion Nodejs SocketIO Morpion Client var socket = ioconnect('http://localhost:8080'); function play(data) { var x = datax; var y = datay; var color =(dataposition == 0)?"red":"blue"; $('#c'+x+y)css("background-color", color); function onclick(x,y) { socketemit("play", {x:x,y:y function initcell(x,y) { $('#c'+x+y)click(function() { onclick(x,y); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 343 / 436 Nodejs SocketIO Jeu de Morpion Nodejs SocketIO Morpion Serveur var server = require('http')createserver(app); var io = require('socketio')listen(server); var Game = require('/game'); var Player = require('/player'); appuse(expressstatic( dirname+'/www')); var currentgame = new Game(); iosocketson('connection', function (socket) { currentgameaddplayer(new Player(socket)); if (currentgameisfull()) currentgame = new Game(); serverlisten(8080); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 345 / 436
Nodejs SocketIO Jeu de Morpion Nodejs SocketIO Morpion Serveur var Game = function() { thisplayers = []; thisactiveposition = -1; /* */ Gameprototype = { isfull : function() { return thisplayerslength == 2;, addplayer : function(player) { playersetgame(this, thisplayerslength); thisplayerspush(player); if (thisisfull()) thisstartgame();, /* */ Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 346 / 436 Nodejs SocketIO Jeu de Morpion Nodejs SocketIO Morpion Serveur Nodejs SocketIO Jeu de Morpion Nodejs SocketIO Morpion Serveur var Player = function(socket) { thissocket = socket; thisgame = null; thisposition = 0; Playerprototype = { sendmessage : function(msg, data) { thissocketemit(msg, data);, setgame : function(game, position) { /* */ Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 347 / 436 Nodejs SocketIO Jeu de Morpion Nodejs SocketIO Morpion Serveur var Player = function(socket) { /* */ Playerprototype = { /* */ setgame : function(game, position) { thisgame = game; thisposition = position; thissocketon('play', function(data) { gameplay(position, datax, datay); thissocketon('disconnect', function() { gamegiveup(position); Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 348 / 436 var Game = function() { /* */ thisinitgrid(); Gameprototype = { isfull : function() { /* */, addplayer : function(player) { /* */, initgrid : function() { thisnbemptycells = 9; thisgrid = []; for (var x = 0; x < 3; x++) { thisgrid[x] = []; for (var y = 0; y < 3; y++) thisgrid[x][y] = -1;, /* */ Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 349 / 436
Nodejs SocketIO Jeu de Morpion Nodejs SocketIO Morpion Serveur Nodejs SocketIO Jeu de Morpion Nodejs SocketIO Morpion Serveur Gameprototype = { isfull : function() { /* */, addplayer : function(player) { /* */, initgrid : function() { / * */, setactiveposition : function(position) { thisactiveposition = position; thisplayers[position]sendmessage("timetoplay"); thisplayers[1 - position]sendmessage("wait");, startgame : function() { thissetactiveposition(0);, /* */ Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 350 / 436 Nodejs SocketIO Jeu de Morpion Nodejs SocketIO Morpion Serveur Gameprototype = { /* isfull, addplayer, initgrid, setactiveposition */ play : function(position, x, y) { if (thisactiveposition!=position) return; if (thisgrid[x][y]!=-1) return; thisgrid[x][y] = position; thisnbemptycells--; for (var p = 0; p < 2; p++) thisplayers[p]sendmessage("play", { position : position, x : x, y : y if (thishaswin(position)) thisendgamewithavictory(position); else if (thisnbemptycells==0) thisendgameinadraw(position); else thissetactiveposition(1 - thisactiveposition);, /* */ Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 351 / 436 Nodejs SocketIO Jeu de Morpion Nodejs SocketIO Morpion Serveur Gameprototype = { /* isfull, addplayer, initgrid, setactiveposition, play */ endgameinadraw : function() { thisplayers[0]sendmessage("draw"); thisplayers[1]sendmessage("draw"); thisactiveposition = -1;, endgamewithavictory : function(position) { thisplayers[position]sendmessage("win"); thisplayers[1-position]sendmessage("lost"); thisactiveposition = -1;, giveup : function(position) { if (thisactiveposition!=-1) { thisplayers[1-position]sendmessage("win"); thisactiveposition = -1; thisplayers = [];, /* */ Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 352 / 436 Gameprototype = { /* isfull, addplayer, initgrid, setactiveposition, play */ haswin : function(pos) { for (var i = 0; i < 3; i++) { var ok1 = true, ok2 = true; for (var j = 0; j < 3; j++) ok1 = ok1 && (thisgrid[i][j]==pos); for (var j = 0; j < 3; j++) ok2 = ok2 && (thisgrid[j][i]==pos); if (ok1 ok2) return true; var ok1 = true, ok2 = true; for (var i = 0; i < 3; i++) ok1 = ok1 && (thisgrid[i][i]==pos); for (var i = 0; i < 3; i++) ok2 = ok2 && (thisgrid[i][2-i]==pos); return ok1 ok2; Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 353 / 436
Nodejs SocketIO Jeu de Morpion Nodejs SocketIO Morpion Serveur Organisation du programme du serveur : trois fichiers : mainjs, gamejs, playerjs Exportation : var Player = function(socket) { /* */ Playerprototype = { setgame : function(game, position) { /* */, sendmessage : function(msg, data) { /* */ moduleexports = Player; Bertrand Estellon (AMU) Développement Web 2 April 1, 2014 354 / 436