Commit 191ddeb1 authored by Arnaud Vergnet's avatar Arnaud Vergnet
Browse files

feat: handle errors

parent faecd8bb8159
Pipeline #118142 failed with stages
in 2 minutes and 30 seconds
......@@ -14,5 +14,7 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from typing import List, Type
from pyramid.config import Configurator
from pyramid.request import Request
......@@ -17,3 +19,13 @@
from pyramid.config import Configurator
from pyramid.request import Request
from cubicweb import (
ValidationError,
Unauthorized,
UnknownEid,
UniqueTogetherError,
ViolatedConstraint,
QueryError,
Forbidden,
)
from rql import RQLSyntaxError
......@@ -19,5 +31,5 @@
from cubicweb_api.routes import ROUTE_NAME_TO_CONTEXT
from cubicweb_api.routes import ROUTE_NAME_TO_CONTEXT, get_route_name
class JsonApiView:
......@@ -29,7 +41,69 @@
return self.request.context.render()
class JsonApiExceptionView(JsonApiView):
status_int = 500
def __init__(self, exc: Exception, request: Request):
super().__init__(request)
self.exc = exc
def __call__(self):
self.request.response.status_int = self.status_int
return {"error": self.exc.__class__.__name__, "message": str(self.exc)}
class JsonApiBadRequestView(JsonApiExceptionView):
status_int = 400
class JsonApiUnauthorizedView(JsonApiExceptionView):
status_int = 401
class JsonApiForbiddenView(JsonApiExceptionView):
status_int = 403
def add_exception_view(
config: Configurator,
route_part: str,
exception_view: Type[JsonApiExceptionView],
exception: Type[Exception] = None,
):
config.add_exception_view(
exception_view,
route_name=get_route_name(route_part),
context=exception,
renderer="json",
)
def add_bad_request_view(
config: Configurator, route_part: str, exception: Type[Exception]
):
add_exception_view(config, route_part, JsonApiBadRequestView, exception)
def add_exception_views(config: Configurator, bad_request_routes: List[str]):
for route_part in ROUTE_NAME_TO_CONTEXT:
add_exception_view(config, route_part, JsonApiUnauthorizedView, Unauthorized)
add_exception_view(config, route_part, JsonApiForbiddenView, Forbidden)
add_exception_view(config, route_part, JsonApiExceptionView)
for route_part in bad_request_routes:
for exception_cls in (
RQLSyntaxError,
ValidationError,
UnknownEid,
UniqueTogetherError,
ViolatedConstraint,
QueryError,
):
add_bad_request_view(config, route_part, exception_cls)
def includeme(config: Configurator):
for route_part in ROUTE_NAME_TO_CONTEXT:
config.add_view(
JsonApiView,
......@@ -32,8 +106,8 @@
def includeme(config: Configurator):
for route_part in ROUTE_NAME_TO_CONTEXT:
config.add_view(
JsonApiView,
route_name=f"v1_{route_part}",
route_name=get_route_name(route_part),
renderer="json",
require_csrf=False,
)
......@@ -37,3 +111,4 @@
renderer="json",
require_csrf=False,
)
add_exception_views(config, ["transaction", "rql"])
......@@ -104,7 +104,15 @@
}
def get_route_name(route_part: str):
return f"v1_{route_part}"
def get_route_pattern(route_part: str):
return rf"/api/v1/{route_part}"
def includeme(config: Configurator):
repo = config.registry["cubicweb.repository"]
repo.api_transactions = ApiTransactionsRepository(repo)
for route_part, context in ROUTE_NAME_TO_CONTEXT.items():
......@@ -107,5 +115,7 @@
def includeme(config: Configurator):
repo = config.registry["cubicweb.repository"]
repo.api_transactions = ApiTransactionsRepository(repo)
for route_part, context in ROUTE_NAME_TO_CONTEXT.items():
config.add_route(f"v1_{route_part}", rf"/api/v1/{route_part}", factory=context)
config.add_route(
get_route_name(route_part), get_route_pattern(route_part), factory=context
)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment