Flask Middleware Ontwikkeling en Integratie
description
Met deze prompt kan de gebruiker leren hoe middleware in Flask effectief te gebruiken voor het verbeteren van de applicatiestructuur, foutafhandeling en logging. Het lost problemen op rondom gestructureerde verzoekverwerking en biedt concrete voorbeelden van maatwerk middleware, wat beter is dan algemene documentatie omdat het specifiek is toegespitst op de gebruiker zijn projectstructuur en behoeften.
prompt
Help me bij het ontwikkelen en integreren van middleware in mijn Flask applicatie. Mijn huidige applicatie structuur is: <beschrijf je huidige applicatie structuur>. Leg uit hoe ik middleware ka ...
try_prompt
generate_helper
disclaimerOnPageApi
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Natuurlijk! In Flask kun je middleware gebruiken om verzoeken te verwerken, logging toe te passen en foutafhandeling te verbeteren door gebruik te maken van WSGI middleware of door custom middleware te schrijven met behulp van Flask's `before_request`, `after_request`, en `errorhandler` functies. Hier zijn enkele manieren en voorbeelden:
1. **Gebruik van `before_request` en `after_request` voor middleware-achtig gedrag**
Deze functies worden uitgevoerd vóór en na elke request.
```python
from flask import Flask, request, g
app = Flask(__name__)
# Middleware-achtig gedrag voor alle requests
@app.before_request
def before_request_func():
# Bijvoorbeeld: logging van inkomende verzoeken
print(f"Ontvangen verzoek naar {request.path}")
# Je kunt ook gegevens opslaan in 'g' voor gebruik later
g.start_time = request.start_time = __import__('time').time()
@app.after_request
def after_request_func(response):
# Bijvoorbeeld: logging van responsetijd
duur = __import__('time').time() - g.start_time
print(f"Verzoek naar {request.path} duurde {duur:.4f} seconden")
return response
```
2. **Custom middleware met WSGI**
Je kunt ook een WSGI middleware schrijven die elke request afhandelt.
```python
class MyMiddleware:
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
# Verzoek voor verwerking
print("Middleware: verzoek ontvangen")
# Hier kun je headers controleren, request aanpassen, etc.
return self.app(environ, start_response)
# Applicatie wrapen met middleware
app.wsgi_app = MyMiddleware(app.wsgi_app)
```
3. **Logging implementeren**
Gebruik bijvoorbeeld Python's `logging` module binnen je middleware of request handlers.
```python
import logging
logging.basicConfig(level=logging.INFO)
@app.before_request
def log_request():
logging.info(f"Request: {request.method} {request.path}")
```
4. **Foutafhandeling verbeteren**
Gebruik `@app.errorhandler()` om custom foutpagina’s of logica toe te voegen.
```python
@app.errorhandler(404)
def page_not_found(e):
# Log de fout
app.logger.warning(f"404 Fout op {request.path}")
# Custom response
return "Pagina niet gevonden", 404
@app.errorhandler(Exception)
def handle_exception(e):
# Log de fout
app.logger.error(f"Onverwachte fout: {e}")
return "Er is een fout opgetreden, probeer het later opnieuw.", 500
```
### Samenvatting
- Gebruik `@app.before_request` en `@app.after_request` voor eenvoudige middleware-achtige functies.
- Voor meer controle, implementeer een WSGI middleware class en wrap je app.
- Voeg logging toe via de `logging` module.
- Verbeter foutafhandeling met `@app.errorhandler`.
Door deze technieken toe te passen, kun je je Flask applicatie uitbreiden met krachtige middleware-functionaliteit, zonder dat je je huidige structuur met één bestand en geen Blueprints hoeft aan te passen.
provider: deepseek
model: deepseek-chat
Zeker! Ik leg je stap voor stap uit hoe je middleware kunt ontwikkelen en integreren in je Flask applicatie.
## Basis Middleware Structuur in Flask
Middleware in Flask wordt typisch geïmplementeerd als WSGI-middleware. Hier is de basisstructuur:
```python
from flask import Flask, request
import time
import logging
app = Flask(__name__)
# Configureer logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class SimpleMiddleware:
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
# Pre-request verwerking
start_time = time.time()
request_method = environ.get('REQUEST_METHOD')
request_path = environ.get('PATH_INFO')
logger.info(f"Inkomend verzoek: {request_method} {request_path}")
# Verwerk het verzoek
response = self.app(environ, start_response)
# Post-request verwerking
duration = time.time() - start_time
logger.info(f"Verzoek voltooid in {duration:.4f} seconden")
return response
# Wrap je app met middleware
app.wsgi_app = SimpleMiddleware(app.wsgi_app)
```
## Praktische Middleware Voorbeelden
### 1. Logging Middleware
```python
class LoggingMiddleware:
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
start_time = time.time()
ip_address = environ.get('REMOTE_ADDR')
user_agent = environ.get('HTTP_USER_AGENT', 'Onbekend')
method = environ.get('REQUEST_METHOD')
path = environ.get('PATH_INFO')
# Log inkomend verzoek
logger.info(f"IP: {ip_address} - {method} {path} - User-Agent: {user_agent}")
def custom_start_response(status, headers, exc_info=None):
# Log response status
logger.info(f"Response: {status}")
return start_response(status, headers, exc_info)
response = self.app(environ, custom_start_response)
duration = time.time() - start_time
logger.info(f"Request duur: {duration:.3f}s")
return response
```
### 2. Authentication Middleware
```python
class AuthMiddleware:
def __init__(self, app, api_keys):
self.app = app
self.api_keys = api_keys
def __call__(self, environ, start_response):
# Skip auth voor bepaalde routes
path = environ.get('PATH_INFO')
if path in ['/login', '/public']:
return self.app(environ, start_response)
# Controleer API key
api_key = environ.get('HTTP_X_API_KEY') or environ.get('QUERY_STRING', '').split('api_key=')[-1].split('&')[0]
if api_key not in self.api_keys:
# Unauthorized response
start_response('401 Unauthorized', [('Content-Type', 'text/plain')])
return [b'Unauthorized - Ongeldige API key']
return self.app(environ, start_response)
```
### 3. Rate Limiting Middleware
```python
from collections import defaultdict
from datetime import datetime, timedelta
class RateLimitMiddleware:
def __init__(self, app, max_requests=100, time_window=3600):
self.app = app
self.max_requests = max_requests
self.time_window = time_window
self.requests = defaultdict(list)
def __call__(self, environ, start_response):
client_ip = environ.get('REMOTE_ADDR')
current_time = datetime.now()
# Clean oude requests
self.requests[client_ip] = [t for t in self.requests[client_ip]
if current_time - t < timedelta(seconds=self.time_window)]
if len(self.requests[client_ip]) >= self.max_requests:
start_response('429 Too Many Requests', [('Content-Type', 'text/plain')])
return [b'Rate limit exceeded - Probeer later opnieuw']
self.requests[client_ip].append(current_time)
return self.app(environ, start_response)
```
### 4. Error Handling Middleware
```python
class ErrorHandlingMiddleware:
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
try:
return self.app(environ, start_response)
except Exception as e:
# Log de error
logger.error(f"Onverwachte fout: {str(e)}", exc_info=True)
# Return een gestandaardiseerde error response
start_response('500 Internal Server Error', [('Content-Type', 'application/json')])
error_response = {
"error": "Internal Server Error",
"message": "Er is een onverwachte fout opgetreden",
"status": 500
}
return [json.dumps(error_response).encode()]
```
## Integratie in Je Flask App
```python
from flask import Flask, jsonify
import json
app = Flask(__name__)
# Je bestaande routes
@app.route('/')
def home():
return jsonify({"message": "Welkom bij mijn Flask app!"})
@app.route('/api/data')
def get_data():
return jsonify({"data": [1, 2, 3, 4, 5]})
# Configureer middleware
api_keys = {"secret-key-123", "another-key-456"}
# Chain middleware (volgorde is belangrijk!)
app.wsgi_app = ErrorHandlingMiddleware(app.wsgi_app)
app.wsgi_app = RateLimitMiddleware(app.wsgi_app, max_requests=50, time_window=3600)
app.wsgi_app = AuthMiddleware(app.wsgi_app, api_keys)
app.wsgi_app = LoggingMiddleware(app.wsgi_app)
if __name__ == '__main__':
app.run(debug=True)
```
## Alternatieve Aanpak met Flask's `before_request` en `after_request`
Voor eenvoudigere use cases kun je ook Flask's built-in decorators gebruiken:
```python
@app.before_request
def before_request():
request.start_time = time.time()
logger.info(f"Begonnen met: {request.method} {request.path}")
@app.after_request
def after_request(response):
duration = time.time() - request.start_time
logger.info(f"Voltooid: {request.method} {request.path} - Status: {response.status_code} - Duur: {duration:.3f}s")
response.headers['X-Response-Time'] = f'{duration:.3f}s'
return response
@app.errorhandler(404)
def not_found(error):
return jsonify({"error": "Niet gevonden", "message": "De opgevraagde resource bestaat niet"}), 404
@app.errorhandler(500)
def internal_error(error):
logger.error(f"Server error: {error}")
return jsonify({"error": "Interne serverfout", "message": "Er is iets misgegaan"}), 500
```
## Belangrijke Tips:
1. **Middleware volgorde**: De volgorde waarin je middleware wrap is belangrijk
2. **Performance**: Houd middleware lichtgewicht voor kritieke paden
3. **Foutafhandeling**: Zorg dat errors goed worden gelogged en afgehandeld
4. **Testen**: Test je middleware grondlijk met verschillende scenario's
Begin met eenvoudige logging middleware en breid geleidelijk uit op basis van je behoeften!