192 lines
5.9 KiB
Python
192 lines
5.9 KiB
Python
import pytest
|
|
from bs4 import BeautifulSoup
|
|
|
|
from sanic import Sanic
|
|
from sanic.response import text
|
|
from sanic.exceptions import InvalidUsage, ServerError, NotFound, Unauthorized
|
|
from sanic.exceptions import Forbidden, abort
|
|
|
|
|
|
class SanicExceptionTestException(Exception):
|
|
pass
|
|
|
|
|
|
@pytest.fixture(scope='module')
|
|
def exception_app():
|
|
app = Sanic('test_exceptions')
|
|
|
|
@app.route('/')
|
|
def handler(request):
|
|
return text('OK')
|
|
|
|
@app.route('/error')
|
|
def handler_error(request):
|
|
raise ServerError("OK")
|
|
|
|
@app.route('/404')
|
|
def handler_404(request):
|
|
raise NotFound("OK")
|
|
|
|
@app.route('/403')
|
|
def handler_403(request):
|
|
raise Forbidden("Forbidden")
|
|
|
|
@app.route('/401/basic')
|
|
def handler_401_basic(request):
|
|
raise Unauthorized("Unauthorized", "Basic", {"realm": "Sanic"})
|
|
|
|
@app.route('/401/digest')
|
|
def handler_401_digest(request):
|
|
challenge = {
|
|
"realm": "Sanic",
|
|
"qop": "auth, auth-int",
|
|
"algorithm": "MD5",
|
|
"nonce": "abcdef",
|
|
"opaque": "zyxwvu",
|
|
}
|
|
raise Unauthorized("Unauthorized", "Digest", challenge)
|
|
|
|
@app.route('/401/bearer')
|
|
def handler_401_bearer(request):
|
|
raise Unauthorized("Unauthorized", "Bearer")
|
|
|
|
@app.route('/invalid')
|
|
def handler_invalid(request):
|
|
raise InvalidUsage("OK")
|
|
|
|
@app.route('/abort')
|
|
def handler_invalid(request):
|
|
abort(500)
|
|
return text("OK")
|
|
|
|
@app.route('/divide_by_zero')
|
|
def handle_unhandled_exception(request):
|
|
1 / 0
|
|
|
|
@app.route('/error_in_error_handler_handler')
|
|
def custom_error_handler(request):
|
|
raise SanicExceptionTestException('Dummy message!')
|
|
|
|
@app.exception(SanicExceptionTestException)
|
|
def error_in_error_handler_handler(request, exception):
|
|
1 / 0
|
|
|
|
return app
|
|
|
|
|
|
def test_catch_exception_list():
|
|
app = Sanic('exception_list')
|
|
|
|
@app.exception([SanicExceptionTestException, NotFound])
|
|
def exception_list(request, exception):
|
|
return text("ok")
|
|
|
|
@app.route('/')
|
|
def exception(request):
|
|
raise SanicExceptionTestException("You won't see me")
|
|
|
|
request, response = app.test_client.get('/random')
|
|
assert response.text == 'ok'
|
|
|
|
request, response = app.test_client.get('/')
|
|
assert response.text == 'ok'
|
|
|
|
|
|
def test_no_exception(exception_app):
|
|
"""Test that a route works without an exception"""
|
|
request, response = exception_app.test_client.get('/')
|
|
assert response.status == 200
|
|
assert response.text == 'OK'
|
|
|
|
|
|
def test_server_error_exception(exception_app):
|
|
"""Test the built-in ServerError exception works"""
|
|
request, response = exception_app.test_client.get('/error')
|
|
assert response.status == 500
|
|
|
|
|
|
def test_invalid_usage_exception(exception_app):
|
|
"""Test the built-in InvalidUsage exception works"""
|
|
request, response = exception_app.test_client.get('/invalid')
|
|
assert response.status == 400
|
|
|
|
|
|
def test_not_found_exception(exception_app):
|
|
"""Test the built-in NotFound exception works"""
|
|
request, response = exception_app.test_client.get('/404')
|
|
assert response.status == 404
|
|
|
|
|
|
def test_forbidden_exception(exception_app):
|
|
"""Test the built-in Forbidden exception"""
|
|
request, response = exception_app.test_client.get('/403')
|
|
assert response.status == 403
|
|
|
|
|
|
def test_unauthorized_exception(exception_app):
|
|
"""Test the built-in Unauthorized exception"""
|
|
request, response = exception_app.test_client.get('/401/basic')
|
|
assert response.status == 401
|
|
assert response.headers.get('WWW-Authenticate') is not None
|
|
assert response.headers.get('WWW-Authenticate') == "Basic realm='Sanic'"
|
|
|
|
request, response = exception_app.test_client.get('/401/digest')
|
|
assert response.status == 401
|
|
|
|
auth_header = response.headers.get('WWW-Authenticate')
|
|
assert auth_header is not None
|
|
assert auth_header.startswith('Digest')
|
|
assert "qop='auth, auth-int'" in auth_header
|
|
assert "algorithm='MD5'" in auth_header
|
|
assert "nonce='abcdef'" in auth_header
|
|
assert "opaque='zyxwvu'" in auth_header
|
|
|
|
request, response = exception_app.test_client.get('/401/bearer')
|
|
assert response.status == 401
|
|
assert response.headers.get('WWW-Authenticate') == "Bearer"
|
|
|
|
|
|
def test_handled_unhandled_exception(exception_app):
|
|
"""Test that an exception not built into sanic is handled"""
|
|
request, response = exception_app.test_client.get('/divide_by_zero')
|
|
assert response.status == 500
|
|
soup = BeautifulSoup(response.body, 'html.parser')
|
|
assert soup.h1.text == 'Internal Server Error'
|
|
|
|
message = " ".join(soup.p.text.split())
|
|
assert message == (
|
|
"The server encountered an internal error and "
|
|
"cannot complete your request.")
|
|
|
|
|
|
def test_exception_in_exception_handler(exception_app):
|
|
"""Test that an exception thrown in an error handler is handled"""
|
|
request, response = exception_app.test_client.get(
|
|
'/error_in_error_handler_handler')
|
|
assert response.status == 500
|
|
assert response.body == b'An error occurred while handling an error'
|
|
|
|
|
|
def test_exception_in_exception_handler_debug_off(exception_app):
|
|
"""Test that an exception thrown in an error handler is handled"""
|
|
request, response = exception_app.test_client.get(
|
|
'/error_in_error_handler_handler',
|
|
debug=False)
|
|
assert response.status == 500
|
|
assert response.body == b'An error occurred while handling an error'
|
|
|
|
|
|
def test_exception_in_exception_handler_debug_off(exception_app):
|
|
"""Test that an exception thrown in an error handler is handled"""
|
|
request, response = exception_app.test_client.get(
|
|
'/error_in_error_handler_handler',
|
|
debug=True)
|
|
assert response.status == 500
|
|
assert response.body.startswith(b'Exception raised in exception ')
|
|
|
|
|
|
def test_abort(exception_app):
|
|
"""Test the abort function"""
|
|
request, response = exception_app.test_client.get('/abort')
|
|
assert response.status == 500
|