Joopy is a web framework for python built on WSGI server.
Joopy is re-enginnered from a Java-based web framework called Jooby (2.9.1 version). The suffix "by" is replaced by "py" due to python.
Similarity, Joopy supports two ways to set routes:
- Script API
- MVC API
In the following examples, we set HTTP GET method for the URL "/" and return the string "hello world" to user.
from joopy.src.joopy import Joopy
class myApp(Joopy):
def __init__(self):
super(myApp, self).__init__()
self.get("/", lambda ctx: "hello world")
if __name__ == "__main__":
myApp.runApp(provider=myApp)
The Script API uses the lambda function to define routes.
from joopy.src.joopy import Joopy
class Controller(Joopy):
def __init__(self):
super(Controller, self).__init__()
@self.get("/")
def home(ctx):
return "hello world"
class myApp(Controller):
def __init__(self):
super(myApp, self).__init__()
self.mvc(router=super())
if __name__ == "__main__":
myApp.runApp(provider=myApp)
The MVC API uses the decorator to define routes.
The application in Joopy can have
- One or more routes
- Collection of operator over routes
A Route consists of three part:
- HTTP method, such as GET, POST, etc
- Path pattern, such as "/", "/foo", etc
- Handler function
For example,
self.get("/", lambda ctx: "home")
We use self.get()
for HTTP GET method. The Path pattern is define as "/". The Handler function is lambda ctx: "home"
.
Application logic goes inside a handler. A handler is a function that accepts a context object and produces a result.
For example,
self.get("/", lambda ctx: "home")
self.get("/hello", lambda ctx: "hello world")
self.get("/goodbye", lambda ctx: "good bye")
- GET / ⇒ home
- GET /hello ⇒ hello world
- GET /goodbye ⇒ good bye
Static files such as HTML files can be the result of a handler.
For example,
from joopy.src.joopy import Joopy
class myApp(Joopy):
def __init__(self):
super(myApp, self).__init__()
def demo_app(ctx):
data = self.prepare_html("./demo.html")
ctx.set_header("text/html")
return data
self.get("/demo", lambda ctx: demo_app(ctx))
def prepare_html(self, path):
file = open(path)
lines = file.read()
file.close()
return lines
if __name__ == "__main__":
myApp.runApp(provider=myApp)
GET /demo ⇒ ./demo.html
If there is no handler for a request, Joopy produces a 404 response.
404 Not Found
Cross cutting concerns such as response modification, verification, security, tracing, etc. is available via Route.Decorator. A decorator takes the next handler in the pipeline and produces a new handler.
For example, to modify the response, we can
from joopy.src.joopy import Joopy
class myApp(Joopy):
def __init__(self):
super(myApp, self).__init__()
self.decorator(lambda _next: lambda ctx: _next.apply(ctx) + " decorator")
self.get("/", lambda ctx: "home")
The expected response for URL "/" is "home decorator".
Another example is to compute the latency of response.
import time
from joopy.src.joopy import Joopy
class myApp(Joopy):
def __init__(self):
super(myApp, self).__init__()
def compute_latency(_next):
def handler(ctx):
t1 = time.time() # 1
response = _next.apply(ctx) # 2
t2 = time.time()
print("latency = {:.2f} sec".format(t2-t1)) #3
return response # 4
return handler
self.decorator(compute_latency)
self.get("/", lambda ctx: "decorator")
if __name__ == "__main__":
myApp.runApp(provider=myApp)
- Saves start time
- Proceed with execution
- Compute and print latency
- Returns a response
If you like this project, please don't hestitate to star it. Thanks! 😆