Skip to content

Commit 1ab44dd

Browse files
Support ASGI middleware chains by only yielding http.disconnect when response has been fully received (#153)
* Yield a disconnect on the second receive call * Stop http.disconnect being sent before all response body is sent * Test the correct sequence of messages * Shorter line Co-authored-by: peterstone2017 <12449837+YunchuWang@users.noreply.github.com>
1 parent bd11d48 commit 1ab44dd

File tree

2 files changed

+10
-7
lines changed

2 files changed

+10
-7
lines changed

azure/functions/_http_asgi.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ def __init__(self):
6868
self._headers: Union[Headers, Dict] = {}
6969
self._buffer: List[bytes] = []
7070
self._request_body: Optional[bytes] = b""
71+
self._has_received_response: bool = False
7172

7273
@classmethod
7374
async def from_app(cls, app, scope: Dict[str, Any],
@@ -95,6 +96,7 @@ def _handle_http_response_start(self, message: Dict[str, Any]):
9596

9697
def _handle_http_response_body(self, message: Dict[str, Any]):
9798
self._buffer.append(message["body"])
99+
self._has_received_response = not message.get("more_body", False)
98100
# XXX : Chunked bodies not supported, see
99101
# https://github.com/Azure/azure-functions-host/issues/4926
100102

@@ -106,14 +108,15 @@ async def _receive(self):
106108
"more_body": False,
107109
}
108110
self._request_body = None
111+
return reply
109112
else:
110-
reply = {
113+
while not self._has_received_response:
114+
await asyncio.sleep(0.1)
115+
return {
111116
"type": "http.disconnect",
112117
}
113-
return reply
114118

115119
async def _send(self, message):
116-
logging.debug(f"Received {message} from ASGI worker.")
117120
if message["type"] == "http.response.start":
118121
self._handle_http_response_start(message)
119122
elif message["type"] == "http.response.body":
@@ -142,7 +145,7 @@ def __init__(self, app):
142145
main = func.AsgiMiddleware(app).main
143146
"""
144147
if not self._usage_reported:
145-
self._logger.info("Instantiating Azure Functions ASGI middleware.")
148+
self._logger.debug("Starting Azure Functions ASGI middleware.")
146149
self._usage_reported = True
147150

148151
self._app = app

tests/test_http_asgi.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,6 @@ async def __call__(self, scope, receive, send):
6666
assert isinstance(self.received_request['body'], bytes)
6767
assert isinstance(self.received_request['more_body'], bool)
6868

69-
self.next_request = await receive()
70-
assert self.next_request['type'] == 'http.disconnect'
71-
7269
await send(
7370
{
7471
"type": "http.response.start",
@@ -83,6 +80,9 @@ async def __call__(self, scope, receive, send):
8380
}
8481
)
8582

83+
self.next_request = await receive()
84+
assert self.next_request['type'] == 'http.disconnect'
85+
8686

8787
class TestHttpAsgiMiddleware(unittest.TestCase):
8888
def _generate_func_request(

0 commit comments

Comments
 (0)