Fixes errors related to #378
This commit is contained in:
parent
4f856e8783
commit
579afe012b
|
@ -97,6 +97,7 @@ INTERNAL_SERVER_ERROR_HTML = '''
|
|||
|
||||
|
||||
class SanicException(Exception):
|
||||
|
||||
def __init__(self, message, status_code=None):
|
||||
super().__init__(message)
|
||||
|
||||
|
@ -136,7 +137,7 @@ class RequestTimeout(SanicException):
|
|||
class PayloadTooLarge(SanicException):
|
||||
status_code = 413
|
||||
|
||||
|
||||
|
||||
class HeaderNotFound(SanicException):
|
||||
status_code = 400
|
||||
|
||||
|
@ -154,87 +155,3 @@ class ContentRangeError(SanicException):
|
|||
|
||||
class InvalidRangeType(ContentRangeError):
|
||||
pass
|
||||
|
||||
|
||||
class Handler:
|
||||
handlers = None
|
||||
cached_handlers = None
|
||||
_missing = object()
|
||||
|
||||
def __init__(self):
|
||||
self.handlers = []
|
||||
self.cached_handlers = {}
|
||||
self.debug = False
|
||||
|
||||
def _render_traceback_html(self, exception, request):
|
||||
exc_type, exc_value, tb = sys.exc_info()
|
||||
frames = extract_tb(tb)
|
||||
|
||||
frame_html = []
|
||||
for frame in frames:
|
||||
frame_html.append(TRACEBACK_LINE_HTML.format(frame))
|
||||
|
||||
return TRACEBACK_WRAPPER_HTML.format(
|
||||
style=TRACEBACK_STYLE,
|
||||
exc_name=exc_type.__name__,
|
||||
exc_value=exc_value,
|
||||
frame_html=''.join(frame_html),
|
||||
uri=request.url)
|
||||
|
||||
def add(self, exception, handler):
|
||||
self.handlers.append((exception, handler))
|
||||
|
||||
def lookup(self, exception):
|
||||
handler = self.cached_handlers.get(exception, self._missing)
|
||||
if handler is self._missing:
|
||||
for exception_class, handler in self.handlers:
|
||||
if isinstance(exception, exception_class):
|
||||
self.cached_handlers[type(exception)] = handler
|
||||
return handler
|
||||
self.cached_handlers[type(exception)] = None
|
||||
handler = None
|
||||
return handler
|
||||
|
||||
def response(self, request, exception):
|
||||
"""
|
||||
Fetches and executes an exception handler and returns a response object
|
||||
|
||||
:param request: Request
|
||||
:param exception: Exception to handle
|
||||
:return: Response object
|
||||
"""
|
||||
handler = self.lookup(exception)
|
||||
try:
|
||||
response = handler and handler(
|
||||
request=request, exception=exception)
|
||||
if response is None:
|
||||
response = self.default(request=request, exception=exception)
|
||||
except:
|
||||
log.error(format_exc())
|
||||
if self.debug:
|
||||
response_message = (
|
||||
'Exception raised in exception handler "{}" '
|
||||
'for uri: "{}"\n{}').format(
|
||||
handler.__name__, request.url, format_exc())
|
||||
log.error(response_message)
|
||||
return text(response_message, 500)
|
||||
else:
|
||||
return text('An error occurred while handling an error', 500)
|
||||
return response
|
||||
|
||||
def default(self, request, exception):
|
||||
log.error(format_exc())
|
||||
if isinstance(exception, SanicException):
|
||||
return text(
|
||||
'Error: {}'.format(exception),
|
||||
status=getattr(exception, 'status_code', 500))
|
||||
elif self.debug:
|
||||
html_output = self._render_traceback_html(exception, request)
|
||||
|
||||
response_message = (
|
||||
'Exception occurred while handling uri: "{}"\n{}'.format(
|
||||
request.url, format_exc()))
|
||||
log.error(response_message)
|
||||
return html(html_output, status=500)
|
||||
else:
|
||||
return html(INTERNAL_SERVER_ERROR_HTML, status=500)
|
||||
|
|
|
@ -10,7 +10,8 @@ from urllib.parse import urlencode, urlunparse
|
|||
|
||||
from .config import Config
|
||||
from .constants import HTTP_METHODS
|
||||
from .exceptions import Handler, ServerError, URLBuildError
|
||||
from .handlers import ErrorHandler
|
||||
from .exceptions import ServerError, URLBuildError
|
||||
from .log import log
|
||||
from .response import HTTPResponse
|
||||
from .router import Router
|
||||
|
|
|
@ -1 +1 @@
|
|||
I need to be decoded as a uri
|
||||
I am just a regular static file that needs to have its uri decoded
|
||||
|
|
|
@ -31,7 +31,7 @@ def handler_4(request):
|
|||
@exception_handler_app.route('/5')
|
||||
def handler_5(request):
|
||||
class CustomServerError(ServerError):
|
||||
pass
|
||||
status_code=200
|
||||
raise CustomServerError('Custom server error')
|
||||
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import signal
|
|||
import pytest
|
||||
|
||||
from sanic import Sanic
|
||||
from sanic.utils import HOST, PORT
|
||||
|
||||
AVAILABLE_LISTENERS = [
|
||||
'before_start',
|
||||
|
@ -30,7 +31,7 @@ def start_stop_app(random_name_app, **run_kwargs):
|
|||
signal.signal(signal.SIGALRM, stop_on_alarm)
|
||||
signal.alarm(1)
|
||||
try:
|
||||
random_name_app.run(**run_kwargs)
|
||||
random_name_app.run(HOST, PORT, **run_kwargs)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
|
|
|
@ -49,12 +49,12 @@ def test_static_directory(file_name, base_uri, static_file_directory):
|
|||
assert response.status == 200
|
||||
assert response.body == get_file_content(static_file_directory, file_name)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||
def test_static_head_request(
|
||||
file_name, static_file_content, static_file_directory):
|
||||
def test_static_head_request(file_name, static_file_directory):
|
||||
app = Sanic('test_static')
|
||||
app.static(
|
||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||
use_content_range=True)
|
||||
|
||||
request, response = sanic_endpoint_test(
|
||||
|
@ -62,14 +62,16 @@ def test_static_head_request(
|
|||
assert response.status == 200
|
||||
assert 'Accept-Ranges' in response.headers
|
||||
assert 'Content-Length' in response.headers
|
||||
assert int(response.headers['Content-Length']) == len(get_file_content(static_file_directory, file_name))
|
||||
assert int(response.headers[
|
||||
'Content-Length']) == len(
|
||||
get_file_content(static_file_directory, file_name))
|
||||
|
||||
|
||||
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||
def test_static_content_range_correct(
|
||||
file_name, static_file_content, static_file_directory):
|
||||
def test_static_content_range_correct(file_name, static_file_directory):
|
||||
app = Sanic('test_static')
|
||||
app.static(
|
||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||
use_content_range=True)
|
||||
|
||||
headers = {
|
||||
|
@ -80,16 +82,18 @@ def test_static_content_range_correct(
|
|||
assert response.status == 200
|
||||
assert 'Content-Length' in response.headers
|
||||
assert 'Content-Range' in response.headers
|
||||
static_content = bytes(get_file_content(static_file_directory, file_name))[12:19]
|
||||
assert int(response.headers['Content-Length']) == len(get_file_content(static_file_directory, file_name))
|
||||
assert response.body == get_file_content(static_file_directory, file_name)
|
||||
static_content = bytes(get_file_content(
|
||||
static_file_directory, file_name))[12:19]
|
||||
assert int(response.headers[
|
||||
'Content-Length']) == len(static_content)
|
||||
assert response.body == static_content
|
||||
|
||||
|
||||
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||
def test_static_content_range_front(
|
||||
file_name, static_file_content, static_file_directory):
|
||||
def test_static_content_range_front(file_name, static_file_directory):
|
||||
app = Sanic('test_static')
|
||||
app.static(
|
||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||
use_content_range=True)
|
||||
|
||||
headers = {
|
||||
|
@ -100,19 +104,20 @@ def test_static_content_range_front(
|
|||
assert response.status == 200
|
||||
assert 'Content-Length' in response.headers
|
||||
assert 'Content-Range' in response.headers
|
||||
static_content = bytes(get_file_content(static_file_directory, file_name))[12:]
|
||||
assert int(response.headers['Content-Length']) == len(get_file_content(static_file_directory, file_name))
|
||||
assert response.body == get_file_content(static_file_directory, file_name)
|
||||
static_content = bytes(get_file_content(
|
||||
static_file_directory, file_name))[12:]
|
||||
assert int(response.headers[
|
||||
'Content-Length']) == len(static_content)
|
||||
assert response.body == static_content
|
||||
|
||||
|
||||
|
||||
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||
def test_static_content_range_back(
|
||||
file_name, static_file_content, static_file_directory):
|
||||
def test_static_content_range_back(file_name, static_file_directory):
|
||||
app = Sanic('test_static')
|
||||
app.static(
|
||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||
use_content_range=True)
|
||||
|
||||
|
||||
headers = {
|
||||
'Range': 'bytes=-12'
|
||||
}
|
||||
|
@ -121,30 +126,35 @@ def test_static_content_range_back(
|
|||
assert response.status == 200
|
||||
assert 'Content-Length' in response.headers
|
||||
assert 'Content-Range' in response.headers
|
||||
static_content = bytes(get_file_content(static_file_directory, file_name))[-12:]
|
||||
assert int(response.headers['Content-Length']) == len(get_file_content(static_file_directory, file_name))
|
||||
assert response.body == get_file_content(static_file_directory, file_name)
|
||||
static_content = bytes(get_file_content(
|
||||
static_file_directory, file_name))[-12:]
|
||||
assert int(response.headers[
|
||||
'Content-Length']) == len(static_content)
|
||||
assert response.body == static_content
|
||||
|
||||
|
||||
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||
def test_static_content_range_empty(
|
||||
file_name, static_file_content, static_file_directory):
|
||||
def test_static_content_range_empty(file_name, static_file_directory):
|
||||
app = Sanic('test_static')
|
||||
app.static(
|
||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||
use_content_range=True)
|
||||
|
||||
request, response = sanic_endpoint_test(app, uri='/testing.file')
|
||||
assert response.status == 200
|
||||
assert 'Content-Length' in response.headers
|
||||
assert 'Content-Range' not in response.headers
|
||||
assert int(response.headers['Content-Length']) == len(get_file_content(static_file_directory, file_name))
|
||||
assert response.body == bytes(get_file_content(static_file_directory, file_name))
|
||||
assert int(response.headers[
|
||||
'Content-Length']) == len(get_file_content(static_file_directory, file_name))
|
||||
assert response.body == bytes(
|
||||
get_file_content(static_file_directory, file_name))
|
||||
|
||||
|
||||
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||
def test_static_content_range_error(static_file_path, static_file_content):
|
||||
def test_static_content_range_error(file_name, static_file_directory):
|
||||
app = Sanic('test_static')
|
||||
app.static(
|
||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||
use_content_range=True)
|
||||
|
||||
headers = {
|
||||
|
@ -156,4 +166,4 @@ def test_static_content_range_error(static_file_path, static_file_content):
|
|||
assert 'Content-Length' in response.headers
|
||||
assert 'Content-Range' in response.headers
|
||||
assert response.headers['Content-Range'] == "bytes */%s" % (
|
||||
len(static_file_content),)
|
||||
len(get_file_content(static_file_directory, file_name)),)
|
||||
|
|
Loading…
Reference in New Issue
Block a user