# Web Errors v0.6.10
[![image](https://img.shields.io/pypi/v/web_error.svg)](https://pypi.org/project/web_error/)
[![image](https://img.shields.io/pypi/l/web_error.svg)](https://pypi.org/project/web_error/)
[![image](https://img.shields.io/pypi/pyversions/web_error.svg)](https://pypi.org/project/web_error/)
![style](https://github.com/NRWLDev/web-error/actions/workflows/style.yml/badge.svg)
![tests](https://github.com/NRWLDev/web-error/actions/workflows/tests.yml/badge.svg)
[![codecov](https://codecov.io/gh/NRWLDev/web-error/branch/main/graph/badge.svg)](https://codecov.io/gh/NRWLDev/web-error)
`web_error` is a set of exceptions and handlers for use in starlette/fastapi
applications to support easy error management and responses
Each exception easily marshals to JSON based on the
[RFC9457](https://www.rfc-editor.org/rfc/rfc9457.html) spec for use in api
errors.
## Migrating to 0.6 (RFC9457 support)
Check the discussion [here](github.com/EdgyEdgemond/web-error/discussions/22)
for details on how to update usage to maintain legacy functionality or move over
to problem details support.
## Errors
The base `web_error.error.HttpException` accepts a `title`, `details`, `status`
(default 500) and optional `**kwargs`. An additional `code` can be passed in,
which will be used as the `type`, if not provided the `type` is derived from
the class name.
And will return a JSON response with `exc.status` as the status code and response body:
```json
{
"type": "an-exception",
"title": "title",
"details": "details",
"status": 500,
"extra-key": "extra-value",
...
}
```
Derived types are generated using the class name after dropping `...Error` from
the end, and converting to `kebab-case`. i.e. `PascalCaseError` will derive the
type `pascal-case`. If the class name doesn't suit your purposes, an optional
`code` attribute can be set with the desired value of there response `type`
field.
Some convenience Exceptions are provided with predefined `status` attributes.
To create custom errors subclasss these and define the `title` attribute.
* `web_error.error.ServerException` provides status 500 errors
* `web_error.error.BadRequestException` provides status 400 errors
* `web_error.error.UnauthorisedException` provides status 401 errors
* `web_error.error.NotFoundException` provides status 404 errors
### Custom Errors
Subclassing the convenience classes provide a simple way to consistently raise the same error
with details/extras changing based on the raised context.
```python
from web_error.error import NotFoundException
class UserNotFoundError(NotFoundException):
title = "User not found."
raise UserNotFoundError(details="details")
```
```json
{
"type": "user-not-found",
"title": "User not found",
"details": "details",
"status": 404,
}
```
Whereas a defined `code` will be used in the output.
```python
class UserNotFoundError(NotFoundException):
title = "User not found."
code = "cant-find-user"
raise UserNotFoundError(details="details")
```
```json
{
"type": "cant-find-user",
"title": "User not found",
"details": "details",
"status": 404,
}
```
If additional kwargs are provided when the error is raised, they will be
included in the output (ensure the provided values are json seriablizable.
```python
raise UserNotFoundError(details="details", user_id="1234", metadata={"hello": "world"})
```
```json
{
...
"details": "details",
"user_id": "1234",
"metadata": {"hello": "world"},
}
```
## Starlette
```python
import starlette.applications
import web_error.handler.starlette
app = starlette.applications.Starlette()
web_error.handler.starlette.add_exception_handler(app)
```
A custom logger can be provided to `add_exception_handler(app, logger=...)`.
If you require cors headers, you can pass a `web_error.cors.CorsConfiguration`
instance to `add_exception_handler(cors=...)`.
```python
add_exception_handler(
app,
cors=CorsConfiguration(
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
allow_credentials=True,
)
)
```
To handle unexpected errors provide `unhandled_wrappers`, a dict mapping http
status code to `HttpCodeException`, the system key `default` is also accepted
as the root wrapper for all unhandled exceptions.
If you wish to hide debug messaging from external users, `strip_debug=True`
will log the debug message and remove it from the response.
```python
from web_error.error import HttpCodeException
class NotFoundError(HttpCodeException):
status = 404
message = "Endpoint not found."
web_error.handler.starlette.add_exception_handler(
app,
unhandled_wrappers={
"404": NotFoundError,
},
)
```
## FastAPI
The FastAPI handler is identical to the starlette handler with the additional
handling of `RequestValidationError`.
```python
import fastapi
import web_error.handler.fastapi
app = fastapi.FastAPI()
web_error.handler.fastapi.add_exception_handler(app)
```
Raw data
{
"_id": null,
"home_page": "https://github.com/EdgyEdgemond/web-error/",
"name": "web_error",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.9",
"maintainer_email": null,
"keywords": null,
"author": "Daniel Edgecombe",
"author_email": "edgy.edgemond@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/f5/48/337db1b2ef1553bd892eb70f44a1b164a1ab79cf7a5ec2e38695b202d4b0/web_error-0.6.10.tar.gz",
"platform": null,
"description": "# Web Errors v0.6.10\n[![image](https://img.shields.io/pypi/v/web_error.svg)](https://pypi.org/project/web_error/)\n[![image](https://img.shields.io/pypi/l/web_error.svg)](https://pypi.org/project/web_error/)\n[![image](https://img.shields.io/pypi/pyversions/web_error.svg)](https://pypi.org/project/web_error/)\n![style](https://github.com/NRWLDev/web-error/actions/workflows/style.yml/badge.svg)\n![tests](https://github.com/NRWLDev/web-error/actions/workflows/tests.yml/badge.svg)\n[![codecov](https://codecov.io/gh/NRWLDev/web-error/branch/main/graph/badge.svg)](https://codecov.io/gh/NRWLDev/web-error)\n\n`web_error` is a set of exceptions and handlers for use in starlette/fastapi\napplications to support easy error management and responses\n\nEach exception easily marshals to JSON based on the\n[RFC9457](https://www.rfc-editor.org/rfc/rfc9457.html) spec for use in api\nerrors.\n\n## Migrating to 0.6 (RFC9457 support)\n\nCheck the discussion [here](github.com/EdgyEdgemond/web-error/discussions/22)\nfor details on how to update usage to maintain legacy functionality or move over\nto problem details support.\n\n## Errors\n\nThe base `web_error.error.HttpException` accepts a `title`, `details`, `status`\n(default 500) and optional `**kwargs`. An additional `code` can be passed in,\nwhich will be used as the `type`, if not provided the `type` is derived from\nthe class name.\n\nAnd will return a JSON response with `exc.status` as the status code and response body:\n\n```json\n{\n \"type\": \"an-exception\",\n \"title\": \"title\",\n \"details\": \"details\",\n \"status\": 500,\n \"extra-key\": \"extra-value\",\n ...\n}\n```\n\nDerived types are generated using the class name after dropping `...Error` from\nthe end, and converting to `kebab-case`. i.e. `PascalCaseError` will derive the\ntype `pascal-case`. If the class name doesn't suit your purposes, an optional\n`code` attribute can be set with the desired value of there response `type`\nfield.\n\nSome convenience Exceptions are provided with predefined `status` attributes.\nTo create custom errors subclasss these and define the `title` attribute.\n\n* `web_error.error.ServerException` provides status 500 errors\n* `web_error.error.BadRequestException` provides status 400 errors\n* `web_error.error.UnauthorisedException` provides status 401 errors\n* `web_error.error.NotFoundException` provides status 404 errors\n\n### Custom Errors\n\nSubclassing the convenience classes provide a simple way to consistently raise the same error\nwith details/extras changing based on the raised context.\n\n```python\nfrom web_error.error import NotFoundException\n\n\nclass UserNotFoundError(NotFoundException):\n title = \"User not found.\"\n\nraise UserNotFoundError(details=\"details\")\n```\n\n```json\n{\n \"type\": \"user-not-found\",\n \"title\": \"User not found\",\n \"details\": \"details\",\n \"status\": 404,\n}\n```\n\nWhereas a defined `code` will be used in the output.\n\n```python\nclass UserNotFoundError(NotFoundException):\n title = \"User not found.\"\n code = \"cant-find-user\"\n\nraise UserNotFoundError(details=\"details\")\n```\n\n```json\n{\n \"type\": \"cant-find-user\",\n \"title\": \"User not found\",\n \"details\": \"details\",\n \"status\": 404,\n}\n```\n\nIf additional kwargs are provided when the error is raised, they will be\nincluded in the output (ensure the provided values are json seriablizable.\n\n\n```python\nraise UserNotFoundError(details=\"details\", user_id=\"1234\", metadata={\"hello\": \"world\"})\n```\n\n```json\n{\n ...\n \"details\": \"details\",\n \"user_id\": \"1234\",\n \"metadata\": {\"hello\": \"world\"},\n}\n```\n\n## Starlette\n\n\n```python\n import starlette.applications\n import web_error.handler.starlette\n\n app = starlette.applications.Starlette()\n\n web_error.handler.starlette.add_exception_handler(app)\n```\n\nA custom logger can be provided to `add_exception_handler(app, logger=...)`.\n\nIf you require cors headers, you can pass a `web_error.cors.CorsConfiguration`\ninstance to `add_exception_handler(cors=...)`.\n\n```python\nadd_exception_handler(\n app,\n cors=CorsConfiguration(\n allow_origins=[\"*\"],\n allow_methods=[\"*\"],\n allow_headers=[\"*\"],\n allow_credentials=True,\n )\n)\n```\n\nTo handle unexpected errors provide `unhandled_wrappers`, a dict mapping http\nstatus code to `HttpCodeException`, the system key `default` is also accepted\nas the root wrapper for all unhandled exceptions.\n\nIf you wish to hide debug messaging from external users, `strip_debug=True`\nwill log the debug message and remove it from the response.\n\n```python\n from web_error.error import HttpCodeException\n\n class NotFoundError(HttpCodeException):\n status = 404\n message = \"Endpoint not found.\"\n\n web_error.handler.starlette.add_exception_handler(\n app,\n unhandled_wrappers={\n \"404\": NotFoundError,\n },\n )\n```\n\n## FastAPI\n\nThe FastAPI handler is identical to the starlette handler with the additional\nhandling of `RequestValidationError`.\n\n```python\n import fastapi\n import web_error.handler.fastapi\n\n\n app = fastapi.FastAPI()\n web_error.handler.fastapi.add_exception_handler(app)\n```\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "Web based error utils",
"version": "0.6.10",
"project_urls": {
"Homepage": "https://github.com/EdgyEdgemond/web-error/",
"Repository": "https://github.com/EdgyEdgemond/web-error/"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "e0ef50dbb14c4ea6592dcbc729c722a472621d78f9fc342a4a703ef8093fa052",
"md5": "3164d6b6b38805d689366c23de2e4175",
"sha256": "953ea3aba751375141ec7c87e7448fc5e2389edf7c4b28e166fd4da129d0e8e9"
},
"downloads": -1,
"filename": "web_error-0.6.10-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3164d6b6b38805d689366c23de2e4175",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.9",
"size": 13100,
"upload_time": "2024-04-11T11:26:36",
"upload_time_iso_8601": "2024-04-11T11:26:36.674956Z",
"url": "https://files.pythonhosted.org/packages/e0/ef/50dbb14c4ea6592dcbc729c722a472621d78f9fc342a4a703ef8093fa052/web_error-0.6.10-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "f548337db1b2ef1553bd892eb70f44a1b164a1ab79cf7a5ec2e38695b202d4b0",
"md5": "03da053d4fe8584f0d3418edc9ecde30",
"sha256": "44bfac089644e970ebb29e5206741720d497f5ee62307d89be1c59b66e72969f"
},
"downloads": -1,
"filename": "web_error-0.6.10.tar.gz",
"has_sig": false,
"md5_digest": "03da053d4fe8584f0d3418edc9ecde30",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.9",
"size": 12154,
"upload_time": "2024-04-11T11:26:38",
"upload_time_iso_8601": "2024-04-11T11:26:38.309286Z",
"url": "https://files.pythonhosted.org/packages/f5/48/337db1b2ef1553bd892eb70f44a1b164a1ab79cf7a5ec2e38695b202d4b0/web_error-0.6.10.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-04-11 11:26:38",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "EdgyEdgemond",
"github_project": "web-error",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "web_error"
}