1use crate::request::{
2 DeleteResponse, FHIRResponse, HistoryResponse, InvokeResponse, SearchResponse,
3};
4use axum::response::IntoResponse;
5use haste_fhir_model::r4::generated::{
6 resources::Resource,
7 terminology::IssueType,
8 types::{FHIRId, FHIRInstant},
9};
10use haste_fhir_operation_error::OperationOutcomeError;
11use haste_reflect::MetaValue;
12use http::{HeaderMap, StatusCode};
13
14fn add_resource_headers(headers: &mut HeaderMap, resource: &Resource) -> () {
15 let _id = resource
16 .get_field("id")
17 .and_then(|id| id.as_any().downcast_ref::<String>());
18
19 let meta = resource.get_field("meta");
20
21 let last_modified = meta
22 .and_then(|meta| meta.get_field("lastUpdated"))
23 .and_then(|lu| lu.as_any().downcast_ref::<Box<FHIRInstant>>())
24 .and_then(|lu| lu.value.as_ref());
25
26 let version_id = meta
27 .and_then(|meta| meta.get_field("versionId"))
28 .and_then(|vid| vid.as_any().downcast_ref::<Box<FHIRId>>())
29 .and_then(|vid| vid.value.as_ref());
30
31 if let Some(last_modified) = last_modified {
32 headers.insert(
33 axum::http::header::LAST_MODIFIED,
34 last_modified
35 .format("%a, %d %b %G %H:%M:%S GMT")
36 .parse()
37 .unwrap(),
38 );
39 }
40 if let Some(version_id) = version_id {
41 headers.insert(
42 axum::http::header::ETAG,
43 format!("W/\"{}\"", version_id).parse().unwrap(),
44 );
45 }
46}
47
48fn add_headers(response: &FHIRResponse) -> HeaderMap {
49 let mut header = HeaderMap::new();
50 header.insert(
51 axum::http::header::CONTENT_TYPE,
52 "application/fhir+json".parse().unwrap(),
53 );
54
55 match response {
56 FHIRResponse::Create(resp) => {
57 add_resource_headers(&mut header, &resp.resource);
58 }
59 FHIRResponse::Read(resp) => {
60 if let Some(resource) = &resp.resource {
61 add_resource_headers(&mut header, resource);
62 }
63 }
64 FHIRResponse::VersionRead(resp) => {
65 add_resource_headers(&mut header, &resp.resource);
66 }
67 FHIRResponse::Update(resp) => {
68 add_resource_headers(&mut header, &resp.resource);
69 }
70 FHIRResponse::Patch(fhirpatch_response) => {
71 add_resource_headers(&mut header, &fhirpatch_response.resource);
72 }
73 _ => {}
74 };
75
76 header
77}
78
79impl IntoResponse for FHIRResponse {
80 fn into_response(self) -> axum::response::Response {
81 let header = add_headers(&self);
82
83 match self {
84 FHIRResponse::Create(response) => (
85 StatusCode::CREATED,
86 header,
87 haste_fhir_serialization_json::to_string(&response.resource).unwrap(),
89 )
90 .into_response(),
91 FHIRResponse::Read(response) => {
92 if let Some(resource) = response.resource {
93 (
94 StatusCode::OK,
95 header,
96 haste_fhir_serialization_json::to_string(&resource).unwrap(),
98 )
99 .into_response()
100 } else {
101 OperationOutcomeError::error(
102 IssueType::NotFound(None),
103 "Resource not found.".to_string(),
104 )
105 .into_response()
106 }
107 }
108 FHIRResponse::VersionRead(response) => (
109 StatusCode::OK,
110 header,
111 haste_fhir_serialization_json::to_string(&response.resource).unwrap(),
113 )
114 .into_response(),
115 FHIRResponse::Update(response) => (
116 StatusCode::OK,
117 header,
118 haste_fhir_serialization_json::to_string(&response.resource).unwrap(),
120 )
121 .into_response(),
122 FHIRResponse::Capabilities(response) => (
123 StatusCode::OK,
124 header,
125 haste_fhir_serialization_json::to_string(&response.capabilities).unwrap(),
127 )
128 .into_response(),
129 FHIRResponse::History(history_response) => match history_response {
130 HistoryResponse::Instance(response) => (
131 StatusCode::OK,
132 header,
133 haste_fhir_serialization_json::to_string(&response.bundle).unwrap(),
135 )
136 .into_response(),
137 HistoryResponse::Type(response) => (
138 StatusCode::OK,
139 header,
140 haste_fhir_serialization_json::to_string(&response.bundle).unwrap(),
142 )
143 .into_response(),
144 HistoryResponse::System(response) => (
145 StatusCode::OK,
146 header,
147 haste_fhir_serialization_json::to_string(&response.bundle).unwrap(),
149 )
150 .into_response(),
151 },
152 FHIRResponse::Search(search_response) => match search_response {
153 SearchResponse::Type(response) => (
154 StatusCode::OK,
155 header,
156 haste_fhir_serialization_json::to_string(&response.bundle).unwrap(),
158 )
159 .into_response(),
160 SearchResponse::System(response) => (
161 StatusCode::OK,
162 header,
163 haste_fhir_serialization_json::to_string(&response.bundle).unwrap(),
165 )
166 .into_response(),
167 },
168 FHIRResponse::Batch(response) => {
169 (
170 StatusCode::OK,
171 header,
172 haste_fhir_serialization_json::to_string(&response.resource).unwrap(),
174 )
175 .into_response()
176 }
177 FHIRResponse::Invoke(invoke_response) => match invoke_response {
178 InvokeResponse::Instance(invoke_response) => {
179 (
180 StatusCode::OK,
181 header,
182 haste_fhir_serialization_json::to_string(&invoke_response.resource)
184 .unwrap(),
185 )
186 .into_response()
187 }
188 InvokeResponse::Type(invoke_response) => {
189 (
190 StatusCode::OK,
191 header,
192 haste_fhir_serialization_json::to_string(&invoke_response.resource)
194 .unwrap(),
195 )
196 .into_response()
197 }
198 InvokeResponse::System(invoke_response) => {
199 (
200 StatusCode::OK,
201 header,
202 haste_fhir_serialization_json::to_string(&invoke_response.resource)
204 .unwrap(),
205 )
206 .into_response()
207 }
208 },
209
210 FHIRResponse::Delete(delete_response) => match delete_response {
211 DeleteResponse::Instance(_) => (StatusCode::NO_CONTENT, header, "").into_response(),
212 DeleteResponse::Type(_) => (StatusCode::NO_CONTENT, header, "").into_response(),
213 DeleteResponse::System(_) => (StatusCode::NO_CONTENT, header, "").into_response(),
214 },
215
216 FHIRResponse::Patch(fhirpatch_response) => (
217 StatusCode::OK,
218 header,
219 haste_fhir_serialization_json::to_string(&fhirpatch_response.resource).unwrap(),
221 )
222 .into_response(),
223
224 FHIRResponse::Transaction(fhirtransaction_response) => {
225 (
226 StatusCode::OK,
227 header,
228 haste_fhir_serialization_json::to_string(&fhirtransaction_response.resource)
230 .unwrap(),
231 )
232 .into_response()
233 }
234 }
235 }
236}