About
This repository is an example of how I like to do error handling with axum with the help of enum_convert to avoid some repetitive From implementations.
The code implements a dummy job runner API with those few routes:
POST /jobsto create a jobGET /jobsto get the jobs listGET /job/{job_id}to get a specific jobPOST /job/{job_id}/resetto reset a job statePOST /job/{job_id}/cancelto cancel a job so that it does not get executed
The main idea for error handling is that each route handler has its own error type (see [CancelJobError](https://github.com/avandecreme/axum-error-example/blob/main/src/bin/axum_error_example/api/…
About
This repository is an example of how I like to do error handling with axum with the help of enum_convert to avoid some repetitive From implementations.
The code implements a dummy job runner API with those few routes:
POST /jobsto create a jobGET /jobsto get the jobs listGET /job/{job_id}to get a specific jobPOST /job/{job_id}/resetto reset a job statePOST /job/{job_id}/cancelto cancel a job so that it does not get executed
The main idea for error handling is that each route handler has its own error type (see CancelJobError for example). This allows a very precise description of the possible failure cases of each handler. Note that all of those handler error types have an InternalError variant which is here to handle server side errors (mapped to http 500 error code) such as the database being unreachable. This variant is just a wrapper around anyhow::Error for maximum flexibility. The other variants are user errors (mapped to http 4xx error code).
Because some handlers have some errors in common (for example JobNotFound), a global ApiError is used which contains the union of all the variants of all the handler errors. This allows writing the error message and the mapping to http error codes only once for each variant. Note that in this example the error is returned as a simple string, but one can easily use a more advanced format such as RFC7807.
To convert between the handler errors to ApiError, we implement From<HandlerError> for ApiError. This is where enum_convert comes in handy, thanks to the EnumInto derive macro, avoiding the repetitive From manual implementation.
Running
Should be as simple as cargo run. You should then be able to interact with the endpoints, for example using httpie:
http POST :3000/jobs description=test
http :3000/jobs
http :3000/jobs/your-job-uuid
http POST :3000/jobs/your-job-uuid/reset
http POST :3000/jobs/your-job-uuid/cancel