From 732b284b01a9973240fcbb0484ac4445a2b07dcc Mon Sep 17 00:00:00 2001 From: Hanzhang Zeng <48038149+Hazhzeng@users.noreply.github.com> Date: Mon, 3 May 2021 12:32:37 -0700 Subject: [PATCH 1/4] Add AnatoliB to CodeOwners --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index ab041660..8aa846cd 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -9,4 +9,4 @@ # AZURE FUNCTIONS TEAM # For all file changes, github would automatically include the following people in the PRs. # -* @anirudhgarg @Hazhzeng @vrdmr +* @anirudhgarg @Hazhzeng @vrdmr @AnatoliB From c6b5208d98dc524e5b71f10a45af9c9af81f14d2 Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Mon, 10 Oct 2022 09:18:14 +1100 Subject: [PATCH 2/4] Create an async handler and deprecate the old --- azure/functions/_http_asgi.py | 37 ++++++++++++++++++++++++++++------- tests/test_http_asgi.py | 20 +++++++++++++++++++ 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/azure/functions/_http_asgi.py b/azure/functions/_http_asgi.py index 879a37e6..bf62870c 100644 --- a/azure/functions/_http_asgi.py +++ b/azure/functions/_http_asgi.py @@ -4,6 +4,7 @@ from typing import Dict, List, Tuple, Optional, Any, Union import logging import asyncio +from warnings import warn, DeprecationWarning from wsgiref.headers import Headers from ._abc import Context @@ -149,18 +150,19 @@ def __init__(self, app): self.main = self._handle def handle(self, req: HttpRequest, context: Optional[Context] = None): - """Method to convert an Azure Functions HTTP request into a ASGI - Python object. Example on handling ASGI app in a HTTP trigger by - calling .handle() in .main() method: + """Deprecated. Please use handle_async instead: - import azure.functions as func + import azure.functions as func - from FastapiApp import app + from FastapiApp import app - def main(req, context): - return func.AsgiMiddleware(app).handle(req, context) + async def main(req, context): + return await func.AsgiMiddleware(app).handle_async(req, context) """ + warn("handle() is deprecated. Please use handle_async() instead.", + DeprecationWarning, stacklevel=2) self._logger.debug(f"Handling {req.url} as an ASGI request.") + self._logger.warning(f"handle() is deprecated. Please `await .handle_async()` instead.") return self._handle(req, context) def _handle(self, req, context): @@ -172,3 +174,24 @@ def _handle(self, req, context): ) return asgi_response.to_func_response() + + async def handle_async(self, req: HttpRequest, context: Optional[Context] = None): + """Method to convert an Azure Functions HTTP request into a ASGI + Python object. Example on handling ASGI app in a HTTP trigger by + calling .handle_async() in .main() method: + + import azure.functions as func + + from FastapiApp import app + + async def main(req, context): + return await func.AsgiMiddleware(app).handle_async(req, context) + """ + self._logger.debug(f"Awaiting {req.url} as an ASGI request.") + return await self._handle_async(req, context) + + async def _handle_async(self, req, context): + asgi_request = AsgiRequest(req, context) + scope = asgi_request.to_asgi_http_scope() + asgi_response = await AsgiResponse.from_app(self._app, scope, req.get_body()) + return asgi_response.to_func_response() diff --git a/tests/test_http_asgi.py b/tests/test_http_asgi.py index e48d541c..4395fd72 100644 --- a/tests/test_http_asgi.py +++ b/tests/test_http_asgi.py @@ -1,6 +1,7 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. +import asyncio import unittest import azure.functions as func @@ -194,3 +195,22 @@ def test_middleware_wrapper(self): # Verify asserted self.assertEqual(response.status_code, 200) self.assertEqual(response.get_body(), test_body) + + def test_middleware_async_calls_app_with_context(self): + """Test the middleware with the awaitable handle_async() method + async def main(req, context): + return await AsgiMiddleware(app).handle_async(req, context) + """ + app = MockAsgiApplication() + test_body = b'Hello world!' + app.response_body = test_body + app.response_code = 200 + req = self._generate_func_request() + ctx = self._generate_func_context() + response = asyncio.get_event_loop().run_until_complete( + AsgiMiddleware(app).handle_async(req, ctx) + ) + + # Verify asserted + self.assertEqual(response.status_code, 200) + self.assertEqual(response.get_body(), test_body) From a4bc03c8be5e48a033890b9e23a973a1557c3eb7 Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Mon, 10 Oct 2022 09:26:42 +1100 Subject: [PATCH 3/4] DeprecationWarning is a builtin --- azure/functions/_http_asgi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure/functions/_http_asgi.py b/azure/functions/_http_asgi.py index bf62870c..e8254390 100644 --- a/azure/functions/_http_asgi.py +++ b/azure/functions/_http_asgi.py @@ -4,7 +4,7 @@ from typing import Dict, List, Tuple, Optional, Any, Union import logging import asyncio -from warnings import warn, DeprecationWarning +from warnings import warn from wsgiref.headers import Headers from ._abc import Context From 42a5ffd36b37c19714289d527a7d9369177b29c8 Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Mon, 10 Oct 2022 09:57:58 +1100 Subject: [PATCH 4/4] fix flake8 violations --- azure/functions/_http_asgi.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/azure/functions/_http_asgi.py b/azure/functions/_http_asgi.py index e8254390..4273c03e 100644 --- a/azure/functions/_http_asgi.py +++ b/azure/functions/_http_asgi.py @@ -152,17 +152,18 @@ def __init__(self, app): def handle(self, req: HttpRequest, context: Optional[Context] = None): """Deprecated. Please use handle_async instead: - import azure.functions as func + import azure.functions as func - from FastapiApp import app + from FastapiApp import app - async def main(req, context): - return await func.AsgiMiddleware(app).handle_async(req, context) + async def main(req, context): + return await func.AsgiMiddleware(app).handle_async(req, context) """ - warn("handle() is deprecated. Please use handle_async() instead.", + warn("handle() is deprecated. Please use handle_async() instead.", DeprecationWarning, stacklevel=2) self._logger.debug(f"Handling {req.url} as an ASGI request.") - self._logger.warning(f"handle() is deprecated. Please `await .handle_async()` instead.") + self._logger.warning( + "handle() is deprecated. Please `await .handle_async()` instead.") return self._handle(req, context) def _handle(self, req, context): @@ -174,8 +175,10 @@ def _handle(self, req, context): ) return asgi_response.to_func_response() - - async def handle_async(self, req: HttpRequest, context: Optional[Context] = None): + + async def handle_async(self, + req: HttpRequest, + context: Optional[Context] = None): """Method to convert an Azure Functions HTTP request into a ASGI Python object. Example on handling ASGI app in a HTTP trigger by calling .handle_async() in .main() method: @@ -185,7 +188,8 @@ async def handle_async(self, req: HttpRequest, context: Optional[Context] = None from FastapiApp import app async def main(req, context): - return await func.AsgiMiddleware(app).handle_async(req, context) + return await func.AsgiMiddleware(app).handle_async(req, + context) """ self._logger.debug(f"Awaiting {req.url} as an ASGI request.") return await self._handle_async(req, context) @@ -193,5 +197,7 @@ async def main(req, context): async def _handle_async(self, req, context): asgi_request = AsgiRequest(req, context) scope = asgi_request.to_asgi_http_scope() - asgi_response = await AsgiResponse.from_app(self._app, scope, req.get_body()) + asgi_response = await AsgiResponse.from_app(self._app, + scope, + req.get_body()) return asgi_response.to_func_response()