Handle Chrome preconnect (Fixes #8)

This commit is contained in:
Ricardo Mendonça Ferreira
2020-06-15 16:54:43 -03:00
committed by Miguel Grinberg
parent c5e1873523
commit 125af4b4a9
3 changed files with 91 additions and 82 deletions

View File

@@ -17,6 +17,8 @@ class Request(BaseRequest):
async def create(stream, client_addr): async def create(stream, client_addr):
# request line # request line
line = (await stream.readline()).strip().decode() line = (await stream.readline()).strip().decode()
if not line: # pragma: no cover
return None
method, url, http_version = line.split() method, url, http_version = line.split()
http_version = http_version.split('/', 1)[1] http_version = http_version.split('/', 1)[1]
@@ -103,48 +105,52 @@ class Microdot(BaseMicrodot):
async def dispatch_request(self, reader, writer): async def dispatch_request(self, reader, writer):
req = await Request.create(reader, writer.get_extra_info('peername')) req = await Request.create(reader, writer.get_extra_info('peername'))
f = self.find_route(req) if req:
try: f = self.find_route(req)
res = None try:
if f: res = None
for handler in self.before_request_handlers: if f:
res = await self._invoke_handler(handler, req) for handler in self.before_request_handlers:
if res: res = await self._invoke_handler(handler, req)
break if res:
if res is None: break
res = await self._invoke_handler(f, req, **req.url_args) if res is None:
if isinstance(res, tuple): res = await self._invoke_handler(
res = Response(*res) f, req, **req.url_args)
elif not isinstance(res, Response): if isinstance(res, tuple):
res = Response(res) res = Response(*res)
for handler in self.after_request_handlers: elif not isinstance(res, Response):
res = await self._invoke_handler(handler, req, res) or res res = Response(res)
elif 404 in self.error_handlers: for handler in self.after_request_handlers:
res = await self._invoke_handler(self.error_handlers[404], req) res = await self._invoke_handler(
else: handler, req, res) or res
res = 'Not found', 404 elif 404 in self.error_handlers:
except Exception as exc:
print_exception(exc)
res = None
if exc.__class__ in self.error_handlers:
try:
res = await self._invoke_handler( res = await self._invoke_handler(
self.error_handlers[exc.__class__], req, exc) self.error_handlers[404], req)
except Exception as exc2: # pragma: no cover
print_exception(exc2)
if res is None:
if 500 in self.error_handlers:
res = await self._invoke_handler(self.error_handlers[500],
req)
else: else:
res = 'Internal server error', 500 res = 'Not found', 404
if isinstance(res, tuple): except Exception as exc:
res = Response(*res) print_exception(exc)
elif not isinstance(res, Response): res = None
res = Response(res) if exc.__class__ in self.error_handlers:
await res.write(writer) try:
res = await self._invoke_handler(
self.error_handlers[exc.__class__], req, exc)
except Exception as exc2: # pragma: no cover
print_exception(exc2)
if res is None:
if 500 in self.error_handlers:
res = await self._invoke_handler(
self.error_handlers[500], req)
else:
res = 'Internal server error', 500
if isinstance(res, tuple):
res = Response(*res)
elif not isinstance(res, Response):
res = Response(res)
await res.write(writer)
await writer.aclose() await writer.aclose()
if self.debug: # pragma: no cover if self.debug and req: # pragma: no cover
print('{method} {path} {status_code}'.format( print('{method} {path} {status_code}'.format(
method=req.method, path=req.path, method=req.method, path=req.path,
status_code=res.status_code)) status_code=res.status_code))

View File

@@ -45,7 +45,7 @@ try:
except ImportError: except ImportError:
try: try:
import socket import socket
except ImportError: except ImportError: # pragma: no cover
socket = None socket = None
@@ -102,6 +102,8 @@ class Request():
def create(client_stream, client_addr): def create(client_stream, client_addr):
# request line # request line
line = client_stream.readline().strip().decode() line = client_stream.readline().strip().decode()
if not line: # pragma: no cover
return None
method, url, http_version = line.split() method, url, http_version = line.split()
http_version = http_version.split('/', 1)[1] http_version = http_version.split('/', 1)[1]
@@ -362,48 +364,49 @@ class Microdot():
stream = sock stream = sock
req = Request.create(stream, addr) req = Request.create(stream, addr)
f = self.find_route(req) if req:
try: f = self.find_route(req)
res = None try:
if f: res = None
for handler in self.before_request_handlers: if f:
res = handler(req) for handler in self.before_request_handlers:
if res: res = handler(req)
break if res:
if res is None: break
res = f(req, **req.url_args) if res is None:
if isinstance(res, tuple): res = f(req, **req.url_args)
res = Response(*res) if isinstance(res, tuple):
elif not isinstance(res, Response): res = Response(*res)
res = Response(res) elif not isinstance(res, Response):
for handler in self.after_request_handlers: res = Response(res)
res = handler(req, res) or res for handler in self.after_request_handlers:
elif 404 in self.error_handlers: res = handler(req, res) or res
res = self.error_handlers[404](req) elif 404 in self.error_handlers:
else: res = self.error_handlers[404](req)
res = 'Not found', 404
except Exception as exc:
print_exception(exc)
res = None
if exc.__class__ in self.error_handlers:
try:
res = self.error_handlers[exc.__class__](req, exc)
except Exception as exc2: # pragma: no cover
print_exception(exc2)
if res is None:
if 500 in self.error_handlers:
res = self.error_handlers[500](req)
else: else:
res = 'Internal server error', 500 res = 'Not found', 404
if isinstance(res, tuple): except Exception as exc:
res = Response(*res) print_exception(exc)
elif not isinstance(res, Response): res = None
res = Response(res) if exc.__class__ in self.error_handlers:
res.write(stream) try:
res = self.error_handlers[exc.__class__](req, exc)
except Exception as exc2: # pragma: no cover
print_exception(exc2)
if res is None:
if 500 in self.error_handlers:
res = self.error_handlers[500](req)
else:
res = 'Internal server error', 500
if isinstance(res, tuple):
res = Response(*res)
elif not isinstance(res, Response):
res = Response(res)
res.write(stream)
stream.close() stream.close()
if stream != sock: # pragma: no cover if stream != sock: # pragma: no cover
sock.close() sock.close()
if self.debug: # pragma: no cover if self.debug and req: # pragma: no cover
print('{method} {path} {status_code}'.format( print('{method} {path} {status_code}'.format(
method=req.method, path=req.path, method=req.method, path=req.path,
status_code=res.status_code)) status_code=res.status_code))

View File

@@ -1,5 +1,5 @@
[tox] [tox]
envlist=flake8,py35,py36,py37,py38upy envlist=flake8,py36,py37,py38,py39,upy
skipsdist=True skipsdist=True
skip_missing_interpreters=True skip_missing_interpreters=True
@@ -12,12 +12,12 @@ commands=
coverage erase coverage erase
deps=coverage deps=coverage
basepython= basepython=
flake8: python3.7 flake8: python3.8
py35: python3.5
py36: python3.6 py36: python3.6
py37: python3.7 py37: python3.7
py38: python3.8 py38: python3.8
upy: python3.7 py39: python3.9
upy: python3.8
[testenv:flake8] [testenv:flake8]
deps= deps=