I’ve been hearing lots of good things about React (a JavaScript library to build User Interfaces) and recently came across the several tutorials that have a backend implementation in:
I felt that there was one missing in particular and that of course is:
For those not familiar with circuits it is:
- A Python Application Framework
- Supports a loosely coupled architecture
- Is fully event-driven (i.e: react!)
- Supports Asynchronous I/O
- Supports Coroutines
- and more more...
Here is the same implementation of the above backends using circuits:
from os import environ
from json import dumps, loads
from circuits.web import Server, Controller, Static
class Comments(Controller):
channel = "/comments.json"
def index(self, **data):
with open("comments.json", "r") as f:
comments = loads(f.read())
if self.request.method == "POST":
comments.append({"author": data["author"], "text": data["text"]})
with open("comments.json", "w") as f:
f.write(dumps(comments))
self.response.headers["Content-Type"] = "application/json"
self.response.headers["Cache-Control"] = "no-cache"
return dumps(comments)
(Server(("0.0.0.0", int(environ.get("PORT", 3000)))) + Comments() + Static(docroot="public")).run()Now whilst this may seem very similar to the Python+Flask example using circuits has several advantages:
- We can easily add new functionality by “composing” and “registering” more Component(s)
Let’s say we want to password protect our resource without modifying the existing code?
Easy:
Write a Auth Component:
from hashlib import md5
from circuits import handler, Component
from circuits.web.tools import check_auth, basic_auth
class Auth(Component):
channel = "web"
realm = "Comments"
users = {"admin": md5("admin").hexdigest()}
@handler("request", priority=1.0)
def on_request(self, event, request, response):
if request.path != "/comments.json":
return
if not check_auth(request, response, self.realm, self.users):
event.stop()
return basic_auth(request, response, self.realm, self.users)And add this newly created component into the mix:
(Server(("0.0.0.0", int(environ.get("PORT", 3000)))) + Auth() + Comments() + Static(docroot="public")).run()Enjoy! And happy hacking! :)