We are working on developing an API using Python Quart. We have multiple routes set-up and a global error handling method
@app.errorhandler(InternalServerError)
def handle_error(error):
<logging and return server error code>
We need a way to tag each request by adding a random hash to the request object. So it can be accessed anywhere by tapping into the request object. For instance, the error handler should be able to access the random hash that's tagged with each request.
What is the cleanest way to achieve this using the Quart API framework. We wish to achieve this without any unexpected side effects.
CodePudding user response:
Here is a complete solution based on sub-classing the Request object, which according to the internal Quart comments is the preferred method.
https://pgjones.gitlab.io/quart/reference/source/quart.html https://github.com/pgjones/quart/blob/main/src/quart/wrappers/request.py
In this implementation a "correlation_id" needs to be taken from the request.args or generated on the fly, and should be attached to the request context for general use throughout the request in code or error handling etc.
(NOTE: the "ABC" import avoids some issues some Python abstract classes & not having to reimplement abstract methods.)
QuartUtilities.py:
from abc import ABC
from typing import cast
from uuid import uuid4
# Subclass of Request so we can add our own custom properties to the request context
class CorrelatedRequest(Request, ABC):
correlation_id: str = ""
def correlate_requests(app: Quart):
app.request_class = CorrelatedRequest
@app.before_request
def ensure_correlation_id_present():
correlated_request = cast(CorrelatedRequest, request)
if correlated_request.correlation_id != "":
return
if 'correlation_id' in request.args:
correlated_request.correlation_id = request.args["correlation_id"]
else:
correlated_request.correlation_id = uuid4()
def get_request_correlation_id() -> str:
return cast(CorrelatedRequest, request).correlation_id
QuartPI.py:
from quart import Quart
from werkzeug.exceptions import InternalServerError
from QuartUtilities import correlate_requests
app = Quart(__name__)
correlate_requests(app)
@app.errorhandler(InternalServerError)
def handle_error(error):
correlation_id = get_or_create_correlation_id()