Sanic can now parse args and json
This commit is contained in:
parent
0489526ac9
commit
e0b9260644
|
@ -5,6 +5,8 @@ import signal
|
||||||
import functools
|
import functools
|
||||||
import httptools
|
import httptools
|
||||||
import logging
|
import logging
|
||||||
|
from ujson import loads as json_loads
|
||||||
|
from urllib.parse import parse_qs
|
||||||
|
|
||||||
import httptools
|
import httptools
|
||||||
try:
|
try:
|
||||||
|
@ -21,7 +23,7 @@ from .response import HTTPResponse
|
||||||
PRINT = 0
|
PRINT = 0
|
||||||
|
|
||||||
class Request:
|
class Request:
|
||||||
__slots__ = ('protocol', 'url', 'headers', 'version', 'method')
|
__slots__ = ('protocol', 'url', 'headers', 'version', 'method', 'query_string', 'body', 'parsed_json', 'parsed_args')
|
||||||
|
|
||||||
def __init__(self, protocol, url, headers, version, method):
|
def __init__(self, protocol, url, headers, version, method):
|
||||||
self.protocol = protocol
|
self.protocol = protocol
|
||||||
|
@ -30,6 +32,35 @@ class Request:
|
||||||
self.version = version
|
self.version = version
|
||||||
self.method = method
|
self.method = method
|
||||||
|
|
||||||
|
# Capture query string
|
||||||
|
query_string_position = self.url.find(b"?")
|
||||||
|
if query_string_position != -1:
|
||||||
|
self.query_string = self.url[query_string_position+1:]
|
||||||
|
self.url = self.url[:query_string_position]
|
||||||
|
else:
|
||||||
|
self.query_string = None
|
||||||
|
|
||||||
|
# Init but do not inhale
|
||||||
|
self.body = None
|
||||||
|
self.parsed_json = None
|
||||||
|
self.parsed_args = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def json(self):
|
||||||
|
if not self.parsed_json:
|
||||||
|
if not self.body:
|
||||||
|
raise ValueError("No body to parse")
|
||||||
|
self.parsed_json = json_loads(self.body)
|
||||||
|
|
||||||
|
return self.parsed_json
|
||||||
|
|
||||||
|
@property
|
||||||
|
def args(self):
|
||||||
|
if not self.parsed_args and self.query_string:
|
||||||
|
self.parsed_args = {k:v if len(v)>1 else v[0] for k,v in parse_qs(self.query_string).items()}
|
||||||
|
|
||||||
|
return self.parsed_args
|
||||||
|
|
||||||
class HttpProtocol(asyncio.Protocol):
|
class HttpProtocol(asyncio.Protocol):
|
||||||
|
|
||||||
__slots__ = ('loop',
|
__slots__ = ('loop',
|
||||||
|
@ -79,8 +110,8 @@ class HttpProtocol(asyncio.Protocol):
|
||||||
try:
|
try:
|
||||||
#print(data)
|
#print(data)
|
||||||
self.parser.feed_data(data)
|
self.parser.feed_data(data)
|
||||||
except httptools.parser.errors.HttpParserError:
|
except httptools.parser.errors.HttpParserError as e:
|
||||||
#log.error("Invalid request data, connection closed")
|
log.error("Invalid request data, connection closed ({})".format(e))
|
||||||
self.transport.close()
|
self.transport.close()
|
||||||
|
|
||||||
def on_url(self, url):
|
def on_url(self, url):
|
||||||
|
@ -98,21 +129,27 @@ class HttpProtocol(asyncio.Protocol):
|
||||||
method=self.parser.get_method()
|
method=self.parser.get_method()
|
||||||
)
|
)
|
||||||
#print("res {} - {}".format(n, self.request))
|
#print("res {} - {}".format(n, self.request))
|
||||||
self.loop.call_soon(self.handle, self.request)
|
|
||||||
|
def on_body(self, body):
|
||||||
|
self.request.body = body
|
||||||
|
def on_message_complete(self):
|
||||||
|
self.loop.create_task(self.get_response(self.request))
|
||||||
|
|
||||||
# -------------------------------------------- #
|
# -------------------------------------------- #
|
||||||
# Responding
|
# Responding
|
||||||
# -------------------------------------------- #
|
# -------------------------------------------- #
|
||||||
|
|
||||||
def handle(self, request):
|
async def get_response(self, request):
|
||||||
handler = self.router.get(request.url)
|
handler = self.router.get(request.url)
|
||||||
if handler.is_async:
|
try:
|
||||||
future = asyncio.Future()
|
if handler.is_async:
|
||||||
self.loop.create_task(self.handle_response(future, handler, request))
|
response = await handler(request)
|
||||||
future.add_done_callback(self.handle_result)
|
else:
|
||||||
else:
|
response = handler(request)
|
||||||
response = handler(request)
|
except Exception as e:
|
||||||
self.write_response(request, response)
|
response = HTTPResponse("Error: {}".format(e))
|
||||||
|
|
||||||
|
self.write_response(request, response)
|
||||||
|
|
||||||
def write_response(self, request, response):
|
def write_response(self, request, response):
|
||||||
#print("response - {} - {}".format(self.n, self.request))
|
#print("response - {} - {}".format(self.n, self.request))
|
||||||
|
@ -122,8 +159,8 @@ class HttpProtocol(asyncio.Protocol):
|
||||||
#print("KA - {}".format(self.parser.should_keep_alive()))
|
#print("KA - {}".format(self.parser.should_keep_alive()))
|
||||||
if not keep_alive:
|
if not keep_alive:
|
||||||
self.transport.close()
|
self.transport.close()
|
||||||
except:
|
except Exception as e:
|
||||||
log.error("Writing request failed, connection closed")
|
log.error("Writing request failed, connection closed {}".format(e))
|
||||||
self.transport.close()
|
self.transport.close()
|
||||||
|
|
||||||
self.parser = None
|
self.parser = None
|
||||||
|
|
13
test.aiohttp.py
Normal file
13
test.aiohttp.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
from aiohttp import web
|
||||||
|
|
||||||
|
async def handle(request):
|
||||||
|
name = request.match_info.get('name', "Anonymous")
|
||||||
|
text = "Hello, " + name
|
||||||
|
return web.Response(text=text)
|
||||||
|
|
||||||
|
|
||||||
|
app = web.Application()
|
||||||
|
app.router.add_get('/', handle)
|
||||||
|
app.router.add_get('/{name}', handle)
|
||||||
|
|
||||||
|
web.run_app(app)
|
9
test.py
9
test.py
|
@ -6,8 +6,17 @@ app = Sanic("test")
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
async def test(request):
|
async def test(request):
|
||||||
return json({ "test": True })
|
return json({ "test": True })
|
||||||
|
|
||||||
@app.route("/text")
|
@app.route("/text")
|
||||||
def test(request):
|
def test(request):
|
||||||
return text('hi')
|
return text('hi')
|
||||||
|
|
||||||
|
@app.route("/post_json")
|
||||||
|
def test(request):
|
||||||
|
return json({ "received": True, "message": request.json })
|
||||||
|
|
||||||
|
@app.route("/query_string")
|
||||||
|
def test(request):
|
||||||
|
return json({ "parsed": True, "args": request.args, "url": request.url, "query_string": request.query_string })
|
||||||
|
|
||||||
app.run(host="0.0.0.0")
|
app.run(host="0.0.0.0")
|
Loading…
Reference in New Issue
Block a user