WSGI frameworks¶
Did you know because of the awesome work from a2wsgi 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.wsgi 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.wsgi 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.wsgi 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.wsgi 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.wsgi 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.wsgi 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.