() translation by (you can also view the original English article)
En la parte anterior de esta serie, vimos cómo comenzar con Eve, un framework API REST de Python, y cómo crear algunas API. En esta parte de la serie, usaremos esas API para crear una aplicación impulsada por Node.js y AngularJS.
Implementaremos la funcionalidad de registro usando Node.js y agregaremos otras funcionalidades llamando a las API REST desde AngularJS.
Empecemos
Para comenzar, clona el código fuente del tutorial anterior y ejecuta las API.
1 |
git clone https://github.com/jay3dec/REST_API_EVE_Part-1 |
Una vez que hayas clonado el código fuente, asegúrate de tener MongoDB en ejecución. Navega hasta el directorio REST_API_EVE_Part-1
y ejecuta la aplicación:
1 |
cd REST_API_EVE_Part-1
|
2 |
python app.py |
Ahora, deberías tener tu API ejecutándose en http://localhost:5000/.
Creando la aplicación NodeJS
Paso 1: Creando una aplicación básica
Crea una carpeta de proyecto llamada AngularNodeApp
. Usaremos Express, un framework de aplicación web minimalista para crear aplicaciones Node.js. Por lo tanto, vamos a instalar express
en nuestro proyecto.
1 |
npm install express
|
Una vez que se haya instalado express
, crea un archivo llamado app.js
. Dentro de app.js
crearemos nuestra aplicación de express y definiremos las rutas para la aplicación.
Comencemos por importar express dentro de app.js
y crear una aplicación express.
1 |
var express = require('express'), |
2 |
app = express(); |
3 |
|
4 |
app.get('/',function(req,res){ |
5 |
res.send('welcome !!'); |
6 |
});
|
7 |
|
8 |
app.listen(3000) |
Acabamos de crear una aplicación express y definimos una ruta, /
, que retornará welcome
cuando se solicite. Ahora inicia el servidor.
1 |
node app.js |
Apunta tu navegador a http://localhost:3000/ y deberías tener el mensaje welcome !!
.
Creemos una página de inicio para nuestra aplicación. Navega a la carpeta del proyecto y crea un nuevo directorio llamado public
. Dentro de public/index
, crea un archivo llamado index.html
. Agrega el siguiente código HTML a index.html
.
1 |
<!DOCTYPE html>
|
2 |
<html lang="en"> |
3 |
|
4 |
<head>
|
5 |
<title>Angular Node App</title> |
6 |
|
7 |
|
8 |
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"> |
9 |
|
10 |
<link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet"> |
11 |
|
12 |
|
13 |
</head>
|
14 |
|
15 |
<body>
|
16 |
|
17 |
<div class="container"> |
18 |
<div class="header"> |
19 |
<nav>
|
20 |
<ul class="nav nav-pills pull-right"> |
21 |
<li role="presentation" class="active"><a href="#">Home</a> |
22 |
</li>
|
23 |
<li role="presentation"><a href="/signIn">Sign In</a> |
24 |
</li>
|
25 |
<li role="presentation"><a href="/signUp">Sign Up</a> |
26 |
</li>
|
27 |
</ul>
|
28 |
</nav>
|
29 |
<h3 class="text-muted">Angular Node App</h3> |
30 |
</div>
|
31 |
|
32 |
<div class="jumbotron"> |
33 |
<h1>Angular Node App</h1> |
34 |
<p class="lead"></p> |
35 |
<p><a class="btn btn-lg btn-success" href="/signUp" role="button">Sign up today</a> |
36 |
</p>
|
37 |
</div>
|
38 |
|
39 |
|
40 |
|
41 |
<footer class="footer"> |
42 |
<p>© Company 2015</p> |
43 |
</footer>
|
44 |
|
45 |
</div>
|
46 |
</body>
|
47 |
|
48 |
</html>
|
A continuación, modifiquemos el controlador de solicitudes /
existente para mostrar index.html
. Define la ruta a la carpeta public
en app.js
.
1 |
app.use(express.static(__dirname + '/public')); |
Modifica el controlador de solicitudes por /
como se muestra a continuación:
1 |
app.get('/',function(req,res){ |
2 |
res.sendFile('index.html',{'root': __dirname + '/public/index'}); |
3 |
});
|
Guarda los cambios y reinicia el servidor. Apunta tu navegador a http://localhost:3000/ y deberías poder ver la página de la aplicación.



