heart/
response.rs

1use crate::maud::Markup;
2use serde::Serialize;
3use warp::http::{Response, StatusCode};
4use warp::reply;
5use warp::reply::WithStatus;
6
7pub fn hx_with(
8    status: StatusCode,
9    res: Markup,
10) -> Response<String> {
11    Response::builder()
12        .header("Content", "text/html")
13        .status(status)
14        .body(res.into_string())
15        // TODO: verify that this is the case
16        .expect("BUG: impossible")
17}
18
19macro_rules! generate_hx_status_functions {
20    ($($fname:ident, $status:ident);* $(;)?) => {
21        $(
22            pub fn $fname(res: Markup) -> Response<String> {
23                hx_with(StatusCode::$status, res)
24            }
25        )*
26    };
27}
28
29generate_hx_status_functions! {
30    // funny aliases
31    hx, OK;
32    hx_error, IM_A_TEAPOT;
33
34    // 1XX
35    hx_continue, CONTINUE;
36    hx_switching_protocols, SWITCHING_PROTOCOLS;
37    hx_processing, PROCESSING;
38
39    // 2XX
40    hx_ok, OK;
41    hx_created, CREATED;
42    hx_accepted, ACCEPTED;
43    hx_non_authoritative_information, NON_AUTHORITATIVE_INFORMATION;
44    hx_no_content, NO_CONTENT;
45    hx_reset_content, RESET_CONTENT;
46    hx_partial_content, PARTIAL_CONTENT;
47    hx_multi_status, MULTI_STATUS;
48    hx_already_reported, ALREADY_REPORTED;
49    hx_im_used, IM_USED;
50
51    // 3XX
52    hx_multiple_choices, MULTIPLE_CHOICES;
53    hx_moved_permanently, MOVED_PERMANENTLY;
54    hx_found, FOUND;
55    hx_see_other, SEE_OTHER;
56    hx_not_modified, NOT_MODIFIED;
57    hx_use_proxy, USE_PROXY;
58    hx_temporary_redirect, TEMPORARY_REDIRECT;
59    hx_permanent_redirect, PERMANENT_REDIRECT;
60
61    // 4XX
62    hx_bad_request, BAD_REQUEST;
63    hx_unauthorized, UNAUTHORIZED;
64    hx_payment_required, PAYMENT_REQUIRED;
65    hx_forbidden, FORBIDDEN;
66    hx_not_found, NOT_FOUND;
67    hx_method_not_allowed, METHOD_NOT_ALLOWED;
68    hx_not_acceptable, NOT_ACCEPTABLE;
69    hx_proxy_authentication_required, PROXY_AUTHENTICATION_REQUIRED;
70    hx_request_timeout, REQUEST_TIMEOUT;
71    hx_conflict, CONFLICT;
72    hx_gone, GONE;
73    hx_length_required, LENGTH_REQUIRED;
74    hx_precondition_failed, PRECONDITION_FAILED;
75    hx_payload_too_large, PAYLOAD_TOO_LARGE;
76    hx_uri_too_long, URI_TOO_LONG;
77    hx_unsupported_media_type, UNSUPPORTED_MEDIA_TYPE;
78    hx_range_not_satisfiable, RANGE_NOT_SATISFIABLE;
79    hx_expectation_failed, EXPECTATION_FAILED;
80    hx_im_a_teapot, IM_A_TEAPOT;
81    hx_misdirected_request, MISDIRECTED_REQUEST;
82    hx_unprocessable_entity, UNPROCESSABLE_ENTITY;
83    hx_locked, LOCKED;
84    hx_failed_dependency, FAILED_DEPENDENCY;
85    hx_upgrade_required, UPGRADE_REQUIRED;
86    hx_precondition_required, PRECONDITION_REQUIRED;
87    hx_too_many_requests, TOO_MANY_REQUESTS;
88    hx_request_header_fields_too_large, REQUEST_HEADER_FIELDS_TOO_LARGE;
89    hx_unavailable_for_legal_reasons, UNAVAILABLE_FOR_LEGAL_REASONS;
90
91    // 5XX
92    hx_internal_server_error, INTERNAL_SERVER_ERROR;
93    hx_not_implemented, NOT_IMPLEMENTED;
94    hx_bad_gateway, BAD_GATEWAY;
95    hx_service_unavailable, SERVICE_UNAVAILABLE;
96    hx_gateway_timeout, GATEWAY_TIMEOUT;
97    hx_http_version_not_supported, HTTP_VERSION_NOT_SUPPORTED;
98    hx_variant_also_negotiates, VARIANT_ALSO_NEGOTIATES;
99    hx_insufficient_storage, INSUFFICIENT_STORAGE;
100    hx_loop_detected, LOOP_DETECTED;
101    hx_not_extended, NOT_EXTENDED;
102    hx_network_authentication_required, NETWORK_AUTHENTICATION_REQUIRED
103}
104
105pub fn js_with<T: Serialize>(
106    data: &T,
107    status_code: &StatusCode,
108) -> WithStatus<String> {
109    let json =
110        serde_json::to_string(data).expect("BUG: Impossible");
111    reply::with_status(json, *status_code)
112}
113
114macro_rules! generate_js_status_functions {
115    ($($fname:ident, $status:ident);* $(;)?) => {
116        $(
117            pub fn $fname<T: Serialize>(
118                data: &T,
119            ) -> WithStatus<String> {
120                js_with(data, &StatusCode::$status)
121            }
122        )*
123    };
124}
125
126generate_js_status_functions! {
127    // funny aliases
128    js, OK;
129    js_error, IM_A_TEAPOT;
130
131    // 1XX
132    js_continue, CONTINUE;
133    js_switching_protocols, SWITCHING_PROTOCOLS;
134    js_processing, PROCESSING;
135
136    // 2XX
137    js_ok, OK;
138    js_created, CREATED;
139    js_accepted, ACCEPTED;
140    js_non_authoritative_information, NON_AUTHORITATIVE_INFORMATION;
141    js_no_content, NO_CONTENT;
142    js_reset_content, RESET_CONTENT;
143    js_partial_content, PARTIAL_CONTENT;
144    js_multi_status, MULTI_STATUS;
145    js_already_reported, ALREADY_REPORTED;
146    js_im_used, IM_USED;
147
148    // 3XX
149    js_multiple_choices, MULTIPLE_CHOICES;
150    js_moved_permanently, MOVED_PERMANENTLY;
151    js_found, FOUND;
152    js_see_other, SEE_OTHER;
153    js_not_modified, NOT_MODIFIED;
154    js_use_proxy, USE_PROXY;
155    js_temporary_redirect, TEMPORARY_REDIRECT;
156    js_permanent_redirect, PERMANENT_REDIRECT;
157
158    // 4XX
159    js_bad_request, BAD_REQUEST;
160    js_unauthorized, UNAUTHORIZED;
161    js_payment_required, PAYMENT_REQUIRED;
162    js_forbidden, FORBIDDEN;
163    js_not_found, NOT_FOUND;
164    js_method_not_allowed, METHOD_NOT_ALLOWED;
165    js_not_acceptable, NOT_ACCEPTABLE;
166    js_proxy_authentication_required, PROXY_AUTHENTICATION_REQUIRED;
167    js_request_timeout, REQUEST_TIMEOUT;
168    js_conflict, CONFLICT;
169    js_gone, GONE;
170    js_length_required, LENGTH_REQUIRED;
171    js_precondition_failed, PRECONDITION_FAILED;
172    js_payload_too_large, PAYLOAD_TOO_LARGE;
173    js_uri_too_long, URI_TOO_LONG;
174    js_unsupported_media_type, UNSUPPORTED_MEDIA_TYPE;
175    js_range_not_satisfiable, RANGE_NOT_SATISFIABLE;
176    js_expectation_failed, EXPECTATION_FAILED;
177    js_im_a_teapot, IM_A_TEAPOT;
178    js_misdirected_request, MISDIRECTED_REQUEST;
179    js_unprocessable_entity, UNPROCESSABLE_ENTITY;
180    js_locked, LOCKED;
181    js_failed_dependency, FAILED_DEPENDENCY;
182    js_upgrade_required, UPGRADE_REQUIRED;
183    js_precondition_required, PRECONDITION_REQUIRED;
184    js_too_many_requests, TOO_MANY_REQUESTS;
185    js_request_header_fields_too_large, REQUEST_HEADER_FIELDS_TOO_LARGE;
186    js_unavailable_for_legal_reasons, UNAVAILABLE_FOR_LEGAL_REASONS;
187
188    // 5XX
189    js_internal_server_error, INTERNAL_SERVER_ERROR;
190    js_not_implemented, NOT_IMPLEMENTED;
191    js_bad_gateway, BAD_GATEWAY;
192    js_service_unavailable, SERVICE_UNAVAILABLE;
193    js_gateway_timeout, GATEWAY_TIMEOUT;
194    js_http_version_not_supported, HTTP_VERSION_NOT_SUPPORTED;
195    js_variant_also_negotiates, VARIANT_ALSO_NEGOTIATES;
196    js_insufficient_storage, INSUFFICIENT_STORAGE;
197    js_loop_detected, LOOP_DETECTED;
198    js_not_extended, NOT_EXTENDED;
199    js_network_authentication_required, NETWORK_AUTHENTICATION_REQUIRED
200}
201
202pub fn sse_chunk<T: Into<String>>(s: T) -> crate::sse::Event {
203    crate::sse::Event::default().event("message-chunk").data(s)
204}
205pub fn sse_complete<T: Into<String>>(s: T) -> crate::sse::Event {
206    crate::sse::Event::default()
207        .event("message-complete")
208        .data(s)
209}