You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/overview/exception_handling.md
+86-93Lines changed: 86 additions & 93 deletions
Original file line number
Diff line number
Diff line change
@@ -1,29 +1,31 @@
1
1
# **Exceptions & Exception Handling**
2
-
Ellar comes with a built-in exceptions middleware, `ExceptionMiddleware`, which is responsible for processing all exceptions across
3
-
an application. When an exception is not handled by your application code, it is caught by this middleware, which
4
-
then automatically sends an appropriate user-friendly response.
2
+
Ellar includes a built-in exceptions middleware, known as `ExceptionMiddleware`, responsible for processing all exceptions
3
+
that occur within an application. When an exception goes unhandled by your application code,
4
+
it is intercepted by this middleware, which then automatically sends an appropriate, user-friendly response.
5
5
6
6
```json
7
7
{
8
8
"status_code": 403,
9
9
"detail": "Forbidden"
10
10
}
11
11
```
12
-
And based on application config `DEBUG` value, the exception is raised during is `config.DEBUG`
13
-
is True but when `config.DEBUG` a 500 error is returned as shown below:
12
+
Depending on the application's configuration and the value of `DEBUG`, the exception handling behavior differs.
13
+
When `config.DEBUG` is True, the exception that is raised is shown to the client for easy error debugging.
14
+
However, when `config.DEBUG` is False, a 500 error is returned to the client, as illustrated below:
15
+
14
16
```json
15
17
{
16
18
"statusCode": 500,
17
19
"message": "Internal server error"
18
20
}
19
21
```
20
22
21
-
Types of exceptions types managed by default:
23
+
Ellar manages various types of exceptions by default:
22
24
23
25
-**`HTTPException`**: Provided by `Starlette` to handle HTTP errors.eg. `HTTPException(status_code, detail=None, headers=None)`
24
26
-**`WebSocketException`**: Provided by `Starlette` to manage websocket errors. eg `WebSocketException(code=1008, reason=None)`
25
27
-**`RequestValidationException`**: Provided by `Pydantic` for validation of request data
26
-
-**`APIException`**: It is a type of exception for REST APIbased applications. It gives more concept to error and provides a simple interface for creating other custom exception needs in your application without having to create an extra exception handler.
28
+
-**`APIException`**: It is a type of exception designed for REST API-based applications. It offers a more conceptual approach to handling errors and provides a simple interface for creating other custom exceptions in your application without requiring an additional exception handler.
27
29
28
30
For example,
29
31
@@ -38,8 +40,8 @@ Types of exceptions types managed by default:
38
40
```
39
41
40
42
### **Built-in APIExceptions**
41
-
Ellar provides a set of standard exceptions that inherit from the base `APIException`.
42
-
These are exposed from the `ellar.common` package,and represent many of the most common HTTP exceptions:
43
+
Ellar offers a set of standard exceptions that inherit from the base `APIException`.
44
+
These exceptions are available within the `ellar.common` package and represent many of the most common HTTP exceptions:
43
45
44
46
-`AuthenticationFailed`
45
47
-`ImproperConfiguration`
@@ -51,10 +53,11 @@ These are exposed from the `ellar.common` package, and represent many of the mos
51
53
-`UnsupportedMediaType`
52
54
53
55
## **Throwing standard exceptions**
54
-
Let's use this `ServiceUnavailableException` in our previous project.
56
+
Let's use the `ServiceUnavailableException` in our previous project.
55
57
56
58
For example, in the `CarController`, we have a `get_all()` method (a `GET` route handler).
57
-
Let's assume that this route handler throws an exception for some reason. To demonstrate this, we'll hard-code it as follows:
59
+
Let's assume that this route handler throws an exception for some reason.
60
+
To demonstrate this, we'll hard-code it as follows:
58
61
59
62
```python
60
63
# project_name/apps/car/controllers.py
@@ -70,13 +73,14 @@ Now, when you visit [http://127.0.0.1/car/](http://127.0.0.1/car/){target="_blan
70
73
"detail": "Service Unavailable"
71
74
}
72
75
```
76
+
When we raise the `ServiceUnavailableException`, it produces a `JSON` response because `Ellar` has implemented
77
+
an exception handler for any `APIException` exception type. We will see how to change the default exception handler later.
78
+
79
+
Another error presentation is available on the APIException instance:
73
80
74
-
When we raise the `ServiceUnavailableException` exception type, it produces a `JSON` response because `Ellar` has implemented an exception handler for any `APIException` exception type.
75
-
We will see how to change the default exception handler later.
81
+
-`.detail`: returns the textual description of the error.
82
+
-`get_full_details()`: returns both the textual description and other information about the error.
76
83
77
-
There is another error presentation available on the `APIException` instance:
78
-
-`.detail`: returns textual description of the error.
79
-
-`get_full_details()`: returns both textual description and other information about the error.
80
84
81
85
```shell
82
86
>>> print(exc.detail)
@@ -85,16 +89,12 @@ Service Unavailable
85
89
{'detail':'Service Unavailable','code':'service_unavailable', 'description': 'The server cannot process the request due to a high load'}
86
90
```
87
91
88
-
!!!hint
89
-
You should only raise `HTTPException` and `APIException` during route function handling. Since exception manager is a
90
-
middleware and `HTTPException` raised before the `ExceptionMiddleware` will not be managed. Its advice exceptions happening
91
-
inside middleware classes should return appropriate responses directly.
92
-
93
92
94
93
## **Exception Handlers**
95
-
Exception Handlers are classes or functions that handles specific exception type response generation.
94
+
Exception Handlers are classes or functions that handles what response that is returned to the client for specific exception types.
95
+
96
+
Here is an example of an ExceptionHandler that handles `HTTPException` in the application:
96
97
97
-
Below is an example of ExceptionHandler that handles `HTTPException` in the application:
98
98
```python
99
99
import typing as t
100
100
@@ -126,15 +126,17 @@ class HTTPExceptionHandler(IExceptionHandler):
We have registered a handler for any `HTTP` exception with a `405` status code which we are returning a template `405.html` as a response.
205
+
In this code snippet, we've registered a handler for any `HTTP` exception with a `405` status code, and we return a template, `405.html`, as a response.
206
+
Similarly, you can create an exception handler for the `500` status code that returns an HTML template.
203
207
204
208
!!!info
205
-
Ellar will look for `405.html` in all registered modules. So `car` folder, create a `templates` folder and add `405.html`.
206
-
207
-
The same way can create Handler for `500` error code.
209
+
Ellar will search for `405.html` in all registered modules. So, within the `car` folder, create a templates folder and add `405.html`.
208
210
209
211
210
212
## **Registering Exception Handlers**
211
213
We have successfully created two exception handlers `ExceptionHandlerAction405` and `MyCustomExceptionHandler` but they are not yet visible to the application.
212
214
213
-
-`config.py`: The config file holds manage application settings. The `EXCEPTION_HANDLERS` variable defines all custom exception handlers registered to `ExceptionMiddlewareService` when bootstrapping the application.
214
-
215
-
```python
216
-
# project_name/config.py
217
-
import typing as t
218
-
from ellar.core import ConfigDefaultTypesMixin
219
-
from ellar.common import IExceptionHandler
220
-
from .apps.custom_exceptions import MyCustomExceptionHandler, ExceptionHandlerAction405
215
+
=== "Using config.py"
216
+
In the `config.py` file, which holds application settings, you can define custom exception handlers to be registered with the `ExceptionMiddlewareService` during the application's bootstrapping process.
217
+
218
+
```python
219
+
# project_name/config.py
220
+
import typing as t
221
+
from ellar.core import ConfigDefaultTypesMixin
222
+
from ellar.common import IExceptionHandler
223
+
from .apps.custom_exceptions import MyCustomExceptionHandler, ExceptionHandlerAction405
224
+
225
+
class BaseConfig(ConfigDefaultTypesMixin):
226
+
EXCEPTION_HANDLERS: t.List[IExceptionHandler] = [
227
+
MyCustomExceptionHandler(),
228
+
ExceptionHandlerAction405()
229
+
]
230
+
```
231
+
=== "Using Application Instance"
232
+
Alternatively, you can add exception handlers directly through the app instance in your application:
221
233
222
-
classBaseConfig(ConfigDefaultTypesMixin):
223
-
EXCEPTION_HANDLERS: t.List[IExceptionHandler] = [
224
-
MyCustomExceptionHandler(),
234
+
```python
235
+
# project_name/server.py
236
+
237
+
import os
238
+
239
+
from ellar.common.constants import ELLAR_CONFIG_MODULE
240
+
from ellar.core.factory import AppFactory
241
+
from .root_module import ApplicationModule
242
+
from .apps.custom_exceptions import MyCustomExceptionHandler, ExceptionHandlerAction405
Once we register the `OverrideAPIExceptionHandler` exception handler, it will become the default handler for the `APIException` exception type.
281
+
Once you register the `OverrideAPIExceptionHandler` exception handler, it will become the default `handler` for the `APIException` exception type.
279
282
280
283
## **Declaring Exception Handler as a function**
281
-
In the previous section, we have seen how to create a custom ExceptionHandler from `IExceptionHandler`. In this section we will do the same using a plane function.
284
+
In the previous section, we saw how to create a custom ExceptionHandler from `IExceptionHandler`. In this section, we'll achieve the same result using a plain function.
282
285
283
-
For example, lets say we have a function `exception_handler_fun` as shown below
286
+
For example, let's say we have a function `exception_handler_fun` as shown below:
284
287
285
288
```python
286
289
from starlette.responses import PlainTextResponse
@@ -290,8 +293,7 @@ from ellar.common import IExecutionContext
To get the `exception_handler_fun` to work as an ExceptionHandler, you will need `CallableExceptionHandler` from `ellar.common.exceptions` package.
296
+
To make the `exception_handler_fun` work as an ExceptionHandler, you will need to use `CallableExceptionHandler` from the `ellar.common.exceptions` package:
0 commit comments