---
myst:
html_meta:
"description": ""
"property=og:description": ""
"property=og:title": ""
"keywords": ""
---
# Middlewares
A middleware is an object that wraps the original application,
hence the name.
A middle is called between the application and the server.
It can modify the response or the environment or route requests to
different application objects.
> ```{image} ./_static/middlewares2.png
> :scale: 90%
> ```
Middlewares and apps are agnostic to each other,
so we can plumb any WSGI app to our middleware,
and our middleware to any WSGI app. Middleware can be chained,
allowing our response or request to go through multiple
phases of processing.
Here is for example how the Django web framework chains multiple middlewares
before calling the application:
```shell
$ django-admin startproject example
$ grep -c2 -ni middleware example/example/settings.py
grep -i middleware example/example/settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
```
Django imports these middlewares from the their
specified module and plumbs them one after another. Let's see how
we can do that too.
Other frameworks use `extentions` sometimes also called `plugins` or
`includes`. For example, the Flask framework really wraps the
`Application` instance:
```python
"""
Example how flask uses 3 middlewares each wrapping around the
application
"""
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.bcrypt import Bcrypt
from flask.ext.login import LoginManager
app = Flask(__name__)
bcrypt = Bcrypt(app)
login_manager = LoginManager()
login_manager.init_app(app)
db = SQLAlchemy(app)
```
`Bottle.py` has a similar approach:
```python
import bottle
from bottle.ext import sqlite
app = bottle.Bottle()
plugin = sqlite.Plugin(dbfile='/tmp/test.db')
app.install(plugin)
@app.route('/show/:item')
def show(item, db):
row = db.execute('SELECT * from items where name=?', item).fetchone()
if row:
return template('showitem', page=row)
return HTTPError(404, "Page not found")
```
Bottle hides the fact that the `app.install` command is wrapping your
application with a call plugin which takes place before your application
and after your application login. These actions could be for example opening
and closing connections to the database before and after the request if
needed.
## A Simple WSGI Middleware
As an example we show a simple WSGI middle which logs the
environment dictionary to the console:
```python
def log_environ(handler):
"""print the environment dictionary to the console"""
from pprint import pprint
def _inner(environ, start_function):
pprint(environ)
return handler(environ, start_function)
return _inner
# this will show "Hello World!" in your browser,
# and the environment in the console
app = log_environ(hello_world_app)
```
### Exercise 2
Implement your own middleware which capitalizes the response you original
application return.
````{dropdown} Solution
:animate: fade-in-slide-down
:icon: question
```python
def capitalize_response(handler):
"""dumb middleware the assumes response is a list of
strings which can be capitalized"""
def _inner(environ, start_response):
response = handler(environ, start_response)
return [line.decode().upper().encode() for line in response]
return _inner
def handler(environ, start_function):
start_function('200 OK', [('Content-Type', 'text/plain')])
return [b"Hello World!\n"]
# this will return HELLO WORLD
app = capitalize_response(handler)
```
````
### Exercise 3
Implement your own middleware which reverses the response. Upon calling this
middleware twice you should see the original response, e.g.:
```python
def reverser(wsgiapp):
...
...
app = reverser(reverser(app)) # should return Hello WSGI!
```
````{dropdown} Solution
:animate: fade-in-slide-down
:icon: question
```python
def reverser(handler):
def _inner(environ, start_response):
response = handler(environ, start_response)
new_response = [x[::-1] for x in response]
print(new_response)
return new_response
return _inner
def app(environ, start_function):
start_function('200 OK', [('Content-Type', 'text/plain')])
return [b"Hello World!\n"]
# this will return Hello World
app = reverser(reverser(app))
```
````