cratestack_axum/transport/
validate.rs1use axum::http::HeaderMap;
2use cratestack_core::{CratestackError, RouteTransportCapabilities};
3use serde::Deserialize;
4
5use super::http_transport::HttpTransport;
6use super::media_type::{
7 request_content_type, validate_transport_accept_header, validate_transport_content_type_header,
8};
9
10pub fn validate_transport_request_headers<T>(
11 transport: &T,
12 headers: &HeaderMap,
13) -> Result<(), CratestackError>
14where
15 T: HttpTransport,
16{
17 validate_transport_request_headers_for(
18 transport,
19 headers,
20 &RouteTransportCapabilities {
21 request_types: &[],
22 response_types: &[],
23 default_response_type: "",
24 supports_sequence_response: false,
25 },
26 )
27}
28
29pub fn validate_transport_response_headers<T>(
30 transport: &T,
31 headers: &HeaderMap,
32) -> Result<(), CratestackError>
33where
34 T: HttpTransport,
35{
36 validate_transport_response_headers_for(
37 transport,
38 headers,
39 &RouteTransportCapabilities {
40 request_types: &[],
41 response_types: &[],
42 default_response_type: "",
43 supports_sequence_response: false,
44 },
45 )
46}
47
48pub fn validate_transport_request_headers_for<T>(
49 transport: &T,
50 headers: &HeaderMap,
51 capabilities: &RouteTransportCapabilities,
52) -> Result<(), CratestackError>
53where
54 T: HttpTransport,
55{
56 validate_transport_accept_header(headers, &encodable_response_types(transport, capabilities))?;
57 if capabilities.request_types.is_empty() {
58 Ok(())
59 } else {
60 validate_transport_content_type_header(headers, capabilities.request_types)
61 }
62}
63
64pub fn validate_transport_response_headers_for<T>(
65 transport: &T,
66 headers: &HeaderMap,
67 capabilities: &RouteTransportCapabilities,
68) -> Result<(), CratestackError>
69where
70 T: HttpTransport,
71{
72 validate_transport_accept_header(headers, &encodable_response_types(transport, capabilities))
73}
74
75fn encodable_response_types<T>(
88 transport: &T,
89 capabilities: &RouteTransportCapabilities,
90) -> Vec<&'static str>
91where
92 T: HttpTransport,
93{
94 capabilities
95 .response_types
96 .iter()
97 .copied()
98 .filter(|content_type| transport.can_encode(content_type))
99 .collect()
100}
101
102pub fn decode_transport_request_for<TTransport, TValue>(
103 transport: &TTransport,
104 headers: &HeaderMap,
105 capabilities: &RouteTransportCapabilities,
106 body: &[u8],
107) -> Result<TValue, CratestackError>
108where
109 TTransport: HttpTransport,
110 TValue: for<'de> Deserialize<'de>,
111{
112 let content_type = request_content_type(headers, capabilities.request_types)?;
113 transport.decode_request(content_type, body)
114}
115
116#[cfg(test)]
117mod tests;