Building an AngularJS + Python web app
Note: This is a blog post about my past experience with AngularJS 1 and the first in a series about Angular. If you want to get started, I strongly recommend getting directly into Angular 5+ and start your project with the Angular CLI.
Over the last two years, I worked on about five bigger projects with AngularJS and it's successor, Angular, Google's awesome frontend framework. It allows you to build some nice frontends and to really build separated, reusable parts, which is one on the main reasons I grew so fond of it.
Looking back, building that application was a big step for me in which I learned so much, as it involved not only building separated components - tackling specific problems is always easier than having the freedom to do just anything - but also to have a bigger picture, bringing those components together, learn about and add missing parts, until everything is working together nicely.
So starting with an idea I wrote some frontend code, built the backend to provide some data, set up a server and database, organized a domain and DNS entries, set up HTTPS, learned about securing a web app and JWT, sending automated Emails and using RESTful services. I'd like to share some of the things I learned and also some technical details in the following write-up.
Back to 2016
As a preparation (or more because AngularJS was something new and shiny for me and I wanted to try it, really) I wanted to build something reasonably small but still build the whole stack.
Coincidentally, I also took a spanish course, trying to learn spanish, and was looking for a way to exercise the given vocabulary. So I came up with vocabulario-espanol.ch:
Have a look, but don't expect too much, it was one of my first projects in AngularJS, but it helped me a lot in getting a better understanding in lots of things.
Technology stack
This was my technology stack, on which I'd like to elaborate more below.
Simple web server
To start a super simple python web server (you want to get started fast, right?), just run the following script, and it will serve all content from the directory "static":
Just browse http://127.0.0.1:5000/index.html and your app should pop open. It's based on Flask, and I really love how quick you can get started developing web stuff, for example AngularJS or ProcessingJS (like Pushr I made some months ago).
AngularJS components
The most important AngularJS components include:
- Controllers
- Filters
- Directives
- Services
For a quick start, check out the following page, which has an example of each:
The AngularJS docs are really a good point to start (with lots of examples) and also a good reference.
REST: learn more about HTTP
For building a modern web app, a good idea is to have a server which serves some defined URI endpoints as a REST API. For this it's a good idea to refresh your memory on some basic HTTP issues:
- HTTP methods - learn how to use GET, POST, PUT, DELETE and map them to CRUD actions onto a database (see also RFC 7231). Also, learn the difference between PUT and POST (idempotence)
- Using HTTP status codes - at least the basic ones mentioned (like 200, 201, 204, 302, 400, 401, 403, 404, 409, 500), depending on the project and scope.
- Resource URIs: Model your endpoints acccording to your data, e.g.
- collection:
GET /users
- retrieve all users - single item:
GET /customers/5
- retrieve customer with id 5
- collection:
Routing
For Routing, Angular has some good libraries, for example ngRoute or UI-Router. You can specify certain application states and assign templates and controllers to them:
JSFiddle
When facing some weird or inexplicable error, it's usually a good idea to test certain behaviour as isolated as possible to narrow it down. I started using JSFiddle extensively for quick examples, in AngularJS but also for plain Javascript or even styling issues in CSS.
Some examples:
- Basic AngularJS example
- angular.forEach
- || operator
- Comparing null, undefined, {}, []
- Sorting with null
- Custom CHF filter
- Filter on certain attributes
- Correct number sorting in combined text/number lists
- Filter with empty string or null
Testing with Karma & Jasmine
A major issue enforced by the AngularJS-Team is testability - every component is testable, and writing tests itself is easy and fun (once you managed to install and configure Karma). For example, let's test some components above:
See Jasmine's introduction.js for a good and comprehensive guide to testing possibilities, matchers, etc.
Security & Authentication
Currently, users are able to log in and save their progress (if they want):
For that I needed users to be able to login with a password. I'm really not a security expert but I can only recommend reading why salting is important and why you should not write your own crypto, which handle some important aspects of security.
I went with pbkdf2, since it is already available (through werkzeug, which is part of Flask):
from werkzeug.security import generate_password_hash, check_password_hash
# on registration, generate hash to save in database
pwhash = generate_password_hash(password)
# on login, check hash
if check_password_hash(pwhash, password_attempt):
token = create_token(...)
If a user logs in and the password is verified using the above method, we create a token using JSON web tokens (JWT) to grant access.
For the AngularJS part, I just send the token with the two or three requests which require authentification (you could use a $httpInterceptor
to send the received token with every server call made):
fetchWords: function () {
return $http.get(API + "words/", {headers:
{'Authorization': 'Token ' + UserService.getToken()}})
.success(function (data) {
words = data;
});
}
}
Persistence
For my website, I use SQLite, a lightweight database which serves from a simple file. I can really recommend it for low traffic/write access, but you should check their when to use page for detailed explanations if it souits your project.
Domain, SSL
Apart from a domain and some DNS (an A record
to the correct IP) on Amazon Route53 I obtained a free SSL certificate by Let's encrypt, a project by the Internet Security Research Group (ISRG). There's a neat step-by-step tutorial on Digital Ocean on how to secure Nginx with Let's encrypt.
A neat tool for checking on your certificate (wether it uses strong ciphers and some common vulnerabilities on your server) is ssllabs.com, you can check your own site if everything is set up correctly.
Getting ready for production
Phew! After quite some issues we have a working Flask app, including user management and SSL set up. As said, the quick web server above is just for development, it does not scale well and isn't secure at all. For running in production mode I use Gunicorn with nginx to handle routing, multiple workers and requests, SSL, etc. Also, the static files are served directly from a separate directory, and only the REST-calls are redirected to the Flask-app.
Configuring Nginx takes some time. A good general tutorial is this blog post from realpython.com, in short it works like this:
After configuring nginx and having a working setup, a good read on securing your server is strong SSL security on Nginx.
Thanks for reading!