bytes.cat

La wiki d'FP d'informàtica

Eines de l'usuari

Eines del lloc


Barra lateral

ASIX Administració de Sistemes Informàtics i Xarxes
Tots els mòduls del cicle
MP01 Implantació de sistemes operatius
Totes les UFs del modul
MP02 Gestió de bases de dades
Totes les UFs del modul
MP03 Programació bàsica
Totes les UFs del modul
MP04 Llenguatges de marques i sistemes de gestió d'informació
Totes les UFs del modul
MP05 Fonaments de maquinari
Totes les UFs del modul
MP06 Administració de sistemes operatius
Totes les UFs del modul
MP07 Planificació i administració de xarxes
Totes les UFs del modul
MP08 Serveis de xarxa i Internet
Totes les UFs del modul
MP09 Implantació d'aplicacions web
Totes les UFs del modul
MP10 Administració de sistemes gestors de bases de dades
Totes les UFs del modul
MP11 Seguretat i alta disponibilitat
Totes les UFs del modul
MP12 Formació i orientació laboral
Totes les UFs del modul
MP13 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP14 Projecte
Totes les UFs del modul
DAM Desenvolupament d’aplicacions multiplataforma
Tots els mòduls del cicle
MP01 Sistemes informàtics
Totes les UFs del modul
MP02 Bases de dades
Totes les UFs del modul
MP03 Programació bàsica
Totes les UFs del modul
MP04 Llenguatges de marques i sistemes de gestió d'informació
Totes les UFs del modul
MP05 Entorns de desenvolupament
Totes les UFs del modul
MP06 Accés a dades
Totes les UFs del modul
MP07 Desenvolupament d’interfícies
Totes les UFs del modul
MP08 Programació multimèdia i dispositius mòbils
Totes les UFs del modul
MP09 Programació de serveis i processos
Totes les UFs del modul
MP10 Sistemes de gestió empresarial
Totes les UFs del modul
MP11 Formació i orientació laboral
Totes les UFs del modul
MP12 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP13 Projecte de síntesi
Totes les UFs del modul
MPDual Mòdul Dual / Projecte
DAW Desenvolupament d’aplicacions web
Tots els mòduls del cicle
MP01 Sistemes informàtics
Totes les UFs del modul
MP02 Bases de dades
Totes les UFs del modul
MP03 Programació
Totes les UFs del modul
MP04 Llenguatge de marques i sistemes de gestió d’informació
Totes les UFs del modul
MP05 Entorns de desenvolupament
Totes les UFs del modul
MP06 Desenvolupament web en entorn client
Totes les UFs del modul
MP07 Desenvolupament web en entorn servidor
Totes les UFs del modul
MP08 Desplegament d'aplicacions web
Totes les UFs del modul
MP09 Disseny d'interfícies web
Totes les UFs del modul
MP10 Formació i Orientació Laboral
Totes les UFs del modul
MP11 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP12 Projecte de síntesi
Totes les UFs del modul
SMX Sistemes Microinformàtics i Xarxes
Tots els mòduls del cicle
MP01 Muntatge i manteniment d’equips
Totes les UFs del modul
MP02 Sistemes Operatius Monolloc
Totes les UFs del modul
MP03 Aplicacions ofimàtiques
Totes les UFs del modul
MP04 Sistemes operatius en xarxa
Totes les UFs del modul
MP05 Xarxes locals
Totes les UFs del modul
MP06 Seguretat informàtica
Totes les UFs del modul
MP07 Serveis de xarxa
Totes les UFs del modul
MP08 Aplicacions Web
Totes les UFs del modul
MP09 Formació i Orientació Laboral
Totes les UFs del modul
MP10 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP11 Anglès
Totes les UFs del modul
MP12 Síntesi
Totes les UFs del modul
CETI Ciberseguretat en Entorns de les Tecnologies de la Informació
Tots els mòduls del cicle
nodejs_express

NodeJS amb Express

NodeJS és una plataforma per a desenvolupament web amb JavaScript. Ha arribat a disposar de moltes llibreries que gestionem amb la utilitat NPM.

Express és un framework per a NodeJS que ens facilita la creació d'aplicacions web.

Referències:

