GitHub user asukaminato0721 added a comment to the discussion: Do we have 
better names for opendal python's Layer?

> a more in-depth study on how python users use middleware

Basically define a class -> define special method, usually `__call__` or 
`dispatch` -> put them into a list/builder pattern api

### 1. Django Middleware

```
django_mw_project/
├── myapp/
│   ├── __init__.py
│   ├── middleware.py  # <---
│   ├── views.py
│   └── urls.py
├── django_mw_project/
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py
```

**`myapp/middleware.py`:**

```python
import time

class TimingMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    def __call__(self, request):
        ...
        response = self.get_response(request)
        ...
        return response

class LoggingMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    def __call__(self, request):
        ...
        response = self.get_response(request)
        ...
        return response
```

```py
MIDDLEWARE = [
    ...
    # require seq: LoggingMiddleware -> TimingMiddleware -> ... -> View
    # respond seq: View -> ... -> TimingMiddleware -> LoggingMiddleware
    'myapp.middleware.LoggingMiddleware',
    'myapp.middleware.TimingMiddleware',
]
```

---

### 2. Flask Middleware (use WSGI Middleware)

**`flask_app.py`:**

```python
from flask import Flask, Response
import time

class TimingMiddleware:
    def __init__(self, wsgi_app):
        self.wsgi_app = wsgi_app

    def __call__(self, environ, start_response):
        response_iterable = self.wsgi_app(environ, custom_start_response)
        return response_iterable

class LoggingMiddleware:
    def __init__(self, wsgi_app):
        self.wsgi_app = wsgi_app

    def __call__(self, environ, start_response):
        request = Request(environ)
        def custom_start_response(status, headers, exc_info=None):
            ...
        response_iterable = self.wsgi_app(environ, custom_start_response)
        return response_iterable

app = Flask(__name__)

@app.route('/')
def hello():
    time.sleep(0.1)
    return Response("Hello from Flask with WSGI Middleware!", 
mimetype='text/plain')

# req seq: Logging -> Timing -> Flask App
# res seq: Flask App -> Timing -> Logging
app.wsgi_app = LoggingMiddleware(app.wsgi_app)
app.wsgi_app = TimingMiddleware(app.wsgi_app) # Timing in Logging

if __name__ == '__main__':
    app.run(debug=True, port=5000)
```

---

### 3. FastAPI Middleware

**`fastapi_app.py`:**

```python
from fastapi import FastAPI, Request, Response
import time
from starlette.middleware.base import BaseHTTPMiddleware, 
RequestResponseEndpoint
from starlette.types import ASGIApp, Receive, Scope, Send

class TimingMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next: 
RequestResponseEndpoint) -> Response:
        response = await call_next(request)
        return response

class LoggingMiddleware(BaseHTTPMiddleware):
     async def dispatch(self, request: Request, call_next: 
RequestResponseEndpoint) -> Response:
        response = await call_next(request)
        return response

app = FastAPI()

# use add_middleware 
# req seq: Logging -> Timing -> Route
# res seq: Route -> Timing -> Logging
app.add_middleware(LoggingMiddleware)         # most outside
app.add_middleware(TimingMiddleware)         # inner side

@app.get("/")
async def read_root():
    await asyncio.sleep(0.1)
    return {"message": "Hello from FastAPI with Middleware!"}
```

---

GitHub link: 
https://github.com/apache/opendal/discussions/6074#discussioncomment-12945572

----
This is an automatically sent email for dev@opendal.apache.org.
To unsubscribe, please send an email to: dev-unsubscr...@opendal.apache.org

Reply via email to