Ahora, crea una página llamada signin/signin.html
y agrega el siguiente código HTML:
1 |
<!DOCTYPE html>
|
2 |
<html lang="en"> |
3 |
|
4 |
<head>
|
5 |
<title>Python Flask Bucket List App</title> |
6 |
|
7 |
|
8 |
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"> |
9 |
|
10 |
<link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet"> |
11 |
<link href="signup.css" rel="stylesheet"> |
12 |
|
13 |
|
14 |
</head>
|
15 |
|
16 |
<body>
|
17 |
|
18 |
<div class="container"> |
19 |
<div class="header"> |
20 |
<nav>
|
21 |
<ul class="nav nav-pills pull-right"> |
22 |
<li role="presentation"><a href="/">Home</a> |
23 |
</li>
|
24 |
<li role="presentation" class="active"><a href="#">Sign In</a> |
25 |
</li>
|
26 |
<li role="presentation"><a href="/signUp">Sign Up</a> |
27 |
</li>
|
28 |
</ul>
|
29 |
</nav>
|
30 |
<h3 class="text-muted">Python Flask App</h3> |
31 |
</div>
|
32 |
|
33 |
<div class="jumbotron"> |
34 |
<h1>Bucket List App</h1> |
35 |
<form class="form-signin"> |
36 |
<label for="inputEmail" class="sr-only">Email address</label> |
37 |
<input type="email" name="inputEmail" id="inputEmail" class="form-control" placeholder="Email address" required autofocus> |
38 |
<label for="inputPassword" class="sr-only">Password</label> |
39 |
<input type="password" name="inputPassword" id="inputPassword" class="form-control" placeholder="Password" required> |
40 |
|
41 |
<button id="btnSignIn" class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button> |
42 |
</form>
|
43 |
</div>
|
44 |
|
45 |
|
46 |
|
47 |
<footer class="footer"> |
48 |
<p>© Company 2015</p> |
49 |
</footer>
|
50 |
|
51 |
</div>
|
52 |
</body>
|
53 |
|
54 |
</html>
|
En app.js
, agrega un controlador de solicitudes llamado /SignIn
que mostrará la página signin.html
.
1 |
app.get('/signIn', function(req, res) { |
2 |
res.sendFile('signin.html', { |
3 |
'root': __dirname + '/public/signin' |
4 |
});
|
5 |
});
|
De manera similar, agrega signup.html
a la carpeta public/signup
con el siguiente código HTML:
1 |
<!DOCTYPE html>
|
2 |
<html lang="en"> |
3 |
|
4 |
<head>
|
5 |
<title>Python Flask Bucket List App</title> |
6 |
|
7 |
|
8 |
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"> |
9 |
|
10 |
<link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet"> |
11 |
<link href="signup.css" rel="stylesheet"> |
12 |
|
13 |
|
14 |
</head>
|
15 |
|
16 |
<body>
|
17 |
|
18 |
<div class="container"> |
19 |
<div class="header"> |
20 |
<nav>
|
21 |
<ul class="nav nav-pills pull-right"> |
22 |
<li role="presentation"><a href="/">Home</a> |
23 |
</li>
|
24 |
<li role="presentation"><a href="/signIn">Sign In</a> |
25 |
</li>
|
26 |
<li role="presentation" class="active"><a href="#">Sign Up</a> |
27 |
</li>
|
28 |
</ul>
|
29 |
</nav>
|
30 |
<h3 class="text-muted">Python Flask App</h3> |
31 |
</div>
|
32 |
|
33 |
<div class="jumbotron"> |
34 |
<h1>Bucket List App</h1> |
35 |
<form class="form-signin" action="/register" method="post"> |
36 |
<label for="inputFirstName" class="sr-only">First Name</label> |
37 |
<input type="name" name="inputFirstName" id="inputFirstName" class="form-control" placeholder="First Name" required autofocus> |
38 |
<label for="inputLastName" class="sr-only">Last Name</label> |
39 |
<input type="name" name="inputLastName" id="inputLastName" class="form-control" placeholder="Last Name" required autofocus> |
40 |
<label for="inputUsername" class="sr-only">Username</label> |
41 |
<input type="name" name="inputUsername" id="inputUsername" class="form-control" placeholder="Username" required autofocus> |
42 |
<label for="inputPassword" class="sr-only">Password</label> |
43 |
<input type="password" name="inputPassword" id="inputPassword" class="form-control" placeholder="Password" required> |
44 |
<label for="inputPhone" class="sr-only">Password</label> |
45 |
<input type="number" name="inputPhone" id="inputPhone" class="form-control" placeholder="Phone" required> |
46 |
|
47 |
<button id="btnSignUp" class="btn btn-lg btn-primary btn-block" type="submit">Sign up</button> |
48 |
</form>
|
49 |
</div>
|
50 |
|
51 |
|
52 |
|
53 |
<footer class="footer"> |
54 |
<p>© Company 2015</p> |
55 |
</footer>
|
56 |
|
57 |
</div>
|
58 |
</body>
|
59 |
|
60 |
</html>
|
Agrega un controlador de solicitudes llamado signUp
en app.js
.
1 |
app.get('/signUp', function(req, res) { |
2 |
res.sendFile('signup.html', { |
3 |
'root': __dirname + '/public/signup' |
4 |
});
|
5 |
});
|
Guarda los cambios y reinicia el servidor. Apunta tu navegador a http://localhost:3000 y deberías tener la aplicación ejecutándose. Haz clic en los enlaces de inicio de sesión y registro en la página, y se deben mostrar las páginas respectivas.
Paso 2: Implementando la funcionalidad del registro
Para implementar la funcionalidad de registro, llamaremos a la API REST de Python Eve. Llamaremos a esta API desde el back-end de Node.js
, ya que requiere pasar el nombre de usuario y la contraseña de autenticación del servicio. Entonces, para evitar exponer el nombre de usuario de autenticación y la contraseña de los scripts, haremos esta llamada desde Node.js
.
Primero creemos un controlador register
para la solicitud de tipo POST y así manejar la funcionalidad de registro.
1 |
app.post('/register', function(req, resp) { |
2 |
// Code will be here
|
3 |
});
|
Necesitaremos body-parser
para analizar los datos enviados desde el formulario. Instala body-parser
usando el administrador de paquetes NPM.
1 |
npm install body-parser
|
Una vez que se haya instalado body-parser
, solicítalo dentro de app.js
.
1 |
bodyParser = require('body-parser') |
Para usar body-parser
para analizar los datos enviados desde el formulario, debemos usarlo en nuestra aplicación.
1 |
app.use(bodyParser.urlencoded({ |
2 |
extended: true |
3 |
}));
|
Dentro del controlador /register
podemos analizar los datos del formulario como se muestra a continuación:
1 |
var _firstName = req.body.inputFirstName; |
2 |
var _lastName = req.body.inputLastName; |
3 |
var _username = req.body.inputUsername; |
4 |
var _password = req.body.inputPassword; |
5 |
var _phone = req.body.inputPhone; |
Usaremos request
para realizar la llamada a las API de Eve. Así que instala request en la aplicación.
1 |
npm install request
|
Requerir request
en app.py
.
1 |
request = require('request') |
Crea las opciones para llamar a la API como se muestra a continuación:
1 |
var options = { |
2 |
url: 'http://127.0.0.1:5000/user/', |
3 |
method: 'POST', |
4 |
auth: { |
5 |
user: 'admin', |
6 |
password: 'admin' |
7 |
},
|
8 |
formData: { |
9 |
firstname: _firstName, |
10 |
lastname: _lastName, |
11 |
username: _username, |
12 |
password: _password, |
13 |
phone: _phone |
14 |
}
|
15 |
}
|
Hemos especificado los detalles de la solicitud POST
en las opciones. admin_username
y admin_password
son el nombre de usuario de autenticación y la contraseña necesarios para acceder a la API en la creación de usuarios de Eve.
A continuación, vamos a usar request
para realizar la llamada.
1 |
request(options, function(err, res, body) { |
2 |
if (err) { |
3 |
console.log(err); |
4 |
return; |
5 |
}
|
6 |
console.log('Response: ', res) |
7 |
console.log('Returned data: ', body) |
8 |
})
|
Guarda los cambios y reinicia el servidor. Apunta tu navegador a http://localhost:3000 y navega hasta la pantalla de registro. Ingresa los detalles y haz clic en el botón de registro. Consulta la ventana de la terminal para ver la respuesta y los detalles de creación del usuario devueltos por la llamada a la API.
Paso 3: Manejando errores en el registro
Cuando ocurre un error durante el proceso de registro, pasaremos el mensaje de error a la página de registro. Usaremos un motor de plantillas llamado EJS. Primero, instalemos EJS.
1 |
npm install ejs |
Una vez que hayas terminado con la instalación de EJS
, agrega la siguiente línea de código para configurar la carpeta 'view' y el motor de vistas de plantilla.
1 |
var path = require('path'); |
2 |
app.set('views', path.join(__dirname + '/public/signup')); |
3 |
app.set('view engine', 'ejs'); |
Cambia el nombre de signup.html a signup.ejs
y agrega una etiqueta 'span' para mostrar un error después del botón Enviar.
1 |
<span style="color:red;"><%= error %></span> |
Además, modifica el controlador de solicitudes signUp
.
1 |
app.get('/signUp',function(req,res){ |
2 |
res.render('signup',{error:''}) |
3 |
});
|
Luego, si ocurre algún error en la respuesta de registro, lo pasaremos a la página de registro. Si el proceso de registro no arroja ningún error, redirigiremos al usuario a la página de inicio de sesión.
1 |
request(options, function(err, res, body) { |
2 |
if (err) { |
3 |
return resp.render('signup', { |
4 |
error: err |
5 |
})
|
6 |
}
|
7 |
var result = JSON.parse(body) |
8 |
if (result._status == 'ERR') { |
9 |
if (result._error.code == '400') { |
10 |
return resp.render('signup', { |
11 |
error: 'Username Already Exists!' |
12 |
})
|
13 |
}
|
14 |
return resp.render('signup', { |
15 |
error: result._issues.username |
16 |
})
|
17 |
} else { |
18 |
console.log('All good'); |
19 |
resp.redirect('/signIn'); |
20 |
}
|
21 |
})
|
Guarda todos los cambios y reinicia el servidor. Apunta tu navegador a http://localhost:3000/signUp e intenta registrarte usando un nombre de usuario existente. Dado que el nombre de usuario ya existe, deberías recibir un error.