Primeres passes

  1. Descarrega i instal·la NodeJS per a la teva plataforma. Convé descarregar la darrera versió LTS si volem després utilitzar algunes eines com Cordova (per a compilar sobre dispositius mòbils). La que hi ha als respositoris d'Ubuntu (nodejs-legacy) NO sol ser la darrera LTS. Millor descarregar-la de la pàgina oficial https://nodejs.org
  2. Crea una carpeta per a la teva nova app:
    $ mkdir myApp
  3. Entra a la carpeta:
    $ cd myApp
  4. Inicia un arxiu de projecte package.json amb:
    $ npm init
  5. Instal·la el framework Express amb
    $ npm install express
  6. Segueix l'exemple "Hello World!" de la documentació oficial de Express i implementa'l dins la nova carpeta.
  7. Arrenquem la app amb:
    $ node app.js
  8. Si tot ha anat bé, podràs visualitzar la teva app apuntant el navegador a:
    http://localhost:3000


Autoload amb nodemon

Com que estarem fent continuament canvis en codi i el servidor no els actualitza si no parem i reengeguem el servidor, ens anirà molt bé una eina anomenada nodemon, que autocarregarà els canvis:

$ sudo npm install -g nodemon

I arrenquem la aplicació amb nodemon enlloc de node:

$ nodemon app.js


Utilitzant plantilles EJS

EJS és un sistema de plantilles que ens facilita renderitzar pàgines web. En combinació amb NodeJS i Express ens resulta molt pràctic per separar el codi (processament) del HTML (presentació).

  1. Instal·la segons s'indica en la doc oficial de EJS
  2. Implementa una plantilla en un arxiu .ejs a part. Pots mirar aquest exemple de EJS amb Express
  3. Pensa que els arxius EJS per defecte van dins una carpeta views.
  4. Implementa una capçalera i peu de pàgina separats en arxius EJS i crida'ls amb un include.

L'objectiu ara serà que la nostra aplicació respongui a les dades que li enviem. Per això necessitem formularis…

La documentació de EJS és una mica escassa d'exemples. Si vols saber si una variable existeix o no dins d'una plantilla EJS NO testejis amb

<% if( var1 ) {...} %

sinó amb

<% if( locals.var1 ) {...} %>

tal i com expliquen en aquest post.


Formularis, GET i POST

Quan s'envia un formulari HTML les dades es poden adjuntar utilitzant diversos mètodes, els principals són GET i POST (però també hi ha PUT o DELETE).

Variables via mètode GET

Les dades enviades per GET podem accedir-les amb la variable req.query.

Per exemple, si tenim un formulari amb un

<form action="/checklogin">
    <input "name"="username">
    ...

les dades s'enviaran a la pàgina checklogin (action) dins la URL aproximadament així:

http://elmeudomini.com/checklogin?username=manolo

i podrem accedir via req.query.username.

No cal instal·lar cap complement.

Exercici

Crea una aplicació «Hello, Manolo» que demani el nom d'usuari en un formulari i que a l'enviar-ho via GET ens saludi amb «Hello, <nomusuari>».


Dades POST

Per les dades POST necessitem el package ''body-parser''.

Les dades enviades per POST es poden accedir amb la variable req.body.

Instal·la body-parser amb

npm install body-parser

Tens la documentació oficial del body-parser.

El codi d'exemple ens podria quedar així:

const express = require('express')
const app = express()
const port = 3000
 
// setup
app.set('view engine', 'ejs');
var bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }))
 
 
// routes
app.get('/', (req, res) => {
  res.render("form.ejs"); // cal crear una plantilla a views/form.ejs
})
app.post('/', (req, res) => {
  res.send("Welcome "+req.body.username);
});
 
 
// start app
app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})


Exercicis

  1. Seguint l'exemple anterior, fes una aplicació «Hello, Pepa» que demani el nom d'usuari en un formulari i que a l'enviar-ho ens saludi amb «Hello, <nomusuari>».
    • Si no s'ha introduit cap nom, posarà «Benvningut, Anònim».
    • Afegeix un radiobutton al formulari per indicar si el tractament ha de ser «Benvingut» o bé «Benvinguda».
  2. Realitza una aplicació de login d'usuaris amb NodeJS + Express.
    • Ha d'oferir un formulari que permeti introduir usuari i contrasenya.
    • Definirem els usuaris i contrasenyes en un JS Object (array associatiu).
    • Si l'usuari no existeix, mostrarem un missatge «usuari no existent».
    • Si l'usuari existeix, però la contrasenya és errònia, ens ha de mostrar «contrasenya incorrecta».
  3. Utilitza les plantilles EJS per fer les vistes del formulari i del resultat de la consulta del login.
    • Crea una plantilla base amb un header i footer personalitzat.
    • Aplica la plantilla base a les diferents views derivades.


