From 06792bdd9252bb09ace98513e4cd4f4b7e3bdd01 Mon Sep 17 00:00:00 2001 From: Gareth Coles Date: Sun, 18 Feb 2018 17:28:10 +0000 Subject: Error handlers can now handle more than one HTTP status code --- pysite/base_route.py | 24 ++++++++++++++++++++---- pysite/views/main/error_handlers/http_5xx.py | 12 ++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 pysite/views/main/error_handlers/http_5xx.py (limited to 'pysite') diff --git a/pysite/base_route.py b/pysite/base_route.py index 34c16f8a..5c01bbb9 100644 --- a/pysite/base_route.py +++ b/pysite/base_route.py @@ -2,6 +2,7 @@ import os import random import string +from collections import Iterable from flask import Blueprint, jsonify, render_template from flask.views import MethodView @@ -129,13 +130,18 @@ class ErrorView(BaseView): >>> class MyView(ErrorView): ... name = "my_view" # Flask internal name for this route ... path = "/my_view" # Actual URL path to reach this route - ... error_code = 404 + ... error_code = 404 # Error code ... - ... def get(self): # Name your function after the relevant HTTP method + ... def get(self, error: HTTPException): # Name your function after the relevant HTTP method ... return "Replace me with a template, 404 not found", 404 + + If you'd like to catch multiple HTTP error codes, feel free to supply an iterable for `error_code`. For example... + + >>> error_code = [401, 403] # Handle two specific errors + >>> error_code = range(500, 600) # Handle all 5xx errors """ - error_code = None # type: int + error_code = None # type: Union[int, Iterable] @classmethod def setup(cls: "ErrorView", manager: "pysite.route_manager.RouteManager", blueprint: Blueprint): @@ -153,4 +159,14 @@ class ErrorView(BaseView): if not cls.name or not cls.error_code: raise RuntimeError("Error views must have both `name` and `error_code` defined") - manager.app.errorhandler(cls.error_code)(cls.as_view(cls.name)) + if isinstance(cls.error_code, int): + cls.error_code = [cls.error_code] + + if isinstance(cls.error_code, Iterable): + for code in cls.error_code: + try: + manager.app.errorhandler(code)(cls.as_view(cls.name)) + except KeyError: # This happens if we try to register a handler for a HTTP code that doesn't exist + pass + else: + raise RuntimeError("Error views must have an `error_code` that is either an `int` or an iterable") diff --git a/pysite/views/main/error_handlers/http_5xx.py b/pysite/views/main/error_handlers/http_5xx.py new file mode 100644 index 00000000..ed4d8d82 --- /dev/null +++ b/pysite/views/main/error_handlers/http_5xx.py @@ -0,0 +1,12 @@ +# coding=utf-8 +from werkzeug.exceptions import HTTPException + +from pysite.base_route import ErrorView + + +class Error404View(ErrorView): + name = "error_5xx" + error_code = range(500, 600) + + def get(self, error: HTTPException): + return "Internal server error. Please try again later!", error.code -- cgit v1.2.3