Creando la aplicación AngularJS
Implementando la funcionalidad de inicio de sesión
AngularJS proporciona un servicio llamado $http que ayuda a realizar llamadas a la API REST. De los documentos de AngularJS,
El servicio$http
es un servicio central de Angular que facilita la comunicación con los servidores HTTP remotos a través del objeto XMLHttpRequest del navegador o mediante JSONP.
Copia el contenido del body del archivo index.html
y crea un nuevo archivo llamado public/home/home.html
.
1 |
<div class="container"> |
2 |
<div class="header"> |
3 |
<nav>
|
4 |
<ul class="nav nav-pills pull-right"> |
5 |
<li role="presentation" class="active"><a href="#">Home</a></li> |
6 |
<li role="presentation"><a href="#/signin">Sign In</a></li> |
7 |
<li role="presentation"><a href="/signUp">Sign Up</a></li> |
8 |
</ul>
|
9 |
</nav>
|
10 |
<h3 class="text-muted">Angular Node App</h3> |
11 |
</div>
|
12 |
|
13 |
<div class="jumbotron"> |
14 |
<h1>Angular Node App</h1> |
15 |
<p class="lead"></p> |
16 |
<p><a class="btn btn-lg btn-success" href="/signUp" role="button">Sign up today</a></p> |
17 |
</div>
|
18 |
|
19 |
|
20 |
|
21 |
<footer class="footer"> |
22 |
<p>© Company 2015</p> |
23 |
</footer>
|
24 |
|
25 |
</div>
|
En la carpeta 'home', crea un archivo llamado home.js
y define el módulo home
y la configuración de rutas como se muestra a continuación:
1 |
'use strict'; |
2 |
|
3 |
angular.module('home', ['ngRoute']) |
4 |
|
5 |
.config(['$routeProvider', function($routeProvider) { |
6 |
$routeProvider.when('/home', { |
7 |
templateUrl: '../home/home.html', |
8 |
controller: 'HomeCtrl' |
9 |
});
|
10 |
}])
|
11 |
|
12 |
.controller('HomeCtrl', [function() { |
13 |
|
14 |
}]);
|
De manera similar, reemplaza el código HTML de signin.html
con el contenido del body de signin.html
. Manejaremos el enrutamiento de la página de inicio de sesión a través de la aplicación AngularJS.
Dentro de la carpeta signin
, crea un archivo llamado signin.js
y agrega los siguientes detalles de configuración de ruta.
1 |
'use strict'; |
2 |
|
3 |
angular.module('signin', ['base64','ngRoute','myAppService']) |
4 |
|
5 |
.config(['$routeProvider', function($routeProvider) { |
6 |
$routeProvider.when('/signin', { |
7 |
templateUrl: '../signin/signin.html', |
8 |
controller: 'SignInCtrl' |
9 |
});
|
10 |
}])
|
11 |
En index.html
usaremos ngView
y direccionaremos las vistas de la aplicación AngularJS. Así es como se verá index.html
:
1 |
<!DOCTYPE html>
|
2 |
<html lang="en" ng-app="myApp"> |
3 |
<head>
|
4 |
<title>Angular Node App</title> |
5 |
|
6 |
|
7 |
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"> |
8 |
|
9 |
<link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet"> |
10 |
<script src="https://code.jquery.com/jquery-2.0.1.min.js"></script> |
11 |
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script> |
12 |
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.12/angular.js"></script> |
13 |
<script src="home/home.js"></script> |
14 |
<script src="signin/signin.js"></script> |
15 |
<script src="index/index.js"></script> |
16 |
|
17 |
</head>
|
18 |
|
19 |
<body>
|
20 |
|
21 |
<div ng-view></div> |
22 |
</body>
|
23 |
</html>
|
Dentro de la carpeta index
, crea un archivo llamado index.js
que servirá como archivo raíz. En index.js
inyectaremos los diferentes módulos creados en la aplicación myApp
. Aquí está el archivo index.js
:
1 |
angular.module('myApp', [ |
2 |
'ngRoute', |
3 |
'home', |
4 |
'signin' |
5 |
]).
|
6 |
config(['$routeProvider', function($routeProvider) { |
7 |
$routeProvider.otherwise({redirectTo: '/home'}); |
8 |
}]);
|
Instala angular-route
usando bower e incluye la referencia en index.html
.
1 |
bower install angular-route
|
1 |
<script src="../bower_components/angular-route/angular-route.js"></script> |
También necesitaremos convertir el nombre de usuario y la contraseña a base64
, así que instala angular-base64
.
1 |
bower install angular-base64 |
Una vez instalado, agrega una referencia a angular-base64
en index.html
.
1 |
<script src="../bower_components/angular-base64/angular-base64.js"></script> |
Establece la ruta estática a bower_components
en app.js
.
1 |
app.use('/bower_components', express.static(__dirname + '/bower_components')); |
Dentro de signin.js
, creemos un controlador llamado SignInCtrl
.
1 |
'use strict'; |
2 |
|
3 |
angular.module('signin', ['base64','ngRoute']) |
4 |
|
5 |
.config(['$routeProvider', function($routeProvider) { |
6 |
$routeProvider.when('/signin', { |
7 |
templateUrl: '../signin/signin.html', |
8 |
controller: 'SignInCtrl' |
9 |
});
|
10 |
}])
|
11 |
|
12 |
.controller('SignInCtrl',['$scope','$http','$base64',function($scope,$http,$base64){ |
13 |
}]);
|
Acabamos de crear un controlador llamado SignInCtrl
en signin.js
. Hemos inyectado el módulo base64
en SignInCtrl
.
Al hacer clic en el botón de inicio de sesión, llamaremos a la función signIn
anterior para autenticar al usuario. Entonces, primero agreguemos la directiva ngModel
al campo del nombre de usuario y la contraseña en la página de inicio de sesión.
1 |
<input type="text" name="inputUsername" id="inputUsername" ng-model="username" class="form-control" placeholder="Email address" autofocus> |
2 |
<input type="password" name="inputPassword" id="inputPassword" ng-model="password" class="form-control" placeholder="Password" > |
Agrega la directiva ngClick
al botón de iniciar sesión en signin.html
.
1 |
<button id="btnSignIn" class="btn btn-lg btn-primary btn-block" ng-click="signIn()">Sign in</button> |
Dentro de la función signIn
, lee el nombre de usuario y la contraseña de $scope
. Una vez que tengamos el nombre de usuario y la contraseña, crearemos la cadena base64
usando angular-base64
.
1 |
$scope.signIn = function() { |
2 |
|
3 |
var username = $scope.username; |
4 |
var password = $scope.password; |
5 |
|
6 |
var authdata = $base64.encode(username + ':' + password); |
7 |
}
|
Antes de realizar una llamada a las API REST, debemos configurar los encabezados necesarios. Necesitamos configurar Access-Control-Request-Headers
y Access-Control-Expose-Headers
.
1 |
$http.defaults.headers.common = {"Access-Control-Request-Headers": "accept, origin, authorization"}; |
2 |
|
3 |
$http.defaults.headers.common = {"Access-Control-Expose-Headers": "Origin, X-Requested-With, Content-Type, Accept"}; |
4 |
|
5 |
$http.defaults.headers.common["Cache-Control"] = "no-cache"; |
6 |
|
7 |
$http.defaults.headers.common.Pragma = "no-cache"; |
También necesitaremos establecer el encabezado Authorization
en $http
. Usando el authData
de base64
creado con username
y password
, configura el encabezado de autorización.
1 |
$http.defaults.headers.common['Authorization'] = 'Basic '+authdata; |
A continuación, realiza la llamada GET mediante $http
a las API REST de Python Eve.
1 |
$http({ |
2 |
method: 'GET', |
3 |
url: 'http://127.0.0.1:5000/user/' + username |
4 |
}).
|
5 |
success(function(data, status, headers, config) { |
6 |
console.log(data); |
7 |
}).
|
8 |
error(function(data, status, headers, config) { |
9 |
console.log(data, status); |
10 |
});
|
Guarda todos los cambios y reinicia el servidor. Apunta tu navegador a http://localhost:3000/signin. Intenta iniciar sesión con un nombre de usuario y una contraseña válidos. Verifica la consola del navegador y deberías tener los datos del usuario. Si la autenticación falla, deberías tener un error de autenticación.
Conclusión
En este tutorial, vimos cómo usar las API REST creadas en el tutorial anterior en nuestra aplicación AngularJS
y Node.js
. Implementamos la funcionalidad de inicio de sesión y registro en este tutorial.
En la siguiente parte de esta serie, usaremos las otras API para completar nuestra aplicación AngularJS.
El código fuente de este tutorial está disponible en GitHub.