Persistència amb localStorage

La persistència amb NodeJS, com és d'esperar, es pot fer mitjançant arxius i bases de dades. Hi ha una manera força fàcil d'implementar una persistència senzilla: localStorage. Aquest mecanisme és propi dels browsers, raó per la qual en NodeJS no està disponible de forma nadiua i caldrà carregar la llibreria node-localstorage.

localStorage és un sistema de persistència de tipus key-value, cosa que simplifica molt la forma de treballar, tot i que limita les seves features.

Per instal·lar-ho fes

$ npm install node-localstorage

En el fons aquesta llibreria node-localstorage utilitza arxius (podràs veure les variables emmagatzemades a la carpeta scratch si segueixes les instruccions de la documentació).

Si vols injectar dades al localStorage de la teva aplicació pots fer crear arxius a aquesta carpeta, o bé, de forma més «pulida», des de la consola:

$ node
> var LocalStorage = require('node-localstorage').LocalStorage;
> localStorage = new LocalStorage('./scratch');
> localStorage.setItem("clau","valor");

Objectes a localStorage

localStorage només emmagatzema strings. Si volem posar objectes complexes, com diccionaris o arrays, caldrà utilitzar algun mètode de serialització. Les funcions típiques que s'empren per a això son:

  1. JSON.stringify() ens transforma l'objecte en un string per poder ser insertat al localStorage.
  2. JSON.parse() ens permet recuperar un string serialitzat i el restitueix com a objecte.


Servint arxius estàtics

En principi, NodeJS no hauria de servir arxius estàtics (com imatges, scripts JS de client, etc.), ja que no és molt eficient realitzant aquesta tasca i és millor deixar-la per al servidor web, sigui Apache o Nginx o el què prefereixis.

Tot i això, en alguns casos volem facilitar-nos aquesta funcionalitat fent-ho des de Node i en particular amb Express. Podeu veure com servir arxius estàtics en aquest enllaç.


Càrrega d'arxius

Per carregar arxius podeu utilitzar el mòdul formidable de NPM.

Aquí teniu un breu però clar tutorial de formidable, i també podeu mirar la pàgina oficial de formidable a NPM.


Exercicis

  1. Crea una aplicació de tasques o tasklist utilitzant el localStorage com a sistema de persistència, tal i com s'explica més amunt.
  2. Amplia l'aplicació de login i/o la de tasklist , creant una taula d'usuaris en una base de dades (recomanem PostgreSQL si vols després utilitzar Heroku gratuïtament)
    • Fes que la columna de la contrasenya estigui encriptada amb SHA512.


APIs i JSON

Més endavant voldrem comprovar des d'una app mòbil si el login i pass és correcte. I per això no volem fer servir un formulari, sinó que volem poder fer una crida a una URL que ens pugui respondre OK o KO i prou, sense HTML.

De fet, la majoria d'APIs funcionen amb format JSON tant per a l'entrada com per a la sortida de dades. Per retornar dades en format JSON, que son els propis de JavaScript, només cal utilitzar res.json(jsonObj) , per exemple:

app.get('/api/get_user', (req, res) => {
  res.json( {"username":"manolo"} );
})

Aquesta crida remota és el que acostumem a denominar una «web» API («web» ja que la fem via HTTP).

Per testejar des de la shell fem les crides amb la comanda curl. En HTTP podem triar entre fer-les per GET o per POST i en diferents formats:

  • Crida amb mètode GET amb paràmetres en format estàndard:
    curl http://localhost:5000/api/login -d "user=pepe&password=123"
  • Crida GET amb paràmetres en la URL:
    curl http://localhost:5000/api/logincheck/pepe/123
  • Crida POST i format JSON:
    curl -X POST localhost:5000/api/logincheck -d '{"nom":"pepe", "pass":"123"}' -H "Content-Type: application/json"

    Fixa't en què:

    • Adjuntem dades amb «-d»
    • Indiquem el mètode amb -X
    • Afegim headers amb -H, en aquest cas per indicar que les dades van en format JSON.
    • ULL! Si volem enviar les dades en format JSON, caldrà ajustar el body-parser de la següent manera:
      app.use(bodyParser.json())

