-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathapi_error_response.py
More file actions
145 lines (121 loc) · 5.13 KB
/
api_error_response.py
File metadata and controls
145 lines (121 loc) · 5.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import json
import logging
import uuid
from datetime import UTC, datetime
from enum import Enum
from http import HTTPStatus
from flask import make_response
from flask.typing import ResponseReturnValue
from eligibility_signposting_api.model.operation_outcome import OperationOutcome, OperationOutcomeIssue
logger = logging.getLogger(__name__)
class FHIRIssueSeverity(str, Enum):
FATAL = "fatal"
ERROR = "error"
WARNING = "warning"
INFORMATION = "information"
class FHIRIssueCode(str, Enum):
FORBIDDEN = "forbidden"
PROCESSING = "processing"
VALUE = "value"
class FHIRSpineErrorCode(str, Enum):
ACCESS_DENIED = "ACCESS_DENIED"
INVALID_PARAMETER = "INVALID_PARAMETER"
INTERNAL_SERVER_ERROR = "INTERNAL_SERVER_ERROR"
REFERENCE_NOT_FOUND = "REFERENCE_NOT_FOUND"
class APIErrorResponse:
def __init__(
self,
status_code: HTTPStatus,
fhir_issue_code: FHIRIssueCode,
fhir_issue_severity: FHIRIssueSeverity,
fhir_error_code: str,
fhir_display_message: str,
) -> None:
self.status_code = status_code
self.fhir_issue_code = fhir_issue_code
self.fhir_issue_severity = fhir_issue_severity
self.fhir_coding_system = "https://fhir.nhs.uk/STU3/ValueSet/Spine-ErrorOrWarningCode-1"
self.fhir_error_code = fhir_error_code
self.fhir_display_message = fhir_display_message
def build_operation_outcome_issue(self, diagnostics: str, location: list[str] | None) -> OperationOutcomeIssue:
details = {
"coding": [
{
"system": self.fhir_coding_system,
"code": self.fhir_error_code,
"display": self.fhir_display_message,
}
]
}
return OperationOutcomeIssue(
severity=self.fhir_issue_severity,
code=self.fhir_issue_code,
details=details,
diagnostics=diagnostics,
location=location,
)
def generate_response(self, diagnostics: str, location_param: str | None = None) -> ResponseReturnValue:
issue_location = [f"parameters/{location_param}"] if location_param else None
problem = OperationOutcome(
id=str(uuid.uuid4()),
meta={"lastUpdated": datetime.now(UTC)},
issue=[self.build_operation_outcome_issue(diagnostics, issue_location)],
)
response_body = json.dumps(problem.model_dump(mode="json", exclude_none=True))
return make_response(response_body, self.status_code, {"Content-Type": "application/fhir+json"})
def log_and_generate_response(
self, log_message: str, diagnostics: str, location_param: str | None = None
) -> ResponseReturnValue:
logger.error(log_message)
return self.generate_response(diagnostics, location_param)
INVALID_INCLUDE_ACTIONS_ERROR = APIErrorResponse(
status_code=HTTPStatus.UNPROCESSABLE_ENTITY,
fhir_issue_code=FHIRIssueCode.VALUE,
fhir_issue_severity=FHIRIssueSeverity.ERROR,
fhir_error_code=FHIRSpineErrorCode.INVALID_PARAMETER,
fhir_display_message="The supplied value was not recognised by the API.",
)
INVALID_CATEGORY_ERROR = APIErrorResponse(
status_code=HTTPStatus.UNPROCESSABLE_ENTITY,
fhir_issue_code=FHIRIssueCode.VALUE,
fhir_issue_severity=FHIRIssueSeverity.ERROR,
fhir_error_code=FHIRSpineErrorCode.INVALID_PARAMETER,
fhir_display_message="The supplied category was not recognised by the API.",
)
INVALID_CONDITION_FORMAT_ERROR = APIErrorResponse(
status_code=HTTPStatus.BAD_REQUEST,
fhir_issue_code=FHIRIssueCode.VALUE,
fhir_issue_severity=FHIRIssueSeverity.ERROR,
fhir_error_code=FHIRSpineErrorCode.INVALID_PARAMETER,
fhir_display_message="The given conditions were not in the expected format.",
)
NHS_NUMBER_NOT_FOUND_ERROR = APIErrorResponse(
status_code=HTTPStatus.NOT_FOUND,
fhir_issue_code=FHIRIssueCode.PROCESSING,
fhir_issue_severity=FHIRIssueSeverity.ERROR,
fhir_error_code=FHIRSpineErrorCode.REFERENCE_NOT_FOUND,
fhir_display_message="The given NHS number was not found in our datasets. "
"This could be because the number is incorrect or "
"some other reason we cannot process that number.",
)
INTERNAL_SERVER_ERROR = APIErrorResponse(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
fhir_issue_code=FHIRIssueCode.PROCESSING,
fhir_issue_severity=FHIRIssueSeverity.ERROR,
fhir_error_code=FHIRSpineErrorCode.INTERNAL_SERVER_ERROR,
fhir_display_message="An unexpected internal server error occurred.",
)
NHS_NUMBER_MISMATCH_ERROR = APIErrorResponse(
status_code=HTTPStatus.FORBIDDEN,
fhir_issue_code=FHIRIssueCode.FORBIDDEN,
fhir_issue_severity=FHIRIssueSeverity.ERROR,
fhir_error_code=FHIRSpineErrorCode.ACCESS_DENIED,
fhir_display_message="Access has been denied to process this request.",
)
CONSUMER_ID_NOT_PROVIDED_ERROR = APIErrorResponse(
status_code=HTTPStatus.FORBIDDEN,
fhir_issue_code=FHIRIssueCode.FORBIDDEN,
fhir_issue_severity=FHIRIssueSeverity.ERROR,
fhir_error_code=FHIRSpineErrorCode.ACCESS_DENIED,
fhir_display_message="Access has been denied to process this request.",
)