Add stream decorator for HTTPMethodView

This commit is contained in:
38elements 2017-05-07 21:11:40 +09:00
parent 931397c7e1
commit 0b53c413a7
6 changed files with 67 additions and 3 deletions

View File

@ -35,9 +35,11 @@ async def index(request):
Sanic allows you to get request data by stream, as below. When the request ends, `request.stream.get()` returns `None`. Sanic allows you to get request data by stream, as below. When the request ends, `request.stream.get()` returns `None`.
``` ```python
from sanic import Sanic from sanic import Sanic
from sanic.views import CompositionView from sanic.views import CompositionView
from sanic.views import HTTPMethodView
from sanic.views import stream as stream_decorator
from sanic.blueprints import Blueprint from sanic.blueprints import Blueprint
from sanic.response import stream, text from sanic.response import stream, text
@ -45,6 +47,19 @@ bp = Blueprint('blueprint_request_stream')
app = Sanic('request_stream', is_request_stream=True) app = Sanic('request_stream', is_request_stream=True)
class SimpleView(HTTPMethodView):
@stream_decorator
async def post(self, request):
result = ''
while True:
body = await request.stream.get()
if body is None:
break
result += body.decode('utf-8')
return text(result)
@app.stream('/stream') @app.stream('/stream')
async def handler(request): async def handler(request):
async def streaming(response): async def streaming(response):
@ -83,6 +98,7 @@ async def post_handler(request):
return text(result) return text(result)
app.blueprint(bp) app.blueprint(bp)
app.add_route(SimpleView.as_view(), '/method_view')
view = CompositionView() view = CompositionView()
view.add(['POST'], post_handler, stream=True) view.add(['POST'], post_handler, stream=True)
app.add_route(view, '/composition_view') app.add_route(view, '/composition_view')

View File

@ -6,5 +6,5 @@ data = ""
for i in range(1, 250000): for i in range(1, 250000):
data += str(i) data += str(i)
r = requests.post('http://127.0.0.1:8000/bp_stream', data=data) r = requests.post('http://127.0.0.1:8000/method_view', data=data)
print(r.text) print(r.text)

View File

@ -1,5 +1,7 @@
from sanic import Sanic from sanic import Sanic
from sanic.views import CompositionView from sanic.views import CompositionView
from sanic.views import HTTPMethodView
from sanic.views import stream as stream_decorator
from sanic.blueprints import Blueprint from sanic.blueprints import Blueprint
from sanic.response import stream, text from sanic.response import stream, text
@ -7,6 +9,19 @@ bp = Blueprint('blueprint_request_stream')
app = Sanic('request_stream') app = Sanic('request_stream')
class SimpleView(HTTPMethodView):
@stream_decorator
async def post(self, request):
result = ''
while True:
body = await request.stream.get()
if body is None:
break
result += body.decode('utf-8')
return text(result)
@app.stream('/stream') @app.stream('/stream')
async def handler(request): async def handler(request):
async def streaming(response): async def streaming(response):
@ -45,6 +60,7 @@ async def post_handler(request):
return text(result) return text(result)
app.blueprint(bp) app.blueprint(bp)
app.add_route(SimpleView.as_view(), '/method_view')
view = CompositionView() view = CompositionView()
view.add(['POST'], post_handler, stream=True) view.add(['POST'], post_handler, stream=True)
app.add_route(view, '/composition_view') app.add_route(view, '/composition_view')

View File

@ -352,4 +352,7 @@ class Router:
:return: bool :return: bool
""" """
handler = self.get(request)[0] handler = self.get(request)[0]
if (hasattr(handler, 'view_class') and
hasattr(handler.view_class, request.method.lower())):
handler = getattr(handler.view_class, request.method.lower())
return hasattr(handler, 'is_stream') and handler.is_stream return hasattr(handler, 'is_stream') and handler.is_stream

View File

@ -64,6 +64,11 @@ class HTTPMethodView:
return view return view
def stream(func):
func.is_stream = True
return func
class CompositionView: class CompositionView:
"""Simple method-function mapped view for the sanic. """Simple method-function mapped view for the sanic.
You can add handler functions to methods (get, post, put, patch, delete) You can add handler functions to methods (get, post, put, patch, delete)

View File

@ -2,6 +2,7 @@ from sanic import Sanic
from sanic.blueprints import Blueprint from sanic.blueprints import Blueprint
from sanic.views import CompositionView from sanic.views import CompositionView
from sanic.views import HTTPMethodView from sanic.views import HTTPMethodView
from sanic.views import stream as stream_decorator
from sanic.response import stream, text from sanic.response import stream, text
bp = Blueprint('test_blueprint_request_stream') bp = Blueprint('test_blueprint_request_stream')
@ -13,6 +14,16 @@ class SimpleView(HTTPMethodView):
def get(self, request): def get(self, request):
return text('OK') return text('OK')
@stream_decorator
async def post(self, request):
result = ''
while True:
body = await request.stream.get()
if body is None:
break
result += body.decode('utf-8')
return text(result)
@app.stream('/stream') @app.stream('/stream')
async def handler(request): async def handler(request):
@ -31,7 +42,7 @@ async def get(request):
@bp.stream('/bp_stream') @bp.stream('/bp_stream')
async def bp_handler(request): async def bp_stream(request):
result = '' result = ''
while True: while True:
body = await request.stream.get() body = await request.stream.get()
@ -41,6 +52,11 @@ async def bp_handler(request):
return text(result) return text(result)
@bp.get('/bp_get')
async def bp_get(request):
return text('OK')
def get_handler(request): def get_handler(request):
return text('OK') return text('OK')
@ -73,6 +89,10 @@ def test_request_stream():
assert response.status == 200 assert response.status == 200
assert response.text == 'OK' assert response.text == 'OK'
request, response = app.test_client.post('/method_view', data=data)
assert response.status == 200
assert response.text == data
request, response = app.test_client.get('/composition_view') request, response = app.test_client.get('/composition_view')
assert response.status == 200 assert response.status == 200
assert response.text == 'OK' assert response.text == 'OK'
@ -89,6 +109,10 @@ def test_request_stream():
assert response.status == 200 assert response.status == 200
assert response.text == data assert response.text == data
request, response = app.test_client.get('/bp_get')
assert response.status == 200
assert response.text == 'OK'
request, response = app.test_client.post('/bp_stream', data=data) request, response = app.test_client.post('/bp_stream', data=data)
assert response.status == 200 assert response.status == 200
assert response.text == data assert response.text == data