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; charset=utf-8".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 serde_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 serde_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 serde_json::to_string(&response.resource).unwrap(),
113 )
114 .into_response(),
115 FHIRResponse::Update(response) => (
116 StatusCode::OK,
117 header,
118 serde_json::to_string(&response.resource).unwrap(),
120 )
121 .into_response(),
122 FHIRResponse::Capabilities(response) => (
123 StatusCode::OK,
124 header,
125 serde_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 serde_json::to_string(&response.bundle).unwrap(),
135 )
136 .into_response(),
137 HistoryResponse::Type(response) => (
138 StatusCode::OK,
139 header,
140 serde_json::to_string(&response.bundle).unwrap(),
142 )
143 .into_response(),
144 HistoryResponse::System(response) => (
145 StatusCode::OK,
146 header,
147 serde_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 serde_json::to_string(&response.bundle).unwrap(),
158 )
159 .into_response(),
160 SearchResponse::System(response) => (
161 StatusCode::OK,
162 header,
163 serde_json::to_string(&response.bundle).unwrap(),
165 )
166 .into_response(),
167 },
168 FHIRResponse::Batch(response) => {
169 (
170 StatusCode::OK,
171 header,
172 serde_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 serde_json::to_string(&invoke_response.resource).unwrap(),
184 )
185 .into_response()
186 }
187 InvokeResponse::Type(invoke_response) => {
188 (
189 StatusCode::OK,
190 header,
191 serde_json::to_string(&invoke_response.resource).unwrap(),
193 )
194 .into_response()
195 }
196 InvokeResponse::System(invoke_response) => {
197 (
198 StatusCode::OK,
199 header,
200 serde_json::to_string(&invoke_response.resource).unwrap(),
202 )
203 .into_response()
204 }
205 },
206
207 FHIRResponse::Delete(delete_response) => match delete_response {
208 DeleteResponse::Instance(instance_delete) => (
209 StatusCode::OK,
210 header,
211 serde_json::to_string(&instance_delete.resource).unwrap(),
212 )
213 .into_response(),
214 DeleteResponse::Type(_) => (StatusCode::NO_CONTENT, header, "").into_response(),
215 DeleteResponse::System(_) => (StatusCode::NO_CONTENT, header, "").into_response(),
216 },
217
218 FHIRResponse::Patch(fhirpatch_response) => (
219 StatusCode::OK,
220 header,
221 serde_json::to_string(&fhirpatch_response.resource).unwrap(),
223 )
224 .into_response(),
225
226 FHIRResponse::Transaction(fhirtransaction_response) => {
227 (
228 StatusCode::OK,
229 header,
230 serde_json::to_string(&fhirtransaction_response.resource).unwrap(),
232 )
233 .into_response()
234 }
235 }
236 }
237}