Merge pull request #398 from seemethere/fix_errors_from_content_range
Fixes errors related to #378
This commit is contained in:
commit
7401facc21
|
@ -97,6 +97,7 @@ INTERNAL_SERVER_ERROR_HTML = '''
|
||||||
|
|
||||||
|
|
||||||
class SanicException(Exception):
|
class SanicException(Exception):
|
||||||
|
|
||||||
def __init__(self, message, status_code=None):
|
def __init__(self, message, status_code=None):
|
||||||
super().__init__(message)
|
super().__init__(message)
|
||||||
|
|
||||||
|
@ -154,87 +155,3 @@ class ContentRangeError(SanicException):
|
||||||
|
|
||||||
class InvalidRangeType(ContentRangeError):
|
class InvalidRangeType(ContentRangeError):
|
||||||
pass
|
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 .config import Config
|
||||||
from .constants import HTTP_METHODS
|
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 .log import log
|
||||||
from .response import HTTPResponse
|
from .response import HTTPResponse
|
||||||
from .router import Router
|
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')
|
@exception_handler_app.route('/5')
|
||||||
def handler_5(request):
|
def handler_5(request):
|
||||||
class CustomServerError(ServerError):
|
class CustomServerError(ServerError):
|
||||||
pass
|
status_code=200
|
||||||
raise CustomServerError('Custom server error')
|
raise CustomServerError('Custom server error')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import signal
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from sanic import Sanic
|
from sanic import Sanic
|
||||||
|
from sanic.utils import HOST, PORT
|
||||||
|
|
||||||
AVAILABLE_LISTENERS = [
|
AVAILABLE_LISTENERS = [
|
||||||
'before_start',
|
'before_start',
|
||||||
|
@ -30,7 +31,7 @@ def start_stop_app(random_name_app, **run_kwargs):
|
||||||
signal.signal(signal.SIGALRM, stop_on_alarm)
|
signal.signal(signal.SIGALRM, stop_on_alarm)
|
||||||
signal.alarm(1)
|
signal.alarm(1)
|
||||||
try:
|
try:
|
||||||
random_name_app.run(**run_kwargs)
|
random_name_app.run(HOST, PORT, **run_kwargs)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,9 @@ def test_static_directory(file_name, base_uri, static_file_directory):
|
||||||
assert response.status == 200
|
assert response.status == 200
|
||||||
assert response.body == get_file_content(static_file_directory, file_name)
|
assert response.body == get_file_content(static_file_directory, file_name)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||||
def test_static_head_request(
|
def test_static_head_request(file_name, static_file_directory):
|
||||||
file_name, static_file_content, static_file_directory):
|
|
||||||
app = Sanic('test_static')
|
app = Sanic('test_static')
|
||||||
app.static(
|
app.static(
|
||||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
@ -62,11 +62,13 @@ def test_static_head_request(
|
||||||
assert response.status == 200
|
assert response.status == 200
|
||||||
assert 'Accept-Ranges' in response.headers
|
assert 'Accept-Ranges' in response.headers
|
||||||
assert 'Content-Length' 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'])
|
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||||
def test_static_content_range_correct(
|
def test_static_content_range_correct(file_name, static_file_directory):
|
||||||
file_name, static_file_content, static_file_directory):
|
|
||||||
app = Sanic('test_static')
|
app = Sanic('test_static')
|
||||||
app.static(
|
app.static(
|
||||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
@ -80,13 +82,15 @@ def test_static_content_range_correct(
|
||||||
assert response.status == 200
|
assert response.status == 200
|
||||||
assert 'Content-Length' in response.headers
|
assert 'Content-Length' in response.headers
|
||||||
assert 'Content-Range' in response.headers
|
assert 'Content-Range' in response.headers
|
||||||
static_content = bytes(get_file_content(static_file_directory, file_name))[12:19]
|
static_content = bytes(get_file_content(
|
||||||
assert int(response.headers['Content-Length']) == len(get_file_content(static_file_directory, file_name))
|
static_file_directory, file_name))[12:19]
|
||||||
assert response.body == get_file_content(static_file_directory, file_name)
|
assert int(response.headers[
|
||||||
|
'Content-Length']) == len(static_content)
|
||||||
|
assert response.body == static_content
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||||
def test_static_content_range_front(
|
def test_static_content_range_front(file_name, static_file_directory):
|
||||||
file_name, static_file_content, static_file_directory):
|
|
||||||
app = Sanic('test_static')
|
app = Sanic('test_static')
|
||||||
app.static(
|
app.static(
|
||||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
@ -100,14 +104,15 @@ def test_static_content_range_front(
|
||||||
assert response.status == 200
|
assert response.status == 200
|
||||||
assert 'Content-Length' in response.headers
|
assert 'Content-Length' in response.headers
|
||||||
assert 'Content-Range' in response.headers
|
assert 'Content-Range' in response.headers
|
||||||
static_content = bytes(get_file_content(static_file_directory, file_name))[12:]
|
static_content = bytes(get_file_content(
|
||||||
assert int(response.headers['Content-Length']) == len(get_file_content(static_file_directory, file_name))
|
static_file_directory, file_name))[12:]
|
||||||
assert response.body == get_file_content(static_file_directory, file_name)
|
assert int(response.headers[
|
||||||
|
'Content-Length']) == len(static_content)
|
||||||
|
assert response.body == static_content
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||||
def test_static_content_range_back(
|
def test_static_content_range_back(file_name, static_file_directory):
|
||||||
file_name, static_file_content, static_file_directory):
|
|
||||||
app = Sanic('test_static')
|
app = Sanic('test_static')
|
||||||
app.static(
|
app.static(
|
||||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
@ -121,13 +126,15 @@ def test_static_content_range_back(
|
||||||
assert response.status == 200
|
assert response.status == 200
|
||||||
assert 'Content-Length' in response.headers
|
assert 'Content-Length' in response.headers
|
||||||
assert 'Content-Range' in response.headers
|
assert 'Content-Range' in response.headers
|
||||||
static_content = bytes(get_file_content(static_file_directory, file_name))[-12:]
|
static_content = bytes(get_file_content(
|
||||||
assert int(response.headers['Content-Length']) == len(get_file_content(static_file_directory, file_name))
|
static_file_directory, file_name))[-12:]
|
||||||
assert response.body == get_file_content(static_file_directory, file_name)
|
assert int(response.headers[
|
||||||
|
'Content-Length']) == len(static_content)
|
||||||
|
assert response.body == static_content
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
@pytest.mark.parametrize('file_name', ['test.file', 'decode me.txt'])
|
||||||
def test_static_content_range_empty(
|
def test_static_content_range_empty(file_name, static_file_directory):
|
||||||
file_name, static_file_content, static_file_directory):
|
|
||||||
app = Sanic('test_static')
|
app = Sanic('test_static')
|
||||||
app.static(
|
app.static(
|
||||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
@ -137,11 +144,14 @@ def test_static_content_range_empty(
|
||||||
assert response.status == 200
|
assert response.status == 200
|
||||||
assert 'Content-Length' in response.headers
|
assert 'Content-Length' in response.headers
|
||||||
assert 'Content-Range' not 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 int(response.headers[
|
||||||
assert response.body == bytes(get_file_content(static_file_directory, file_name))
|
'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'])
|
@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 = Sanic('test_static')
|
||||||
app.static(
|
app.static(
|
||||||
'/testing.file', get_file_path(static_file_directory, file_name),
|
'/testing.file', get_file_path(static_file_directory, file_name),
|
||||||
|
@ -156,4 +166,4 @@ def test_static_content_range_error(static_file_path, static_file_content):
|
||||||
assert 'Content-Length' in response.headers
|
assert 'Content-Length' in response.headers
|
||||||
assert 'Content-Range' in response.headers
|
assert 'Content-Range' in response.headers
|
||||||
assert response.headers['Content-Range'] == "bytes */%s" % (
|
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