SlideShare una empresa de Scribd logo
1 de 59
Javascript en el servidor
NodeJs
Jose Emilio Labra Gayo
Depto. Informática
Universidad de Oviedo
Javascript en servidor
Intentos iniciales fallidos:
Netscape (1994), Microsoft IIS
Javascript engine race (2008/9)
V8 (Google), Rhino (Mozilla)
CommonJs (2009)
Especificaciones para Javascript en servidor
Node.js (2009)
Node.js v4 (2015) y soporte para ES6
http://talks.continuation.io/nova-node-meetup-9-15
Desarrollado en 2009 por Ryan Dahl
Entorno de ejecución de Javascript en servidor
Entrada/Salida sin bloqueo
Arquitectura basada en eventos
Ventajas
Sencillez
Fácil escalabilidad
Buena aceptación industrial Ryan Dahl, Fuente: Wikipedia
NodeJs
Vídeos recomendados:
http://goo.gl/DvUqlp (2012, entrevista)
http://goo.gl/jT6xpa (2009, Presentación original)
Implementado sobre v8
Motor javascript de Google
Compilación Just In Time
Proporciona entorno de bajo nivel
Contiene muuuuchos paquetes de más alto nivel:
Express: framework web MVC
Nodemon: Permite hacer cambios en caliente
....
NodeJs
npm - Gestión de paquetes
npm = node package manager
Incluido en la instalación de nodejs
Herramienta en línea de comandos
Similar a maven, gradle, sbt, ...pero para Javascript
Gestión de dependencias y repositorio de paquetes
Fichero de configuración: package.json
npm init // Crea fichero package.json
npm install <paquete> // Instalar paquete
npm install --save <paquete> // Instalar y añadir a package.json
npm install -g <paquete> // Instalar globalmente
npm uninstall <paquete> // Desinstalar paquete
npm update // Actualizar paquetes
NodeJs como lenguaje
Ejemplo Hola mundo
console.log("Hola desde Node");
$ node hola.js
Hola desde Node
hola.js
NodeJs en Servidor
Ejemplo "Hola Mundo" en la Web
$ node hola.js
Servidor arrancado
hola.jsconst http = require('http');
const server = http.createServer();
server.on('request',procesa);
server.listen(3000);
console.log('Servidor arrancado');
function procesa(request, response) {
let url = request.url;
console.log(`URL solicitada: ${url}`);
response.end("Hola");
}
Fundamentos de NodeJs
Funciones de orden superior y callbacks
Programación asíncrona sin bloqueos
Arquitectura basada en eventos
Sistema de módulos
Streams
Funciones de orden superior
Funciones = elementos de primera clase
Pueden asignarse a variables, pasarse como
argumentos o incluso devolverse como valores
=
function suma3(x) {
return x + 3;
}
function aplica2(f,x) {
return f (f (x));
};
const suma3 = x => x + 3
const aplica2 = (f,x) => f (f (x))
console.log(aplica2(suma3,4));
console.log(aplica2(x => x * x,5));
10
625
const fs = require('fs');
const input = "fichero.txt";
function cb(err, datos) {
if (err) throw err;
datos = datos.toUpperCase();
console.log(datos);
}
fs.readFile(input, 'utf8', cb);
Callbacks
Callback
Función que se pasa como argumento a otra
La otra función invoca el callback al finalizar
Puede simplificarse mediante
funciones anónimas
fs.readFile(input,'utf8',(err,datos)=>{
if (err) throw err;
datos = datos.toUpperCase();
console.log(datos);
});
Programación asíncrona
E/S asíncrona mediante callbacks
...
resultado = query('SELECT * FROM posts WHERE id = 1');
hacer_algo_con(resultado);
hacer_otra_cosa
Modelo síncrono
...
query('SELECT * FROM posts WHERE id = 1', function(resultado) {
hacer_algo_con(resultado);
});
hacer_otra_cosa
Modelo asíncrono
callback es invocada cuando la consulta finalice
recibe los resultados de la consulta
hacer_otra_cosa no espera a que finalice la consulta
hacer_otra_cosa espera hasta que la consulta finalice
Buena introducción: https://github.com/maxogden/art-of-node#callbacks
function prueba(f) { setTimeout(f, 500); }
let color = 'azul';
function verColor() {
console.log(`El color es ${color}`);
}
verColor();
prueba(verColor);
color = 'verde';
verColor();
Programación asíncrona
Ejercicio...
Nota:
Las funciones no se ejecutan hasta que no son invocadas
setTimeout(f,x) llama a f después de x milisegundos
el color es azul
el color es verde
el color es verde
Programación asíncrona
NodeJs favorece programación asíncrona
La mayoría de las funciones son asíncronas
Ejemplo: readFile(file[,options],callback)
En ese caso, callback tiene 2 argumentos:
err: Contendrá información del error (si se produjo)
data: Contendrá los datos leídos
Existen funciones síncronas:
Ejemplo: readFileSync(file[,options])
PERO se desaconseja su uso, ya que bloquean el programa
Programación asíncrona
Ejercicio:
• Crear un programa que lea el contenido de un
fichero e indique el tamaño
• Crear un programa que lea los contenidos de dos
ficheros e indique cuál de ellos es mayor.
Programación asíncrona
Código asíncrono puede ser difícil de gestionar
Código piramidal (callbackhell.com)
Librerías que facilitan organización de código:
Async.js, Nimble, Promises, ...
setTimeout(function() {
console.log('Primer bloque');
setTimeout(function() {
console.log('Siguiente bloque');
setTimeout(function() {
console.log('Último bloque');
}, 100);
}, 500);
}, 1000);
Arquitectura basada en eventos
NodeJs se basa en eventos
Un único hilo ó thread
Bucle de eventos: repeat forever {
detectar evento
invocar manejador de evento
}
Detalles
Un único manejador de eventos ejecutándose en cada momento
Cada manejador de eventos se ejecuta hasta el final
Sin interrupción
No hay que preocuparse de sincronización
Arquitectura basada en eventos
Objetos emisores de eventos (EventEmitter)
Emiten eventos con nombre periódicamente
Los eventos se identifican con un string
Ejemplo: 'data', 'end', 'request', 'connection'...
Event listeners = funciones asociadas a eventos
Se invocan al producirse dichos eventos
Métodos para asociar listeners:
addListener, on, once, removeListener, ...
Arquitectura basada en eventos
Asociar listeners de eventos
const http = require('http');
const server = http.createServer();
server.on('request',procesa);
server.listen(3000);
console.log('Servidor arrancado');
function procesa(request, response) {
let url = request.url;
console.log(`URL solicitada: ${url}`);
response.end("Hola");
}
Sistema de módulos
nodeJs utiliza sistema de módulos
Inicialmente basado en CommonJs
require importa un módulo
exports declara objeto que estará disponible
persona.js
const EDAD_VOTO = 18
const persona = {
nombre: "Juan",
edad: 20
}
function puedeVotar() {
return persona.edad > EDAD_VOTO
}
module.exports = persona;
module.exports.puedeVotar = puedeVotar;
const persona=require('./persona');
console.log(persona.nombre);
console.log(persona.puedeVotar());
Módulos y clases (ES6)
Módulo de gestión alumnos
Forma de uso:
class Alumno {
constructor(nombre) {
this.nombre = nombre ;
this.edad = 0 ;
}
setEdad(edad) {
this.edad = edad;
}
saluda() {
console.log(`Soy ${this.nombre}, mi edad es ${this.edad}`)
}
}
module.exports.Alumno = Alumno ;
const Alumno = require('./alumno').Alumno;
let juan = new Alumno("Juan");
juan.setEdad(24);
juan.saluda();
exports.Alumno = class {
...
}Se puede simplificar como
Pruebas unitarias: mocha
Ejercicio:
• Crear una función que comprueba si un nº es par
• Crear una función que calcule el factorial de un nº
Sugerencia: Desarrollo TDD mediante
Fichero de pruebas:
https://gist.github.com/labra/43bb6607265cf9601fca
function par(x) { return (x % 2 == 0); }
function factorial(x) {
if (x < 0) throw "valor negativo";
if (x == 0) return 1
else return x * factorial(x - 1);
}
module.exports.par = par;
module.exports.factorial = factorial;
Descomposición factores
Ejercicio:
• Crear una función que calcule los factores de un nº
Fichero de pruebas:
https://gist.github.com/labra/da7138683bec4a772521
factores(84) = [1,2,2,3,7]
Ejemplo
Curso y alumnos
Ejercicio: Modelar cursos con alumnos
Curso compuesto por:
Nombre del curso
Lista de alumnos
Alumno compuesto por
id del alumno
nota del alumno
Definir métodos de curso:
getNota(id)
ponNota(id,nota)
media
Fichero de pruebas:
https://gist.github.com/labra/660f4944af612fef2f26
Curso Alumno
1..n1
Sistema de módulos
Existen multiples módulos en NodeJs
Algunos módulos core. 'http', 'fs', 'tcp', etc.
Fichero package.json
Permite controlar dependencias a través de npm
Convención para buscar módulos:
require('/home/pepe/m.js'): módulo local
require('./circulo.js'): módulo local en mismo directorio
require('http'): módulo core
require('pepe'): se busca en directorio node_modules
Streams
Interfaces que representan flujos de datos
Todos los streams son instancia de EventEmitter
Ejemplos: stdout, stdin, request, ...
Pueden ser Readable, Writable, ó ambos
Eventos:
'data': Datos recibidos,
'end': Fin de datos
'error': Error recibiendo/escribiendo datos
Streams
Métodos:
setEncoding(e): e puede ser 'utf8', 'hex'
read(): leer datos
write(): escribir datos
pause(): detener emission de datos
resume(): continuar emitiendo datos
pipe(destino,opciones): enlazar datos en destino
unpipe: deshacer los enlaces existentes
...
Objeto process
Objeto global, único en cada aplicación
Contiene información sobre proceso y contexto
process.argv = Argumentos de invocación
process.env = Variables de entorno
process.stdin = Stream de entrada
process.stdout = Stream de salida
process.stderr = Stream de error
...
Línea de comandos
Ejemplo programa que lee argumentos
let args = process.argv.slice(2);
if (args.length == 1) {
console.log("¡Hola " + args[0] + "!");
} else {
console.log("Número de argumentos incorrecto");
}
$ node hola.js pepe
¡Hola Pepe!
hola.js
Línea de commandos: stdin/stdout
Ejemplo con stdin, stdout
Solicitar un número y devolver el doble del número
pideNum("Teclea un número", function(num) {
console.log("El doble de tu número es " + (num * 2) );
process.exit();
});
function pideNum(msg, callback) {
process.stdin.resume();
process.stdout.write(msg + ": ");
process.stdin.once('data', function(data) {
if (isNaN(data)) {
process.stdout.write("Debe ser un númeron");
pideNum(msg, callback);
} else {
callback(data);
}});
}
Juego
Juego de adivinar un nº entre 0 y 100
Sistema de ficheros
Módulo predefinido 'fs'
Envuelve llamadas a funciones POSIX
Los métodos tienen forma síncrona y asíncrona
Forma asíncrona:
Se usa un callback como último argumento
Convención: Primer argumento del callback = excepción
Si se ejecuta con éxito, primer argumento = null ó undefined
Forma síncrona:
No se utiliza último argumento callback
Se lanzan excepciones directamente
Se recomienda usar operaciones asíncronas para evitar bloqueos
Sistema de ficheros
Sistema de ficheros
Leer un fichero y convertir a mayúsculas
const fs = require('fs');
const input = process.argv[2], output = process.argv[3];
fs.readFile(input, 'utf8', function(err, data) {
if (err) throw "No se puede leer " + input + "n" + err;
data = data.toUpperCase();
fs.writeFile(output,data,'utf8', function(err) {
if (err) throw "No se puede escribir " + output + "n" + err;
console.log("Contenidos guardados en..." + output);
});
});
console.log("Cargando..." + input);
Módulo http
Ofrece funcionalidad de http
Métodos
http.get(opciones): crea una petición get
http.request(opciones): crea una petición
Devuelve una instancia de ClientRequest
http.createServer(): crea un servidor
Devuelve una instancia de Server
http request
Crea petición http (objeto ClientRequest)
2 Parámetros: options = opciones de la petición
callback: se invoca con respuesta recibida
La respuesta es un EventEmitter
const http=require('http');
const options = { hostname: 'www.uniovi.es', port: 80,
path: '/', method: 'GET' };
let total='';
var req = http.request(options, response => {
response.on("data", datos => { total+=datos;
console.log("%d bytes recibidos ", datos.length);
});
response.on("end", function() {
console.log("Datos totales = " + total.length);
});
});
req.end();
http get
Crea petición GET
Similar a http request pero usa siempre GET
const http = require('http');
let total='';
const req = http.get("http://www.uniovi.es", response => {
response.on("data", datos => { total+=datos;
console.log("%d bytes recibidos ", datos.length);
});
response.on("end", function() {
console.log("Datos totales = " + total.length);
});
}).on('error', (e) => {
console.log(`Got error: ${e.message}`);
});
http createServer
Crea un servidor http
Asocia un listener a cada petición
El listener muestra la url y escribe Hola
const http=require('http');
const server = http.createServer();
server.on('request', procesa);
server.listen(3000);
function procesa(request,response) {
console.log("URL solicitada = " + request.url);
response.setHeader("Content-Type", "text/html");
response.write("<p>Hola</p>");
response.end();
}
http.createServer(procesa).listen(3000);
Puede simplificarse como:
Esquema
Cliente server
listener
(procesa)
console
const http=require('http');
const server = http.createServer();
server.on('request', procesa);
server.listen(3000);
function procesa(req,response) {
console.log(req.url);
response.setHeader("Content-Type", "text/html");
response.write("<p>Hola</p>");
response.end();
}
GET /pepe
crea request
crea response
emit('request',request,response)
console.log(req.url)
/pepe
response.setHeader("Content-Type", "text/html");
response.write("<p>Hola</p>");
response.end();
Hola
Clase Server
Representa un servidor Web
Es un EventEmitter
Eventos: 'request', 'connect', 'close',...
Métodos
server.listen(Puerto,...):comienza a aceptar conexiones en Puerto
IncomingMessage
Son creados por http.server
Primer argumento de evento 'request'
Implementa interfaz Readable Stream
Eventos: 'data' , 'end',...
Métodos:
httpVersion
headers: Objeto Json con cabeceras
method: puede ser GET, PUT, POST, DELETE,...
url: string con la URL solicitada
IncomingMessage
Ejemplo, obtener datos POST
const http = require('http');
const qs = require('querystring')
http.createServer(procesa).listen(3000);
function procesa(req,resp) {
parseBody(req,resp,saluda);
}
function saluda(post,req,resp) {
resp.end("nombre " + post.nombre +
", edad= " + post.edad);
}
function parseBody(req, resp, next) {
let body = '';
req.on('data', data => {
body += data;
if (body.length > 1e6) {
console.log("Body too big!");
req.connection.destroy();
}
});
req.on('end', () => {
var post = qs.parse(body);
next(post,req,resp);
});
}
Probar con: curl -X POST -d "nombre=pepe&edad=34" http://127.0.0.1:3000
ServerResponse
Objeto creado por http.Server
Segundo argumento de evento 'request'
Implementa interfaz Writable Stream
Métodos:
writeHead(status, headers): envía cabecera de respuesta
statusCode: controla el código de estado
setHeader/removeHeader: añade/borra entradas en cabecera
write: Envía una porción de datos
end: Indica que ya no se va a enviar más datos
ServerResponse
Ejemplo: Devolver contenido HTML
function procesa(req,resp) {
fs.readFile('form.html','utf8',function (err,datos) {
resp.writeHead(200,'{content-type: text/html}');
resp.end(datos);
});
}
Procesar formularios
WWW
GET http://ejemplo.com/form.html
Usuario
Servidor
POST http://ejemplo.com/procesa
cliente = pepe
correo = pepe@kiko.com
form.html
resultado
<h1>Hola Pepe</h1>
<p>Email: pepe@kiko.com</p>
const server = http.createServer(function (req,res){
switch (req.method) {
case 'POST': ... break;
case 'GET': ...break;
default: ...
Procesar formularios
https://goo.gl/Kb2KCi
const http = require('http'),
fs = require('fs'),
url = require('url'),
qs = require('querystring');
const server = http.createServer((req, res) => {
switch (req.method) {
case 'POST':
var body = '';
req.on('data', data => { body += data;
if (body.length > 1e6) req.connection.destroy();
});
req.on('end', () => {
var POST = qs.parse(body);
res.end("Hola " + POST.cliente + "! Tu email es:" + POST.correo);
});
break;
case 'GET':
if (url.parse(req.url, true).pathname == '/') {
fs.readFile('form.html','utf8',function (err,datos) {
res.writeHead(200,'{content-type: text/html}');
res.end(datos);
});
}
break;
default: console.log("Método no soportado" + req.method);
}
}).listen(3000);
Ejemplo API REST con NodeJs
function procesa(req,resp) {
switch (req.method) {
case 'GET': ... // leer un valor
break;
case 'DELETE': ... // borrar un valor
break;
case 'POST': ... // crear un valor
break;
case 'PUT': ... // actualizar un valor
break;
};
}
Ejemplo completo:
http://goo.gl/8Bw1UR
Ejemplos de uso con curl
Lista de alumnos: curl localhost:3000
Ver alumno: curl localhost:3000?id=1
Insertar alumno: curl -X POST -d "nombre=luis&edad=45" http://127.0.0.1:3000
Actualizar alumno: curl -X PUT -d "nombre=Jose&edad=26" http://127.0.0.1:3000?id=0
Borrar alumno: curl -X DELETE localhost:3000?id=1
Subiendo ficheros (paquete formidable)
const formidable = require('formidable'), fs = require('fs'), http = require('http')
http.createServer((req, resp) => {
switch (req.method) {
case 'GET': pideFichero(req,resp); break;
case 'POST': procesaFichero(req,resp); break;
}}).listen(3000);
function procesaFichero(req,resp) {
let form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
resp.writeHead(200, {'content-type': 'application/json'});
fs.readFile(files.fichero.path,'utf8', (err,datos) => {
if (err) throw err;
let json = JSON.parse(datos)
resp.end(JSON.stringify(json));
})});
return;
}
function pideFichero(req,resp) {
resp.writeHead(200, {'content-type': 'text/html'});
resp.end('<h1>Cargar fichero JSON</h1>' +
'<form action="/" enctype="multipart/form-data" method="post">'+
'<input type="file" name="fichero"><br>'+
'<input type="submit" value="Enviar">'+
'</form>'
);
} https://goo.gl/vADe6W
Otras variables globales
console
Métodos: log, debug, info, warn, error,...
__filename: nombre de fichero que se ejecuta
__dirname: directorio desde donde se ejecuta
Negociación de contenido
Negotiator: módulo para negociación de contenido
var Negotiator = require('negotiator');
var tiposDisponibles = ['text/html', 'application/xml'];
function showAlumnos(req,resp) {
var negotiator = new Negotiator(req);
var mediaType = negotiator.mediaType(tiposDisponibles);
switch (mediaType) {
case 'application/xml':
resp.setHeader('content-type',mediaType);
resp.end(alumnos.toXML());
break;
case 'text/html':
resp.setHeader('content-type', mediaType);
resp.end(alumnos.toHTML());
}
}
Ejemplo completo:
http://goo.gl/tWBAIZ
Express
Framework Web sobre Node
Modelo MVC
Facilita creación de aplicaciones Web
var express = require('express');
var app = express();
var port = 3000;
app.get('/usuario/:nombre', function(req, res){
console.log(req.route);
res.send('Hola ' + req.params.nombre + "!");
});
app.listen(port);
console.log("Servidor arrancado en puerto " + port);
Express
Negociación de contenido mediante Accept
const express = require('express');
const app = express();
const users = require('./users');
app.get('/users', function (req,res) {
res.format({
'text/html' : users.html,
'text/plain': users.text,
'application/json': users.json,
'application/xml': users.xml
});
});
app.listen(3000);
console.log('Servidor arrancado');
let users = [{ name: 'Juan' }, ... ];
exports.text = function(req, res){
res.send(users.map(function(user){
return ' - ' + user.name + 'n';
}).join(''));
};
exports.json = function(req, res){
res.json(users);
};
exports.html = function(req, res){
...
};
exports.xml = function(req, res){
...
};
Express
Express es un framework completo MVC
Otras características
Generación automática de aplicaciones
Plantillas HTML
Otros frameworks
Koa, Flatiron, total.js, restify,...
Probando servicios web
Se puede combinar mocha con supertest
const request = require('supertest');
const express = require('express');
const app = require('../apiUsers');
describe('GET /user', function() {
it('devuelve json', function(done) {
request(app)
.get('/users')
.set('Accept', 'application/json')
.expect('Content-Type', /application/json/)
.expect(200, done);
});
}
Acceso a bases de datos
Módulos Mongoose (MongoDB)
Módulo mysql (MySQL)
Ejemplos
Ejemplos utilizados en Node
https://github.com/labra/EjemploNode
Ejemplo con Node y MongoDB
https://github.com/labra/EjemploNode_Mongo
Ejemplo con Node y MySQL
https://github.com/labra/EjemploNode_MySQL
XML con NodeJs
Múltiples librerías.
Ejemplo: libxmljs, libxslt
Enlaces a librería libxml
NOTA:
Instalación en Windows requiere: node_gyp
Ver: https://github.com/TooTallNate/node-gyp/
XPath con NodeJs
Leer fichero XML y acceder a elementos con
XPath
const fs = require('fs');
const libxmljs = require('libxmljs')
let input = process.argv[2], xpath = process.argv[3];
fs.readFile(input, function (err, contents) {
if (err) throw "Cannot open " + input + "n" + err;
var xml = libxmljs.parseXmlString(contents);
var result = xml.get(xpath);
console.log("Resultado: " + result);
});
Manipular XML con NodeJs
Leer fichero XML, añadir hijo y guardarlo
const fs = require('fs');
const libxmljs = require('libxmljs')
let file = process.argv[2];
fs.readFile(file, function (err, contents) {
if (err) throw "Cannot open " + file + "n" + err;
var xml = libxmljs.parseXmlString(contents);
var newChild = libxmljs.Element(xml, 'new-child');
xml.root().addChild(newChild);
fs.writeFile(file, xml.toString(), function (err) {
console.log("Updated file " + file);
});
});
XML Schema con NodeJs
Validar mediante XML Schema
const fs = require('fs');
const libxmljs = require('libxmljs')
let xmlFile = process.argv[2], xsdFile = process.argv[3];
fs.readFile(xmlFile, function (err, dataxml) {
if (err) throw "Cannot open " + xmlFile + "n" + err;
fs.readFile(xsdFile, function (err, dataxsd) {
if (err) throw "Cannot open " + xsdFile + "n" + err;
let xml = libxmljs.parseXml(dataxml);
let xsd = libxmljs.parseXml(dataxsd);
if (xml.validate(xsd)) {
console.log("Es válido");
} else {
console.log("No válidon" + xml.validationErrors);
}
});
});
XSLT con NodeJs
Transformar con XSLT
const libxslt = require('libxslt');
let xmlFile = process.argv[2];
let xslFile = process.argv[3];
libxslt.parseFile(xslFile, function (err, xsl) {
if (err) throw "Cannot open " + xslFile + "n" + err;
xsl.applyToFile(xmlFile,function (err,result) {
if (err) throw "Cannot apply to file " + xmlFile + "n" + err;
console.log(result);
});
});

Más contenido relacionado

La actualidad más candente

La actualidad más candente (18)

Curso scjp 30 navegacion de archivos e io
Curso scjp 30   navegacion de archivos e ioCurso scjp 30   navegacion de archivos e io
Curso scjp 30 navegacion de archivos e io
 
Tema1oficial
Tema1oficialTema1oficial
Tema1oficial
 
Frameworks de templates y xml
Frameworks de templates y xmlFrameworks de templates y xml
Frameworks de templates y xml
 
04 j flex
04 j flex04 j flex
04 j flex
 
Blind X Path Injection
Blind X Path InjectionBlind X Path Injection
Blind X Path Injection
 
Iniciación PHP 5. PHP y MySQL
Iniciación PHP 5. PHP y MySQLIniciación PHP 5. PHP y MySQL
Iniciación PHP 5. PHP y MySQL
 
Php!
Php!Php!
Php!
 
Primeros pasos con Neo4j
Primeros pasos con Neo4jPrimeros pasos con Neo4j
Primeros pasos con Neo4j
 
php y mysql
php y mysqlphp y mysql
php y mysql
 
5
55
5
 
Introducción a XML Schema
Introducción a XML SchemaIntroducción a XML Schema
Introducción a XML Schema
 
Manejo de archivos en java
Manejo de archivos en javaManejo de archivos en java
Manejo de archivos en java
 
Curso scjp 30 navegacion de archivos e io
Curso scjp 30   navegacion de archivos e ioCurso scjp 30   navegacion de archivos e io
Curso scjp 30 navegacion de archivos e io
 
Unidad iii pilas y colas
Unidad iii pilas y colasUnidad iii pilas y colas
Unidad iii pilas y colas
 
Entrada De Datos
Entrada De DatosEntrada De Datos
Entrada De Datos
 
Introducción a PHP5
Introducción a PHP5Introducción a PHP5
Introducción a PHP5
 
Archivos aleatorios en java
Archivos aleatorios en javaArchivos aleatorios en java
Archivos aleatorios en java
 
Ejercicios de XSD
Ejercicios de XSDEjercicios de XSD
Ejercicios de XSD
 

Similar a 19 javascript servidor

Desarrollo web en Nodejs con Pillars por Chelo Quilón
Desarrollo web en Nodejs con Pillars por Chelo QuilónDesarrollo web en Nodejs con Pillars por Chelo Quilón
Desarrollo web en Nodejs con Pillars por Chelo Quilónbetabeers
 
Introducción a NodeJS
Introducción a NodeJSIntroducción a NodeJS
Introducción a NodeJSBEEVA_es
 
Creación de aplicaciones web con Node.js y Express
Creación de aplicaciones web con Node.js y ExpressCreación de aplicaciones web con Node.js y Express
Creación de aplicaciones web con Node.js y Expressbetabeers
 
Testing efectivo con pytest
Testing efectivo con pytestTesting efectivo con pytest
Testing efectivo con pytestHector Canto
 
Node js Alt.net Hispano
Node js Alt.net HispanoNode js Alt.net Hispano
Node js Alt.net Hispanohdgarcia
 
Node Js & 3D Printer
Node Js & 3D PrinterNode Js & 3D Printer
Node Js & 3D Printernanusefue
 
Bases de Datos en Java - Intro a JDBC
Bases de Datos en Java - Intro a JDBCBases de Datos en Java - Intro a JDBC
Bases de Datos en Java - Intro a JDBCCarlos Hernando
 
Introducción al desarrollo Web: Frontend con Angular 6
Introducción al desarrollo Web: Frontend con Angular 6Introducción al desarrollo Web: Frontend con Angular 6
Introducción al desarrollo Web: Frontend con Angular 6Gabriela Bosetti
 
Aprendiendo a usar NDK Android Day(castellano)
Aprendiendo a usar NDK Android Day(castellano)Aprendiendo a usar NDK Android Day(castellano)
Aprendiendo a usar NDK Android Day(castellano)videos
 
PARADIGMAS FP Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONA
PARADIGMAS FP  Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONAPARADIGMAS FP  Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONA
PARADIGMAS FP Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONAVíctor Bolinches
 
Explicacion de la Clase en Java-MySQL.pdf
Explicacion de la Clase en Java-MySQL.pdfExplicacion de la Clase en Java-MySQL.pdf
Explicacion de la Clase en Java-MySQL.pdfGregorioSnchez7
 
PowerShell para administradores
PowerShell para administradoresPowerShell para administradores
PowerShell para administradoresPablo Campos
 

Similar a 19 javascript servidor (20)

Desarrollo web en Nodejs con Pillars por Chelo Quilón
Desarrollo web en Nodejs con Pillars por Chelo QuilónDesarrollo web en Nodejs con Pillars por Chelo Quilón
Desarrollo web en Nodejs con Pillars por Chelo Quilón
 
Introducción a NodeJS
Introducción a NodeJSIntroducción a NodeJS
Introducción a NodeJS
 
Creación de aplicaciones web con Node.js y Express
Creación de aplicaciones web con Node.js y ExpressCreación de aplicaciones web con Node.js y Express
Creación de aplicaciones web con Node.js y Express
 
Testing efectivo con pytest
Testing efectivo con pytestTesting efectivo con pytest
Testing efectivo con pytest
 
Lenguajes de Programación: Clases y objetos
Lenguajes de Programación: Clases y objetosLenguajes de Programación: Clases y objetos
Lenguajes de Programación: Clases y objetos
 
Concurrencia en Java
Concurrencia en Java Concurrencia en Java
Concurrencia en Java
 
Node js Alt.net Hispano
Node js Alt.net HispanoNode js Alt.net Hispano
Node js Alt.net Hispano
 
APIREST LARAVEL Y PHP.pptx
APIREST LARAVEL Y PHP.pptxAPIREST LARAVEL Y PHP.pptx
APIREST LARAVEL Y PHP.pptx
 
Tema servlets
Tema servletsTema servlets
Tema servlets
 
Tema servlets
Tema servletsTema servlets
Tema servlets
 
Tema servlets
Tema servletsTema servlets
Tema servlets
 
Tema servlets
Tema servletsTema servlets
Tema servlets
 
Node Js & 3D Printer
Node Js & 3D PrinterNode Js & 3D Printer
Node Js & 3D Printer
 
Bases de Datos en Java - Intro a JDBC
Bases de Datos en Java - Intro a JDBCBases de Datos en Java - Intro a JDBC
Bases de Datos en Java - Intro a JDBC
 
Introducción al desarrollo Web: Frontend con Angular 6
Introducción al desarrollo Web: Frontend con Angular 6Introducción al desarrollo Web: Frontend con Angular 6
Introducción al desarrollo Web: Frontend con Angular 6
 
Aprendiendo a usar NDK Android Day(castellano)
Aprendiendo a usar NDK Android Day(castellano)Aprendiendo a usar NDK Android Day(castellano)
Aprendiendo a usar NDK Android Day(castellano)
 
PARADIGMAS FP Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONA
PARADIGMAS FP  Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONAPARADIGMAS FP  Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONA
PARADIGMAS FP Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONA
 
Explicacion de la Clase en Java-MySQL.pdf
Explicacion de la Clase en Java-MySQL.pdfExplicacion de la Clase en Java-MySQL.pdf
Explicacion de la Clase en Java-MySQL.pdf
 
OSGi
OSGiOSGi
OSGi
 
PowerShell para administradores
PowerShell para administradoresPowerShell para administradores
PowerShell para administradores
 

Más de Jose Emilio Labra Gayo

Introducción a la investigación/doctorado
Introducción a la investigación/doctoradoIntroducción a la investigación/doctorado
Introducción a la investigación/doctoradoJose Emilio Labra Gayo
 
Challenges and applications of RDF shapes
Challenges and applications of RDF shapesChallenges and applications of RDF shapes
Challenges and applications of RDF shapesJose Emilio Labra Gayo
 
Legislative data portals and linked data quality
Legislative data portals and linked data qualityLegislative data portals and linked data quality
Legislative data portals and linked data qualityJose Emilio Labra Gayo
 
Validating RDF data: Challenges and perspectives
Validating RDF data: Challenges and perspectivesValidating RDF data: Challenges and perspectives
Validating RDF data: Challenges and perspectivesJose Emilio Labra Gayo
 
Legislative document content extraction based on Semantic Web technologies
Legislative document content extraction based on Semantic Web technologiesLegislative document content extraction based on Semantic Web technologies
Legislative document content extraction based on Semantic Web technologiesJose Emilio Labra Gayo
 
Como publicar datos: hacia los datos abiertos enlazados
Como publicar datos: hacia los datos abiertos enlazadosComo publicar datos: hacia los datos abiertos enlazados
Como publicar datos: hacia los datos abiertos enlazadosJose Emilio Labra Gayo
 
RDF Validation Future work and applications
RDF Validation Future work and applicationsRDF Validation Future work and applications
RDF Validation Future work and applicationsJose Emilio Labra Gayo
 

Más de Jose Emilio Labra Gayo (20)

Publicaciones de investigación
Publicaciones de investigaciónPublicaciones de investigación
Publicaciones de investigación
 
Introducción a la investigación/doctorado
Introducción a la investigación/doctoradoIntroducción a la investigación/doctorado
Introducción a la investigación/doctorado
 
Challenges and applications of RDF shapes
Challenges and applications of RDF shapesChallenges and applications of RDF shapes
Challenges and applications of RDF shapes
 
Legislative data portals and linked data quality
Legislative data portals and linked data qualityLegislative data portals and linked data quality
Legislative data portals and linked data quality
 
Validating RDF data: Challenges and perspectives
Validating RDF data: Challenges and perspectivesValidating RDF data: Challenges and perspectives
Validating RDF data: Challenges and perspectives
 
Wikidata
WikidataWikidata
Wikidata
 
Legislative document content extraction based on Semantic Web technologies
Legislative document content extraction based on Semantic Web technologiesLegislative document content extraction based on Semantic Web technologies
Legislative document content extraction based on Semantic Web technologies
 
ShEx by Example
ShEx by ExampleShEx by Example
ShEx by Example
 
Introduction to SPARQL
Introduction to SPARQLIntroduction to SPARQL
Introduction to SPARQL
 
Introducción a la Web Semántica
Introducción a la Web SemánticaIntroducción a la Web Semántica
Introducción a la Web Semántica
 
RDF Data Model
RDF Data ModelRDF Data Model
RDF Data Model
 
2017 Tendencias en informática
2017 Tendencias en informática2017 Tendencias en informática
2017 Tendencias en informática
 
RDF, linked data and semantic web
RDF, linked data and semantic webRDF, linked data and semantic web
RDF, linked data and semantic web
 
Introduction to SPARQL
Introduction to SPARQLIntroduction to SPARQL
Introduction to SPARQL
 
Como publicar datos: hacia los datos abiertos enlazados
Como publicar datos: hacia los datos abiertos enlazadosComo publicar datos: hacia los datos abiertos enlazados
Como publicar datos: hacia los datos abiertos enlazados
 
XSLT
XSLTXSLT
XSLT
 
XPath
XPathXPath
XPath
 
RDF validation tutorial
RDF validation tutorialRDF validation tutorial
RDF validation tutorial
 
RDF Validation Future work and applications
RDF Validation Future work and applicationsRDF Validation Future work and applications
RDF Validation Future work and applications
 
ShEx vs SHACL
ShEx vs SHACLShEx vs SHACL
ShEx vs SHACL
 

19 javascript servidor

  • 1. Javascript en el servidor NodeJs Jose Emilio Labra Gayo Depto. Informática Universidad de Oviedo
  • 2. Javascript en servidor Intentos iniciales fallidos: Netscape (1994), Microsoft IIS Javascript engine race (2008/9) V8 (Google), Rhino (Mozilla) CommonJs (2009) Especificaciones para Javascript en servidor Node.js (2009) Node.js v4 (2015) y soporte para ES6 http://talks.continuation.io/nova-node-meetup-9-15
  • 3. Desarrollado en 2009 por Ryan Dahl Entorno de ejecución de Javascript en servidor Entrada/Salida sin bloqueo Arquitectura basada en eventos Ventajas Sencillez Fácil escalabilidad Buena aceptación industrial Ryan Dahl, Fuente: Wikipedia NodeJs Vídeos recomendados: http://goo.gl/DvUqlp (2012, entrevista) http://goo.gl/jT6xpa (2009, Presentación original)
  • 4. Implementado sobre v8 Motor javascript de Google Compilación Just In Time Proporciona entorno de bajo nivel Contiene muuuuchos paquetes de más alto nivel: Express: framework web MVC Nodemon: Permite hacer cambios en caliente .... NodeJs
  • 5. npm - Gestión de paquetes npm = node package manager Incluido en la instalación de nodejs Herramienta en línea de comandos Similar a maven, gradle, sbt, ...pero para Javascript Gestión de dependencias y repositorio de paquetes Fichero de configuración: package.json npm init // Crea fichero package.json npm install <paquete> // Instalar paquete npm install --save <paquete> // Instalar y añadir a package.json npm install -g <paquete> // Instalar globalmente npm uninstall <paquete> // Desinstalar paquete npm update // Actualizar paquetes
  • 6. NodeJs como lenguaje Ejemplo Hola mundo console.log("Hola desde Node"); $ node hola.js Hola desde Node hola.js
  • 7. NodeJs en Servidor Ejemplo "Hola Mundo" en la Web $ node hola.js Servidor arrancado hola.jsconst http = require('http'); const server = http.createServer(); server.on('request',procesa); server.listen(3000); console.log('Servidor arrancado'); function procesa(request, response) { let url = request.url; console.log(`URL solicitada: ${url}`); response.end("Hola"); }
  • 8. Fundamentos de NodeJs Funciones de orden superior y callbacks Programación asíncrona sin bloqueos Arquitectura basada en eventos Sistema de módulos Streams
  • 9. Funciones de orden superior Funciones = elementos de primera clase Pueden asignarse a variables, pasarse como argumentos o incluso devolverse como valores = function suma3(x) { return x + 3; } function aplica2(f,x) { return f (f (x)); }; const suma3 = x => x + 3 const aplica2 = (f,x) => f (f (x)) console.log(aplica2(suma3,4)); console.log(aplica2(x => x * x,5)); 10 625
  • 10. const fs = require('fs'); const input = "fichero.txt"; function cb(err, datos) { if (err) throw err; datos = datos.toUpperCase(); console.log(datos); } fs.readFile(input, 'utf8', cb); Callbacks Callback Función que se pasa como argumento a otra La otra función invoca el callback al finalizar Puede simplificarse mediante funciones anónimas fs.readFile(input,'utf8',(err,datos)=>{ if (err) throw err; datos = datos.toUpperCase(); console.log(datos); });
  • 11. Programación asíncrona E/S asíncrona mediante callbacks ... resultado = query('SELECT * FROM posts WHERE id = 1'); hacer_algo_con(resultado); hacer_otra_cosa Modelo síncrono ... query('SELECT * FROM posts WHERE id = 1', function(resultado) { hacer_algo_con(resultado); }); hacer_otra_cosa Modelo asíncrono callback es invocada cuando la consulta finalice recibe los resultados de la consulta hacer_otra_cosa no espera a que finalice la consulta hacer_otra_cosa espera hasta que la consulta finalice Buena introducción: https://github.com/maxogden/art-of-node#callbacks
  • 12. function prueba(f) { setTimeout(f, 500); } let color = 'azul'; function verColor() { console.log(`El color es ${color}`); } verColor(); prueba(verColor); color = 'verde'; verColor(); Programación asíncrona Ejercicio... Nota: Las funciones no se ejecutan hasta que no son invocadas setTimeout(f,x) llama a f después de x milisegundos el color es azul el color es verde el color es verde
  • 13. Programación asíncrona NodeJs favorece programación asíncrona La mayoría de las funciones son asíncronas Ejemplo: readFile(file[,options],callback) En ese caso, callback tiene 2 argumentos: err: Contendrá información del error (si se produjo) data: Contendrá los datos leídos Existen funciones síncronas: Ejemplo: readFileSync(file[,options]) PERO se desaconseja su uso, ya que bloquean el programa
  • 14. Programación asíncrona Ejercicio: • Crear un programa que lea el contenido de un fichero e indique el tamaño • Crear un programa que lea los contenidos de dos ficheros e indique cuál de ellos es mayor.
  • 15. Programación asíncrona Código asíncrono puede ser difícil de gestionar Código piramidal (callbackhell.com) Librerías que facilitan organización de código: Async.js, Nimble, Promises, ... setTimeout(function() { console.log('Primer bloque'); setTimeout(function() { console.log('Siguiente bloque'); setTimeout(function() { console.log('Último bloque'); }, 100); }, 500); }, 1000);
  • 16. Arquitectura basada en eventos NodeJs se basa en eventos Un único hilo ó thread Bucle de eventos: repeat forever { detectar evento invocar manejador de evento } Detalles Un único manejador de eventos ejecutándose en cada momento Cada manejador de eventos se ejecuta hasta el final Sin interrupción No hay que preocuparse de sincronización
  • 17. Arquitectura basada en eventos Objetos emisores de eventos (EventEmitter) Emiten eventos con nombre periódicamente Los eventos se identifican con un string Ejemplo: 'data', 'end', 'request', 'connection'... Event listeners = funciones asociadas a eventos Se invocan al producirse dichos eventos Métodos para asociar listeners: addListener, on, once, removeListener, ...
  • 18. Arquitectura basada en eventos Asociar listeners de eventos const http = require('http'); const server = http.createServer(); server.on('request',procesa); server.listen(3000); console.log('Servidor arrancado'); function procesa(request, response) { let url = request.url; console.log(`URL solicitada: ${url}`); response.end("Hola"); }
  • 19. Sistema de módulos nodeJs utiliza sistema de módulos Inicialmente basado en CommonJs require importa un módulo exports declara objeto que estará disponible persona.js const EDAD_VOTO = 18 const persona = { nombre: "Juan", edad: 20 } function puedeVotar() { return persona.edad > EDAD_VOTO } module.exports = persona; module.exports.puedeVotar = puedeVotar; const persona=require('./persona'); console.log(persona.nombre); console.log(persona.puedeVotar());
  • 20. Módulos y clases (ES6) Módulo de gestión alumnos Forma de uso: class Alumno { constructor(nombre) { this.nombre = nombre ; this.edad = 0 ; } setEdad(edad) { this.edad = edad; } saluda() { console.log(`Soy ${this.nombre}, mi edad es ${this.edad}`) } } module.exports.Alumno = Alumno ; const Alumno = require('./alumno').Alumno; let juan = new Alumno("Juan"); juan.setEdad(24); juan.saluda(); exports.Alumno = class { ... }Se puede simplificar como
  • 21. Pruebas unitarias: mocha Ejercicio: • Crear una función que comprueba si un nº es par • Crear una función que calcule el factorial de un nº Sugerencia: Desarrollo TDD mediante Fichero de pruebas: https://gist.github.com/labra/43bb6607265cf9601fca function par(x) { return (x % 2 == 0); } function factorial(x) { if (x < 0) throw "valor negativo"; if (x == 0) return 1 else return x * factorial(x - 1); } module.exports.par = par; module.exports.factorial = factorial;
  • 22. Descomposición factores Ejercicio: • Crear una función que calcule los factores de un nº Fichero de pruebas: https://gist.github.com/labra/da7138683bec4a772521 factores(84) = [1,2,2,3,7] Ejemplo
  • 23. Curso y alumnos Ejercicio: Modelar cursos con alumnos Curso compuesto por: Nombre del curso Lista de alumnos Alumno compuesto por id del alumno nota del alumno Definir métodos de curso: getNota(id) ponNota(id,nota) media Fichero de pruebas: https://gist.github.com/labra/660f4944af612fef2f26 Curso Alumno 1..n1
  • 24. Sistema de módulos Existen multiples módulos en NodeJs Algunos módulos core. 'http', 'fs', 'tcp', etc. Fichero package.json Permite controlar dependencias a través de npm Convención para buscar módulos: require('/home/pepe/m.js'): módulo local require('./circulo.js'): módulo local en mismo directorio require('http'): módulo core require('pepe'): se busca en directorio node_modules
  • 25. Streams Interfaces que representan flujos de datos Todos los streams son instancia de EventEmitter Ejemplos: stdout, stdin, request, ... Pueden ser Readable, Writable, ó ambos Eventos: 'data': Datos recibidos, 'end': Fin de datos 'error': Error recibiendo/escribiendo datos
  • 26. Streams Métodos: setEncoding(e): e puede ser 'utf8', 'hex' read(): leer datos write(): escribir datos pause(): detener emission de datos resume(): continuar emitiendo datos pipe(destino,opciones): enlazar datos en destino unpipe: deshacer los enlaces existentes ...
  • 27. Objeto process Objeto global, único en cada aplicación Contiene información sobre proceso y contexto process.argv = Argumentos de invocación process.env = Variables de entorno process.stdin = Stream de entrada process.stdout = Stream de salida process.stderr = Stream de error ...
  • 28. Línea de comandos Ejemplo programa que lee argumentos let args = process.argv.slice(2); if (args.length == 1) { console.log("¡Hola " + args[0] + "!"); } else { console.log("Número de argumentos incorrecto"); } $ node hola.js pepe ¡Hola Pepe! hola.js
  • 29. Línea de commandos: stdin/stdout Ejemplo con stdin, stdout Solicitar un número y devolver el doble del número pideNum("Teclea un número", function(num) { console.log("El doble de tu número es " + (num * 2) ); process.exit(); }); function pideNum(msg, callback) { process.stdin.resume(); process.stdout.write(msg + ": "); process.stdin.once('data', function(data) { if (isNaN(data)) { process.stdout.write("Debe ser un númeron"); pideNum(msg, callback); } else { callback(data); }}); }
  • 30. Juego Juego de adivinar un nº entre 0 y 100
  • 31. Sistema de ficheros Módulo predefinido 'fs' Envuelve llamadas a funciones POSIX Los métodos tienen forma síncrona y asíncrona Forma asíncrona: Se usa un callback como último argumento Convención: Primer argumento del callback = excepción Si se ejecuta con éxito, primer argumento = null ó undefined Forma síncrona: No se utiliza último argumento callback Se lanzan excepciones directamente Se recomienda usar operaciones asíncronas para evitar bloqueos
  • 32. Sistema de ficheros Sistema de ficheros Leer un fichero y convertir a mayúsculas const fs = require('fs'); const input = process.argv[2], output = process.argv[3]; fs.readFile(input, 'utf8', function(err, data) { if (err) throw "No se puede leer " + input + "n" + err; data = data.toUpperCase(); fs.writeFile(output,data,'utf8', function(err) { if (err) throw "No se puede escribir " + output + "n" + err; console.log("Contenidos guardados en..." + output); }); }); console.log("Cargando..." + input);
  • 33. Módulo http Ofrece funcionalidad de http Métodos http.get(opciones): crea una petición get http.request(opciones): crea una petición Devuelve una instancia de ClientRequest http.createServer(): crea un servidor Devuelve una instancia de Server
  • 34. http request Crea petición http (objeto ClientRequest) 2 Parámetros: options = opciones de la petición callback: se invoca con respuesta recibida La respuesta es un EventEmitter const http=require('http'); const options = { hostname: 'www.uniovi.es', port: 80, path: '/', method: 'GET' }; let total=''; var req = http.request(options, response => { response.on("data", datos => { total+=datos; console.log("%d bytes recibidos ", datos.length); }); response.on("end", function() { console.log("Datos totales = " + total.length); }); }); req.end();
  • 35. http get Crea petición GET Similar a http request pero usa siempre GET const http = require('http'); let total=''; const req = http.get("http://www.uniovi.es", response => { response.on("data", datos => { total+=datos; console.log("%d bytes recibidos ", datos.length); }); response.on("end", function() { console.log("Datos totales = " + total.length); }); }).on('error', (e) => { console.log(`Got error: ${e.message}`); });
  • 36. http createServer Crea un servidor http Asocia un listener a cada petición El listener muestra la url y escribe Hola const http=require('http'); const server = http.createServer(); server.on('request', procesa); server.listen(3000); function procesa(request,response) { console.log("URL solicitada = " + request.url); response.setHeader("Content-Type", "text/html"); response.write("<p>Hola</p>"); response.end(); } http.createServer(procesa).listen(3000); Puede simplificarse como:
  • 37. Esquema Cliente server listener (procesa) console const http=require('http'); const server = http.createServer(); server.on('request', procesa); server.listen(3000); function procesa(req,response) { console.log(req.url); response.setHeader("Content-Type", "text/html"); response.write("<p>Hola</p>"); response.end(); } GET /pepe crea request crea response emit('request',request,response) console.log(req.url) /pepe response.setHeader("Content-Type", "text/html"); response.write("<p>Hola</p>"); response.end(); Hola
  • 38. Clase Server Representa un servidor Web Es un EventEmitter Eventos: 'request', 'connect', 'close',... Métodos server.listen(Puerto,...):comienza a aceptar conexiones en Puerto
  • 39. IncomingMessage Son creados por http.server Primer argumento de evento 'request' Implementa interfaz Readable Stream Eventos: 'data' , 'end',... Métodos: httpVersion headers: Objeto Json con cabeceras method: puede ser GET, PUT, POST, DELETE,... url: string con la URL solicitada
  • 40. IncomingMessage Ejemplo, obtener datos POST const http = require('http'); const qs = require('querystring') http.createServer(procesa).listen(3000); function procesa(req,resp) { parseBody(req,resp,saluda); } function saluda(post,req,resp) { resp.end("nombre " + post.nombre + ", edad= " + post.edad); } function parseBody(req, resp, next) { let body = ''; req.on('data', data => { body += data; if (body.length > 1e6) { console.log("Body too big!"); req.connection.destroy(); } }); req.on('end', () => { var post = qs.parse(body); next(post,req,resp); }); } Probar con: curl -X POST -d "nombre=pepe&edad=34" http://127.0.0.1:3000
  • 41. ServerResponse Objeto creado por http.Server Segundo argumento de evento 'request' Implementa interfaz Writable Stream Métodos: writeHead(status, headers): envía cabecera de respuesta statusCode: controla el código de estado setHeader/removeHeader: añade/borra entradas en cabecera write: Envía una porción de datos end: Indica que ya no se va a enviar más datos
  • 42. ServerResponse Ejemplo: Devolver contenido HTML function procesa(req,resp) { fs.readFile('form.html','utf8',function (err,datos) { resp.writeHead(200,'{content-type: text/html}'); resp.end(datos); }); }
  • 43. Procesar formularios WWW GET http://ejemplo.com/form.html Usuario Servidor POST http://ejemplo.com/procesa cliente = pepe correo = pepe@kiko.com form.html resultado <h1>Hola Pepe</h1> <p>Email: pepe@kiko.com</p> const server = http.createServer(function (req,res){ switch (req.method) { case 'POST': ... break; case 'GET': ...break; default: ...
  • 44. Procesar formularios https://goo.gl/Kb2KCi const http = require('http'), fs = require('fs'), url = require('url'), qs = require('querystring'); const server = http.createServer((req, res) => { switch (req.method) { case 'POST': var body = ''; req.on('data', data => { body += data; if (body.length > 1e6) req.connection.destroy(); }); req.on('end', () => { var POST = qs.parse(body); res.end("Hola " + POST.cliente + "! Tu email es:" + POST.correo); }); break; case 'GET': if (url.parse(req.url, true).pathname == '/') { fs.readFile('form.html','utf8',function (err,datos) { res.writeHead(200,'{content-type: text/html}'); res.end(datos); }); } break; default: console.log("Método no soportado" + req.method); } }).listen(3000);
  • 45. Ejemplo API REST con NodeJs function procesa(req,resp) { switch (req.method) { case 'GET': ... // leer un valor break; case 'DELETE': ... // borrar un valor break; case 'POST': ... // crear un valor break; case 'PUT': ... // actualizar un valor break; }; } Ejemplo completo: http://goo.gl/8Bw1UR Ejemplos de uso con curl Lista de alumnos: curl localhost:3000 Ver alumno: curl localhost:3000?id=1 Insertar alumno: curl -X POST -d "nombre=luis&edad=45" http://127.0.0.1:3000 Actualizar alumno: curl -X PUT -d "nombre=Jose&edad=26" http://127.0.0.1:3000?id=0 Borrar alumno: curl -X DELETE localhost:3000?id=1
  • 46. Subiendo ficheros (paquete formidable) const formidable = require('formidable'), fs = require('fs'), http = require('http') http.createServer((req, resp) => { switch (req.method) { case 'GET': pideFichero(req,resp); break; case 'POST': procesaFichero(req,resp); break; }}).listen(3000); function procesaFichero(req,resp) { let form = new formidable.IncomingForm(); form.parse(req, function(err, fields, files) { resp.writeHead(200, {'content-type': 'application/json'}); fs.readFile(files.fichero.path,'utf8', (err,datos) => { if (err) throw err; let json = JSON.parse(datos) resp.end(JSON.stringify(json)); })}); return; } function pideFichero(req,resp) { resp.writeHead(200, {'content-type': 'text/html'}); resp.end('<h1>Cargar fichero JSON</h1>' + '<form action="/" enctype="multipart/form-data" method="post">'+ '<input type="file" name="fichero"><br>'+ '<input type="submit" value="Enviar">'+ '</form>' ); } https://goo.gl/vADe6W
  • 47. Otras variables globales console Métodos: log, debug, info, warn, error,... __filename: nombre de fichero que se ejecuta __dirname: directorio desde donde se ejecuta
  • 48. Negociación de contenido Negotiator: módulo para negociación de contenido var Negotiator = require('negotiator'); var tiposDisponibles = ['text/html', 'application/xml']; function showAlumnos(req,resp) { var negotiator = new Negotiator(req); var mediaType = negotiator.mediaType(tiposDisponibles); switch (mediaType) { case 'application/xml': resp.setHeader('content-type',mediaType); resp.end(alumnos.toXML()); break; case 'text/html': resp.setHeader('content-type', mediaType); resp.end(alumnos.toHTML()); } } Ejemplo completo: http://goo.gl/tWBAIZ
  • 49. Express Framework Web sobre Node Modelo MVC Facilita creación de aplicaciones Web var express = require('express'); var app = express(); var port = 3000; app.get('/usuario/:nombre', function(req, res){ console.log(req.route); res.send('Hola ' + req.params.nombre + "!"); }); app.listen(port); console.log("Servidor arrancado en puerto " + port);
  • 50. Express Negociación de contenido mediante Accept const express = require('express'); const app = express(); const users = require('./users'); app.get('/users', function (req,res) { res.format({ 'text/html' : users.html, 'text/plain': users.text, 'application/json': users.json, 'application/xml': users.xml }); }); app.listen(3000); console.log('Servidor arrancado'); let users = [{ name: 'Juan' }, ... ]; exports.text = function(req, res){ res.send(users.map(function(user){ return ' - ' + user.name + 'n'; }).join('')); }; exports.json = function(req, res){ res.json(users); }; exports.html = function(req, res){ ... }; exports.xml = function(req, res){ ... };
  • 51. Express Express es un framework completo MVC Otras características Generación automática de aplicaciones Plantillas HTML Otros frameworks Koa, Flatiron, total.js, restify,...
  • 52. Probando servicios web Se puede combinar mocha con supertest const request = require('supertest'); const express = require('express'); const app = require('../apiUsers'); describe('GET /user', function() { it('devuelve json', function(done) { request(app) .get('/users') .set('Accept', 'application/json') .expect('Content-Type', /application/json/) .expect(200, done); }); }
  • 53. Acceso a bases de datos Módulos Mongoose (MongoDB) Módulo mysql (MySQL)
  • 54. Ejemplos Ejemplos utilizados en Node https://github.com/labra/EjemploNode Ejemplo con Node y MongoDB https://github.com/labra/EjemploNode_Mongo Ejemplo con Node y MySQL https://github.com/labra/EjemploNode_MySQL
  • 55. XML con NodeJs Múltiples librerías. Ejemplo: libxmljs, libxslt Enlaces a librería libxml NOTA: Instalación en Windows requiere: node_gyp Ver: https://github.com/TooTallNate/node-gyp/
  • 56. XPath con NodeJs Leer fichero XML y acceder a elementos con XPath const fs = require('fs'); const libxmljs = require('libxmljs') let input = process.argv[2], xpath = process.argv[3]; fs.readFile(input, function (err, contents) { if (err) throw "Cannot open " + input + "n" + err; var xml = libxmljs.parseXmlString(contents); var result = xml.get(xpath); console.log("Resultado: " + result); });
  • 57. Manipular XML con NodeJs Leer fichero XML, añadir hijo y guardarlo const fs = require('fs'); const libxmljs = require('libxmljs') let file = process.argv[2]; fs.readFile(file, function (err, contents) { if (err) throw "Cannot open " + file + "n" + err; var xml = libxmljs.parseXmlString(contents); var newChild = libxmljs.Element(xml, 'new-child'); xml.root().addChild(newChild); fs.writeFile(file, xml.toString(), function (err) { console.log("Updated file " + file); }); });
  • 58. XML Schema con NodeJs Validar mediante XML Schema const fs = require('fs'); const libxmljs = require('libxmljs') let xmlFile = process.argv[2], xsdFile = process.argv[3]; fs.readFile(xmlFile, function (err, dataxml) { if (err) throw "Cannot open " + xmlFile + "n" + err; fs.readFile(xsdFile, function (err, dataxsd) { if (err) throw "Cannot open " + xsdFile + "n" + err; let xml = libxmljs.parseXml(dataxml); let xsd = libxmljs.parseXml(dataxsd); if (xml.validate(xsd)) { console.log("Es válido"); } else { console.log("No válidon" + xml.validationErrors); } }); });
  • 59. XSLT con NodeJs Transformar con XSLT const libxslt = require('libxslt'); let xmlFile = process.argv[2]; let xslFile = process.argv[3]; libxslt.parseFile(xslFile, function (err, xsl) { if (err) throw "Cannot open " + xslFile + "n" + err; xsl.applyToFile(xmlFile,function (err,result) { if (err) throw "Cannot apply to file " + xmlFile + "n" + err; console.log(result); }); });