[Python] Allow to run pure Python request middlewares inside a Tower service (#1734)
## Motivation and Context * Customers want to be able to implement simple middleware directly in Python. This PR aims to add the initial support for it. * Improve the idiomatic experience of logging by exposing a handler compatible with Python's standard library `logging` module. ## Description ### Middleware A middleware is defined as a sync or async Python function that can return multiple values, following these rules: * Middleware not returning will let the execution continue without changing the original request. * Middleware returning a modified Request will update the original request before continuing the execution. * Middleware returning a Response will immediately terminate the request handling and return the response constructed from Python. * Middleware raising MiddlewareException will immediately terminate the request handling and return a protocol specific error, with the option of setting the HTTP return code. * Middleware raising any other exception will immediately terminate the request handling and return a protocol specific error, with HTTP status code 500. Middlewares are registered into the Python application and executed in order of registration. Example: from sdk import App from sdk.middleware import Request, MiddlewareException app = App() @app.request_middleware def inject_header(request: Request): request.set_header("x-amzn-answer", "42") return request @app.request_middleare def check_header(request: Request): if request.get_header("x-amzn-answer") != "42": raise MiddlewareException("Wrong answer", 404) @app.request_middleware def dump_headers(request: Request): logging.debug(f"Request headers after middlewares: {request.headers()}") **NOTE: this PR only adds support for request middlewares, which are executed before the operation handler. Response middlewares, executed after the operation are tracked here: https://github.com/awslabs/smithy-rs/issues/1754.** ### Logging To improve the idiomatic experience, now logging need to be configured from the Python side by using the standard `logging` module. This allows customers to opt-out of our `tracing` based logging implementation and use their own and logging level is now driven by Python. import logging from sdk.logging import TracingHandler logging.basicConfig(level=logging.INFO, handlers=[TracingHandler.handle()]) Signed-off-by:Bigo <1781140+crisidev@users.noreply.github.com> Co-authored-by:
Burak <burakvar@amazon.co.uk>
Loading
Please register or sign in to comment