Skip to content

Frameworks

Vellox is intended to provide support to any ASGI (Asynchronous Server Gateway Interface) application or framework. The "turtles all the way down" principle of ASGI allows for a great deal of interoperability across many different implementations, so the adapter should "just work"* for any ASGI application or framework.

* if it doesn't, then please open an issue. :)

Background

We can think about the ASGI framework support without referencing an existing implementation. There are no framework-specific rules or dependencies in the adapter class, and all applications will be treated the same.

Let's invent an API for a non-existent microframework to demonstrate things further. This could represent any ASGI framework application:

import vellox.adapter
import framework
from vellox import Vellox

app = framework.applications.Application()


@app.route("/")
def endpoint(request: framework.requests.Request) -> dict:
    return {"hi": "there"}


vellox = Vellox(app)

def handler(request):
    return vellox(request)

None of the framework details are important here. The routing decorator, request parameter, and return value of the endpoint method could be anything. The app instance will be a valid app parameter for Vellox so long as the framework exposes an ASGI-compatible interface:

class Application(Protocol):
    async def __call__(self, scope: Scope, receive: ASGIReceive, send: ASGISend) -> None:
        ...

Limitations

An application or framework may implement behaviour that is incompatible with the limitations of GCP Cloud Functions, and there may be additional configuration required depending on a particular deployment circumstance. In some cases it is possible to work around these limitations, but these kinds of limitations should generally be dealt with outside of Vellox itself.

Frameworks

The examples on this page attempt to demonstrate a basic implementation of a particular framework (usually from official documentation) to highlight the interaction with Vellox. Specific deployment tooling, infrastructure, external dependencies, etc. are not taken into account.

Starlette

Starlette is a lightweight ASGI framework/toolkit, which is ideal for building high performance asyncio services.

Vellox uses it as a toolkit in tests. It is developed by Encode, a wonderful community and collection of projects that are forming the foundations of the Python async web ecosystem.

Define an application:

from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
from vellox import Vellox


async def homepage(request):
    return JSONResponse({'hello': 'world'})

routes = [
    Route("/", endpoint=homepage)
]

app = Starlette(debug=True, routes=routes)

Then wrap it using Vellox:

vellox = Vellox(app)

def handler(request):
    return vellox(request)

FastAPI

FastAPI is a modern, fast (high-performance), web framework for building APIs with Python based on standard Python type hints.

from fastapi import FastAPI
from vellox import Vellox

app = FastAPI()


@app.get("/")
def read_root():
    return {"Hello": "World"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "q": q}

vellox = Vellox(app)

def handler(request):
    return vellox(request)

Responder

Responder is a familiar HTTP Service Framework for Python, powered by Starlette. The static_dir and templates_dir parameters must be set to none to disable Responder's automatic directory creation behaviour because GCP Cloud Functions is a read-only file system - see the limitations section for more details.

from vellox import Vellox
import responder

app = responder.API(static_dir=None, templates_dir=None)


@app.route("/{greeting}")
async def greet_world(req, resp, *, greeting):
    resp.text = f"{greeting}, world!"


vellox = Vellox(app)

def handler(request):
    return vellox(request)

The adapter usage for both FastAPI and Responder is the same as Starlette. However, this may be expected because they are built on Starlette - what about other frameworks?

Quart

Quart is a Python ASGI web microframework. It is intended to provide the easiest way to use asyncio functionality in a web context, especially with existing Flask apps. This is possible as the Quart API is a superset of the Flask API.

from quart import Quart
from vellox import Vellox

app = Quart(__name__)


@app.route("/hello")
async def hello():
    return "hello world!"

vellox = Vellox(app)

def handler(request):
    return vellox(request)

Sanic

Sanic is a Python web server and web framework that's written to go fast. It allows the usage of the async/await syntax added in Python 3.5, which makes your code non-blocking and speedy.

from sanic import Sanic
from sanic.response import json
from vellox import Vellox

app = Sanic()


@app.route("/")
async def test(request):
    return json({"hello": "world"})


vellox = Vellox(app)

def handler(request):
    return vellox(request)

Django

Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design.

It started introducing ASGI support in version 3.0. Certain async capabilities are not yet implemented and planned for future releases, however it can still be used with Vellox and other ASGI applications at the outer application level.

# asgi.py
import os
from vellox import Vellox
from django.core.asgi import get_asgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings")

application = get_asgi_application()

vellox = Vellox(app, lifespan="off")

def handler(request):
    return vellox(request)

This example looks a bit different than the others because it is based on Django's standard project configuration, but the ASGI behaviour is the same.

Channels

Channels is a project that takes Django and extends its abilities beyond HTTP - to handle WebSockets, chat protocols, IoT protocols, and more. It is the original driving force behind the ASGI specification.

It currently does not support ASGI version 3, but you can convert the application from ASGI version 2 using the guarantee_single_callable method provided in asgiref.

# asgi.py
import os
import django
from channels.routing import get_default_application
from asgiref.compatibility import guarantee_single_callable
from vellox import Vellox


os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
django.setup()
application = get_default_application()

wrapped_application = guarantee_single_callable(application)

vellox = Vellox(wrapped_application, lifespan="off")

def handler(request):
    return vellox(request)