Skip to content

WSGI frameworks

Did you know because of the awesome work from a2wsgi and from previous amazing jobs from Starlette added to the simplicity of Esmerald you can integrate any wsgi framework (Flask, Django...)?

Yes, that's right, you can now smoothly move to Esmerald without rewriting your old applications from the scratch, actually, you can reuse them directly within Esmerald, even another Esmerald running inside another Esmerald, an Esmeraldception.

WSGIMiddleware

Using this middleware is very simple, let's use Flask as example since it is very fast to spin-up a Flask service compared to other giants like Django.

from flask import Flask, escape, request

from esmerald import Esmerald, Gateway, Include, Request, get
from esmerald.middleware import WSGIMiddleware

flask_app = Flask(__name__)


@flask_app.route("/")
def flask_main():
    name = request.args.get("name", "Esmerald")
    return f"Hello, {escape(name)} from your Flask integrated!"


@get("/home/{name:str}")
async def home(request: Request) -> dict:
    name = request.path_params["name"]
    return {"name": escape(name)}


app = Esmerald(
    routes=[
        Gateway(handler=home),
        Include("/flask", WSGIMiddleware(flask_app)),
    ]
)
from flask import Flask, escape, request

from esmerald import Esmerald, Gateway, Include, Request, get
from esmerald.middleware import WSGIMiddleware

flask_app = Flask(__name__)


@flask_app.route("/")
def flask_main():
    name = request.args.get("name", "Esmerald")
    return f"Hello, {escape(name)} from your Flask integrated!"


@get("/home/{name:str}")
async def home(request: Request) -> dict:
    name = request.path_params["name"]
    return {"name": escape(name)}


app = Esmerald(
    routes=[
        Gateway(handler=home),
        Include(
            routes=[
                Include("/flask", WSGIMiddleware(flask_app)),
            ]
        ),
    ]
)
from flask import Flask, escape, request

from esmerald import Esmerald, Gateway, Include, Request, get
from esmerald.middleware import WSGIMiddleware

flask_app = Flask(__name__)
second_flask_app = Flask(__name__)


@flask_app.route("/")
def flask_main():
    name = request.args.get("name", "Esmerald")
    return f"Hello, {escape(name)} from your Flask integrated!"


@second_flask_app.route("/")
def flask_main():
    name = request.args.get("name", "Esmerald")
    return f"Hello, {escape(name)} from your Flask integrated!"


@get("/home/{name:str}")
async def home(request: Request) -> dict:
    name = request.path_params["name"]
    return {"name": name}


routes = [
    Gateway(handler=home),
    Include(
        routes=[
            Include(
                "/internal",
                routes=[
                    Include(
                        routes=[
                            Include("/flask", WSGIMiddleware(flask_app)),
                        ]
                    )
                ],
            ),
            Include(
                routes=[
                    Include(
                        routes=[
                            Include(
                                "/external",
                                routes=[
                                    Include(
                                        "/second/flask",
                                        WSGIMiddleware(second_flask_app),
                                    ),
                                ],
                            )
                        ]
                    )
                ]
            ),
        ]
    ),
]

app = Esmerald(routes=routes)
from flask import Flask, escape, request

from esmerald import Esmerald, Gateway, Include, Request, get
from esmerald.middleware import WSGIMiddleware

flask_app = Flask(__name__)
second_flask_app = Flask(__name__)


@flask_app.route("/")
def flask_main():
    name = request.args.get("name", "Esmerald")
    return f"Hello, {escape(name)} from your Flask integrated!"


@get("/home/{name:str}")
async def home(request: Request) -> dict:
    name = request.path_params["name"]
    return {"name": escape(name)}


@second_flask_app.route("/")
def second_flask_main():
    name = request.args.get("name", "Esmerald")
    return f"Hello, {escape(name)} from Flask!"


routes = [
    Include(
        path="/",
        routes=[
            Gateway(handler=home),
            Include("/flask", WSGIMiddleware(flask_app)),
            Include("/second/flask", WSGIMiddleware(second_flask_app)),
        ],
    )
]

app = Esmerald(routes=routes)
from flask import Flask, escape, request

from esmerald import Esmerald, Gateway, Include, Request, get
from esmerald.middleware import WSGIMiddleware

flask_app = Flask(__name__)
second_flask_app = Flask(__name__)


@flask_app.route("/")
def flask_main():
    name = request.args.get("name", "Esmerald")
    return f"Hello, {escape(name)} from your Flask integrated!"


@get("/home/{name:str}")
async def home(request: Request) -> dict:
    name = request.path_params["name"]
    return {"name": escape(name)}


@second_flask_app.route("/")
def second_flask_main():
    name = request.args.get("name", "Esmerald")
    return f"Hello, {escape(name)} from Flask!"


sub_esmerald = Esmerald(
    routes=[
        Gateway(handler=home),
        Include("/flask", WSGIMiddleware(flask_app)),
        Include("/second/flask", WSGIMiddleware(second_flask_app)),
    ]
)

routes = [Include("/sub-esmerald", app=sub_esmerald)]

app = Esmerald(routes=routes)
from flask import Flask, escape, request

from esmerald import ChildEsmerald, Esmerald, Gateway, Include, Request, get
from esmerald.middleware import WSGIMiddleware

flask_app = Flask(__name__)
second_flask_app = Flask(__name__)


@flask_app.route("/")
def flask_main():
    name = request.args.get("name", "Esmerald")
    return f"Hello, {escape(name)} from your Flask integrated!"


@get("/home/{name:str}")
async def home(request: Request) -> dict:
    name = request.path_params["name"]
    return {"name": escape(name)}


@second_flask_app.route("/")
def second_flask_main():
    name = request.args.get("name", "Esmerald")
    return f"Hello, {escape(name)} from Flask!"


child_esmerald = ChildEsmerald(
    routes=[
        Gateway(handler=home),
        Include("/flask", WSGIMiddleware(flask_app)),
        Include("/second/flask", WSGIMiddleware(second_flask_app)),
    ]
)

routes = [Include("/child-esmerald", app=child_esmerald)]

app = Esmerald(routes=routes)

You already get the idea, the integrations are endeless!

Verify it

With all of examples from before, you can now verify that the integrations are working.

The paths pointing to the WSGIMiddleware will be handled by Flask and the rest is handled by Esmerald, including the Esmerald inside another Esmerald.

If you run the endpoint handled by Flask:

  • /flask - From simple routing.
  • /flask - From nested routing.
  • /internal/flask and /external/second/flask - From complex routing.
  • /flask and /second/flask - From multiple flask apps.
  • /esmerald/flask and /esmerald/second/flask - From inside another Esmerald

You will see the response:

Hello, Esmerald from Flask!

Accessing any Esmerald endpoint:

  • /home/esmerald - From simple routing.
  • /home/esmerald - From complex routing.
  • /home/esmerald - From nested routing.
  • /home/esmerald - From multiple flask apps.
  • /esmerald/home/esmerald - From inside another Esmerald
{
    "name": "esmerald"
}

WSGI and Esmerald OpenAPI

Only apps that are inherited from Esmerald or ChildEsmerald will be showing in the OpenAPI documentation. This is for compatibility purposes only and does not affect the internal routing.

WSGI integrations and all the urls associated still work.