Desarrollo web para no iniciados – Parte 5 El modelo cliente/servidor (node.js)

Ya casi hemos terminado esta iniciación al desarrollo web. Hemos visto, de forma muy escueta, HTML, CSS y Javascript, todo esto se ejecuta en el cliente. Si nuestro buscaminas estuviese en un servidor de internet, para acceder a el necesitamos un software en una máquina que sea accesible, y que sea capaz de entregarnos la información. Esta parte pretende ser una introducción a como funcionan estos programas, para ello usaremos node.js, con lo que podremos usar nuestros conocimientos sobre javascript.

Node.js es un framework de desarrollo web software servidor, que usa el mismo motor de javascript que google chrome, V8, para permitirnos hacer aplicaciones web usando el mismo lenguaje que usamos en nuestras páginas web. Antes de meternos en faena, comentaros que usar esta herramienta se debe a dos factores:
1. No requerir conocimientos no vistos hasta ahora para poder explicar la parte final de nuestro recorrido por el desarrollo web.
2. Existen muchas herramientas que se han usado, se usan, y se usaran, para el desarrollo web, node.js es una que podemos considerar, de bajo nivel, y tiene unos usos muy interesantes en el desarrollo moderno de la web. Pero no es la mejor herramienta para todo. Para nuestros primero desarrollos nos interesará aprender algo como php o ruby on rails, que simplifican de muchas formas hacer páginas “vivas”. Pero nosotros vamos a usar node.js por que nos permitirá, analizar mejor como van los datos de un lado a otro.

Necesitaremos tener node.js en nuestro ordenador:

Windows, desde la página de node.js en downloads descargamos el instalador, tras instalarlo podremos acceder a node desde nuestra consola: Inicio -> Buscar “cmd.exe”. Una vez en esta podemos probar que funciona:

Microsoft Windows [Versión 6.1.7600]
Copyright (c) 2009 Microsoft Corporation. Reservados todos los derechos.

C:\Users\cartucho>node
> console.log("Hello, World!")
Hello, World!
undefined
>
(^C again to quit)
>
C:\Users\cartucho>

MacOSX, descargamos el instalador y tras instalarlo podremos acceder desde el Terminal, Aplicaciones / Utilidades / Terminal, y comprobar que funciona:

Last login Thu Mar  1 18:09:48 on ttys000
macair:~ cartucho$ node
> console.log("Hello, world!")
Hello, world!
undefined
>
(^C again to quit)
> macair:~ cartucho$

Linux, podéis descargar el código fuente o probar una de estas soluciones.

Bueno tenemos node.js listo para ayudarnos a aprender como funcionan las aplicaciones web.

Cuando vimos html, nombramos las urls, vamos a ver como con ellas podemos movernos por el mundo.
Partamos de una url como:


http://example.com/index.html

Ya vimos que esta url se componía de tres partes:
protocolo: http
host: example.com
path: /index.html

example.com, el host, o nombre de la máquina, es el nombre que usamos los humanos para hacernos fácil recordarlas, pero internamente se usa un número de 32bits que normalmente se representa como bloques de un byte separados por puntos, son las ip.

127.0.0.1 // ip de la propia máquina, también conocida como localhost
192.168.0.1
173.194.34.192 // una ip de google.com

En internet existen servidores que ayudan a conocer que ips tienen los distintos nombres que usamos, google.com, facebook.com, msn.es, etc… Se llaman servidores DNS, y el navegador los usa para saber a que ip tiene que conectarse.

Entonces el navegador para conectarse a una web, primero coje el nombre del host, y se conecta a un servidor DNS y le pregunta por ese dominio, y simplificando, este le indica la ip. Después el navegador se conecta a esta ip, y empieza el protocolo http. Cuando hablamos de protocolos, normalmente nos referimos al idioma que tienen que saber los programas para hablarse, en nuestro caso nuestra solicitud seria:

GET /index.html HTTP/1.1
Host: example.com
User-Agent: Mozilla ...
[Línea en blanco]

Usamos el verbo http, GET, que se usa para pedir un recurso de un servidor web en nuestro caso, el archivo que estamos pidiendo, /index.html, seguido de la versión de protocolo a usar, en nuestro caso HTTP/1.1. Después se indican las cabeceras, que entre muchas opciones tenemos el nombre del host, porque tras una ip podemos tener varios dominios y el User-Agent, que es una cadena que suelen mandar los navegadores para identificarse.

A lo que el servidor nos responderá con unas cabeceras seguidas de un archivo html

HTTP/1.1 200 OK
Date: Fri, 31 Dec 2003 23:59:59 GMT
Content-Type: text/html
Content-Length: 1221

<html>
<body>
... (Contenido) ...
</body>
</html>

La primera linea indica el código de respuesta de la solicitud, 200 significa que todo fue bien, al igual que 404 indica que no se encontró lo que se pidió.

Las cabeceras de respuesta contienen información sobre el tipo de recurso recuperado, Content-Type: text/html o su longitud en bytes, Content-Length: 1221.

Vamos a verlo funcionando, creamos un archivo mi-primer-script-node.js con:

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

Usamos el objeto http, importado desde el API de node.js, para crear un servidor web que atiende peticiones locales, 127.0.0.1, en el puerto 1337. Por defecto http usa el puerto 80 para comunicarse. Los puertos sirven para que una máquina con una ip pueda responder a más de un servicio, podemos, por ejemplo tener un servidor web en el puerto 80 y otro el en puerto 8080 con otra aplicación. Nosotros usamos el 1337, como podríamos usar otro como el 80, el problema con esto, es que dependiendo del sistema en el que estemos, sólo el usuario administrador, root, etc… puede iniciar servicios en puertos inferiores a 1024, por cuestiones de seguridad.

Una vez que nuestro servidor esta creado y escuchando, atendera las peticiones usando la funcion suministrada:

function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}

Cuando llega una solicitud esta dispara la ejecución de la función, pasandole dos objetos, la solicitud, req, y la respuesta que generemos, res. Nosotros nos limitamos a escribir una respuesta correcta, 200, de tipo texto plano, no html y la cadena de texto “Hello, World”.

Ejecutándolo desde la consola con

$ node mi-primer-script-node.js
Server running at http://127.0.0.1:1337/

Podremos ir a nuestro navegador y si tenemos la consola activada en Network podremos ver mas en detalle la llamada desde el punto de vista del navegador.

También podemos ver una radiografía de la información picando el la solicitud.

Veamos un ejemplo en el que mostramos parte de esta información

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.write(req.method+" "+req.url+" from "+req.headers.host+"\n");
  res.write("User-Agent: "+req.headers["user-agent"]+"\n")
  res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

Podemos apagar nuestro servidor pulsando ctrl+C dos veces.
Si probamos este ejemplo en el navegador y comprobamos como cualquier ruta que le pasemos la podemos gestionar desde nuestra funcion:

La carga de html, css y javascript se hace con estas mismas llamadas http, podemos ver nuestras webs como muchas de estas llamadas. Hacer todo esto con node.js sería un poco exagerado, ya que existen servidores web como apache, que nos hacen la tarea de servir nuestros archivos de una forma cómoda y normalizada. Ademas permiten usar lenguajes como php o lua, para que nuestros archivos no sean meramente estáticos. Pero esto queda fuera de los objetivos que perseguíamos cuando empezamos este curso, intentar enseñar los principios del desarrollo web, para gente no versada en el arte de la programación.
Espero que disfrutéis creando la web del mañana ;)

Happy coding!