diff --git a/sanic/app.py b/sanic/app.py index 163e806d..f0da45b2 100644 --- a/sanic/app.py +++ b/sanic/app.py @@ -22,7 +22,7 @@ from sanic.constants import HTTP_METHODS from sanic.exceptions import SanicException, ServerError, URLBuildError from sanic.handlers import ErrorHandler from sanic.log import LOGGING_CONFIG_DEFAULTS, error_logger, logger -from sanic.response import HTTPResponse, StreamingHTTPResponse +from sanic.response import BaseHTTPResponse, HTTPResponse from sanic.router import Router from sanic.server import ( AsyncioServer, @@ -1049,10 +1049,8 @@ class Sanic: "Exception occurred in one of response " "middleware handlers" ) - # Stream response - if isinstance(response, StreamingHTTPResponse): - await response.stream(request) - elif isinstance(response, HTTPResponse): + # Make sure that response is finished / run StreamingHTTP callback + if isinstance(response, BaseHTTPResponse): await request.respond(response).send(end_stream=True) else: raise ServerError( diff --git a/sanic/response.py b/sanic/response.py index 2cc74e1e..47f04b39 100644 --- a/sanic/response.py +++ b/sanic/response.py @@ -77,6 +77,8 @@ class BaseHTTPResponse: class StreamingHTTPResponse(BaseHTTPResponse): + """Old style streaming response. Use `request.respond()` instead of this in + new code to avoid the callback.""" __slots__ = ( "protocol", "streaming_fn", @@ -105,12 +107,14 @@ class StreamingHTTPResponse(BaseHTTPResponse): :param data: str or bytes-ish data to be written. """ - await self.send(self._encode_body(data)) + await super().send(self._encode_body(data)) + + async def send(self, *args, **kwargs): + if self.streaming_fn is not None: + await self.streaming_fn(self) + self.streaming_fn = None + await super().send(*args, **kwargs) - async def stream(self, request): - request.respond(self) - await self.streaming_fn(self) - await self.send(end_stream=True) class HTTPResponse(BaseHTTPResponse):