Repository: sanic-org/sanic

Issue:
Request stream not working when using Blueprints
**Describe the bug**
When trying to use Request Streaming in a route that is part of a blueprint, the request.stream object is never set (it is None), _unless_ `stream=True` has been set on some global route.


**Code snippet**
```
from sanic import Sanic
from sanic.response import text
from sanic.views import HTTPMethodView, stream
from sanic import Blueprint

app = Sanic()

# Not sure if using the decorator here is actually
# allowed or useful
@stream
def test(request):
    return text(type(request.stream))


class TestView(HTTPMethodView):
    @stream
    async def get(self, request):
        return text(type(request.stream))


bp = Blueprint("test")
bp.add_route(test, '/')
bp.add_route(TestView.as_view(), '/class')

app.blueprint(bp, url_prefix='/test')

# Adding this line makes request.stream work FOR ALL ROUTES,
# even those from the blueprint!
# app.add_route(test, '/', stream=True)

app.run(host='0.0.0.0', port=8000)
```


**Expected behavior**
Expect request.stream to be set.


**Environment (please complete the following information):**
 - OS: Ubuntu 18.04, RHEL7
 - Version 18.12.0 and master (cea1547e08230b6ad49eb7777fd8db5335382b7a)


**Additional context**
I am trying to sort this out myself, but the interaction between routes appears very complex. I will submit a pull request if I can get it working.



Discussion:
@quasarj Are you still there?

According to the document, use request stream with `Blueprint` will look like this:
```python
from sanic import Sanic, Blueprint

bp = Blueprint("test")

@bp.get('/', stream=True)
def test(request):
    return text(type(request.stream))

app.blueprint(bp, url_prefix='/test')
app.run(host='0.0.0.0', port=8000)

```

If you want to use `bp.add_route()` with request stream, it seems not working currently because `bp.add_route()` does not support `stream` argument. Maybe I can send a PR to make it work.

Resolving patch:
diff --git a/sanic/blueprints.py b/sanic/blueprints.py
--- a/sanic/blueprints.py
+++ b/sanic/blueprints.py
@@ -212,6 +212,7 @@ def add_route(
         strict_slashes=None,
         version=None,
         name=None,
+        stream=False,
     ):
         """Create a blueprint route from a function.
 
@@ -224,6 +225,7 @@ def add_route(
             training */*
         :param version: Blueprint Version
         :param name: user defined route name for url_for
+        :param stream: boolean specifying if the handler is a stream handler
         :return: function or class instance
         """
         # Handle HTTPMethodView differently
@@ -246,6 +248,7 @@ def add_route(
             methods=methods,
             host=host,
             strict_slashes=strict_slashes,
+            stream=stream,
             version=version,
             name=name,
         )(handler)
diff --git a/sanic/response.py b/sanic/response.py
--- a/sanic/response.py
+++ b/sanic/response.py
@@ -117,7 +117,7 @@ def get_headers(
 
         headers = self._parse_headers()
 
-        if self.status is 200:
+        if self.status == 200:
             status = b"OK"
         else:
             status = STATUS_CODES.get(self.status)
@@ -176,7 +176,7 @@ def output(self, version="1.1", keep_alive=False, keep_alive_timeout=None):
 
         headers = self._parse_headers()
 
-        if self.status is 200:
+        if self.status == 200:
             status = b"OK"
         else:
             status = STATUS_CODES.get(self.status, b"UNKNOWN RESPONSE")


Test patch:
diff --git a/tests/test_request_stream.py b/tests/test_request_stream.py
--- a/tests/test_request_stream.py
+++ b/tests/test_request_stream.py
@@ -270,6 +270,18 @@ async def streaming(response):
 
         return stream(streaming)
 
+    async def post_add_route(request):
+        assert isinstance(request.stream, StreamBuffer)
+
+        async def streaming(response):
+            while True:
+                body = await request.stream.read()
+                if body is None:
+                    break
+                await response.write(body.decode("utf-8"))
+        return stream(streaming)
+
+    bp.add_route(post_add_route, '/post/add_route', methods=['POST'], stream=True)
     app.blueprint(bp)
 
     assert app.is_request_stream is True
@@ -314,6 +326,10 @@ async def streaming(response):
     assert response.status == 200
     assert response.text == data
 
+    request, response = app.test_client.post("/post/add_route", data=data)
+    assert response.status == 200
+    assert response.text == data
+
 
 def test_request_stream_composition_view(app):
     """for self.is_request_stream = True"""