|
| 1 | +# How to Use the API Error Response Module |
| 2 | + |
| 3 | +This document outlines how to use the `api_error_response.py` module for standardized error handling within the Eligibility Signposting API. The module ensures that all API errors are consistent, logged appropriately, and conform to the FHIR `OperationOutcome` standard. |
| 4 | + |
| 5 | +## Core Concepts |
| 6 | + |
| 7 | +The error handling mechanism is built around the class `APIErrorResponse`. |
| 8 | + |
| 9 | +1. **`APIErrorResponse` Class**: This class is a constructor for a specific type of error. An instance of this class holds configuration for an error, such as the `HTTPStatus`, severity, and various FHIR-specific codes. |
| 10 | +2. **Pre-defined Error Instances**: The module defines several singleton instances of for common, application-specific errors. Examples include: |
| 11 | + - `INVALID_CATEGORY_ERROR` |
| 12 | + - `NHS_NUMBER_MISMATCH_ERROR` |
| 13 | + - `INTERNAL_SERVER_ERROR` |
| 14 | +3. **`log_and_generate_response()` Method**: This is the primary method to be used. When called on an `APIErrorResponse` instance, it performs two actions: |
| 15 | + - Logs the error with a detailed internal message. |
| 16 | + - Generates a complete HTTP response dictionary (`statusCode`, `headers`, `body`) containing a FHIR-compliant `OperationOutcome` payload. |
| 17 | + |
| 18 | +## How to Use |
| 19 | + |
| 20 | +The primary way to handle errors is to import a pre-defined error object from `api_error_response.py` and call its `log_and_generate_response()` method. |
| 21 | + |
| 22 | +### 1. Handling Specific, Known Errors |
| 23 | + |
| 24 | +For handling validation failures or other expected error conditions, use one of the pre-defined error instances. |
| 25 | +The `wrapper.py` module uses this pattern to validate query parameters. If a parameter is invalid, it calls the corresponding error function. |
| 26 | + |
| 27 | +#### Example: Invalid "category" parameter |
| 28 | + |
| 29 | +``` python |
| 30 | +# wrapper.py |
| 31 | + |
| 32 | +from eligibility_signposting_api.api_error_response import INVALID_CATEGORY_ERROR |
| 33 | + |
| 34 | +def get_category_error_response(category: str) -> dict[str, Any]: |
| 35 | + """Generates an error response for an invalid category.""" |
| 36 | + |
| 37 | + return INVALID_CATEGORY_ERROR.log_and_generate_response( |
| 38 | + log_message=f"Invalid category query param: '{category}'", |
| 39 | + diagnostics=f"{category} is not a category that is supported by the API", |
| 40 | + location_param="category" |
| 41 | + ) |
| 42 | +``` |
| 43 | + |
| 44 | +#### Key Parameters for `log_and_generate_response()` |
| 45 | + |
| 46 | +- `log_message`: A detailed message for internal logging. This should contain specific information useful for debugging. |
| 47 | +- `diagnostics`: The user-facing error message that will be included in the API response body. |
| 48 | +- `location_param` (optional): The name of the parameter that caused the error. This helps pinpoint the issue for API consumers. |
| 49 | + |
| 50 | +### 2. Handling Unexpected Exceptions (Global Error Handler) |
| 51 | + |
| 52 | +For unexpected errors, a global exception handler in `error_handler.py` catches any unhandled exception and returns a generic 500 Internal Server Error. This prevents sensitive information from leaking in stack traces. |
| 53 | + |
| 54 | +``` python |
| 55 | +# error_handler.py |
| 56 | + |
| 57 | +from eligibility_signposting_api.api_error_response import INTERNAL_SERVER_ERROR |
| 58 | + |
| 59 | +def handle_exception(e: Exception) -> ResponseReturnValue | HTTPException: |
| 60 | + # Generate a generic, safe response for the client |
| 61 | + response = INTERNAL_SERVER_ERROR.log_and_generate_response( |
| 62 | + log_message=f"An unexpected error occurred: {traceback.format_exception(e)}", |
| 63 | + diagnostics="An unexpected error occurred." |
| 64 | + ) |
| 65 | + return make_response(response.get("body"), response.get("statusCode"), response.get("headers")) |
| 66 | +``` |
| 67 | + |
| 68 | +### 3. Creating New Error Types |
| 69 | + |
| 70 | +If a new, reusable error condition is identified, you should add a new instance of `APIErrorResponse` to `api_error_response.py` |
| 71 | +Follow the existing pattern: |
| 72 | + |
| 73 | +``` python |
| 74 | +# api_error_response.py |
| 75 | + |
| 76 | +# ... (other error definitions) |
| 77 | + |
| 78 | +SOME_NEW_ERROR = APIErrorResponse( |
| 79 | + status_code=HTTPStatus.BAD_REQUEST, |
| 80 | + fhir_issue_code=FHIRIssueCode.VALUE, |
| 81 | + fhir_issue_severity=FHIRIssueSeverity.ERROR, |
| 82 | + fhir_coding_system=FHIR_SPINE_ERROR_CODE_SYSTEM, |
| 83 | + fhir_error_code=FHIRSpineErrorCode.INVALID_PARAMETER, |
| 84 | + fhir_display_message="A new specific error message for display", |
| 85 | +) |
| 86 | +``` |
| 87 | + |
| 88 | +By centralizing error definitions, we ensure that the API provides a consistent and predictable experience for its consumers. |
0 commit comments