Teniu aquí més exemples de com es fan les crides amb curl.

Express ens permet recollir els paràmetres de la URL de forma molt fàcil amb la variable req.params.

app.get('/api/user/:id', function (req, res) {
  userId = req.params.id;
  userObj = getUser(userId);
  res.json()
})

Recopilant el dit fins ara, per accedir als paràmtres d'entrada de l'usuari amb Express utilitzarem:

  • req.query per a les dades GET
  • req.body per a les dades POST (amb body-parser)
  • req.params per a les dades de la URL
  • req.headers per a les dades del headers HTTP.

Implementa la ruta /api/logincheck/, i respon si l'usuari i contrasenya enviats per GET són correctes o incorrectes.


Habilitant CORS

Les aplicacions web que correm en browsers amb JS solen tenir una protecció de seguretat per evitar crides entre diferents orígens de dades. És el que anomenem CORS o Cross-Origin Resource Sharing.

Pots mirar una demo de com funciona CORS a http://ieti.cat/cors/

Utilitza aquest mòdul per habilitar CORS a la nostra flamant API.

Mirant més de prop, podem comprovar si la nostra aplicació està funcionant amb CORS si trobem al seu headers el següent:

Access-Control-Allow-Origin: *

Per veure els headers de la response només cal que feu la crida curl -i


Autenticació a les APIs

Els mètodes més habituals d'autenticació per a APIs son:

  • BasicAuth : es tracta d'enviar usuari i password codificats en base64 a les capçaleres. No recomanat en entorns de producció ja que la contrasenya és una dada sensible que no convé enviar a cada request.
  • TokenAuth : més recomanable que el BasicAuth, ja que enviarem la contrasenya 1 cop a l'inici de la comunicació, i se'ns retornarà un token, que podrem emprar més tard per cada request que fem. D'aquesta manera el nivell de seguretat es millora.

Basic Auth

BasicAuth és un sistema molt simple i que no es recomana en entorns de producció. Tot i així, sol utilitzar-se en alguns entorns de test com a mètode simple d'autenticació. Per a NodeJS+express disposem del plugin express-basic-auth, senzill però efectiu per a aquesta tasca.

Per cridar una BasicAuth amb curl fem:

curl -u usuari:contrasenya http://...

Token Authentication i JWT

Podeu llegir sobre token authentication i les seves bones pràctiques. L'article explica força bé un tipus particular de token auth per al context web anomenat JWT (JSON Web Tokens) que utilitzen un sistema de signatura digital. La única pega que té és que té una certa complicació en la implementació.

Com a referència, aquí tens un tutorial per a JWT amb NodeJS, tingues en compte que utilitza MongoDB (amb mongoose per emmagatzemar els tokens. Utilitza'l només si has entès bé com emprar la signatura digital.


Posant NodeJS en producció amb Heroku

Segueix el tutorial NodeJS Heroku d'aquesta mateixa wiki.


Utilitzant MongoDB amb NodeJS

Segueix el tutorial accedint mongodb en què explica com utilitzar MongoDB amb PHP i NodeJS.


Accions en temps real amb Socket.IO

El protocol HTTP no és adequat per a temps real ja que no està orientat a connexió, i crea i destrueix el socket en cada request efectuada al servidor. Això es fa per tal d'alliberar recursos del servidor i no saturar-lo. La contrapartida és que afegeix un overhead de precessament que fa que per demanar dades molt sovint no sigui adequat. Per enviar dades repetidament (com podria ser el cas d'un chat, o millor encara, el moviment d'un joystick) sigui millor mantenir el socket obert.

Una eina adequada per acomplir això és Socket.IO . Recomanable el tutorial inicial per crear un programa de xat que il·lustra molt bé com treballar.


nodejs_express.txt · Darrera modificació: 2022/03/02 10:39 per enrique_mieza_sanchez