kutil_http/transcoding/
response.rs1use super::{super::headers::*, body::*};
2
3use {
4 ::bytes::*,
5 http::{header::*, *},
6 http_body::*,
7 kutil_std::error::*,
8 kutil_transcoding::*,
9};
10
11pub trait IntoTranscodingResponse<BodyT>: Sized
17where
18 BodyT: Body,
19 BodyT::Error: Into<CapturedError>,
20{
21 fn with_transcoding_body_passthrough(self) -> Response<TranscodingBody<BodyT>> {
23 self.with_transcoding_body_passthrough_with_first_bytes(None)
24 }
25
26 fn with_transcoding_body_passthrough_with_first_bytes(
28 self,
29 first_bytes: Option<Bytes>,
30 ) -> Response<TranscodingBody<BodyT>>;
31
32 fn with_transcoding_body(
34 self,
35 encoding: &Encoding,
36 encodable_by_default: bool,
37 ) -> Response<TranscodingBody<BodyT>> {
38 self.with_transcoding_body_with_first_bytes(None, encoding, encodable_by_default)
39 }
40
41 fn with_transcoding_body_with_first_bytes(
43 self,
44 first_bytes: Option<Bytes>,
45 encoding: &Encoding,
46 encodable_by_default: bool,
47 ) -> Response<TranscodingBody<BodyT>>;
48}
49
50impl<BodyT> IntoTranscodingResponse<BodyT> for Response<BodyT>
51where
52 BodyT: Body,
53 BodyT::Error: Into<CapturedError>,
54{
55 fn with_transcoding_body_passthrough_with_first_bytes(
56 self,
57 first_bytes: Option<Bytes>,
58 ) -> Response<TranscodingBody<BodyT>> {
59 let (mut parts, body) = self.into_parts();
60 parts.headers.remove(XX_ENCODE);
61 parts.headers.remove(XX_CACHE);
62 Response::from_parts(parts, body.into_transcoding_passthrough_with_first_bytes(first_bytes))
63 }
64
65 fn with_transcoding_body_with_first_bytes(
66 self,
67 first_bytes: Option<Bytes>,
68 encoding: &Encoding,
69 encodable_by_default: bool,
70 ) -> Response<TranscodingBody<BodyT>> {
71 if *encoding == Encoding::Identity {
72 return self.with_transcoding_body_passthrough_with_first_bytes(first_bytes);
73 }
74
75 let (mut parts, body) = self.into_parts();
76
77 let encode = parts.headers.xx_encode(encodable_by_default);
78 parts.headers.remove(XX_CACHE);
79 parts.headers.remove(XX_ENCODE);
80
81 if !encode {
82 tracing::debug!("not encoding to {} ({}=false)", encoding, XX_ENCODE);
83 return Response::from_parts(parts, body.into_transcoding_passthrough_with_first_bytes(first_bytes));
84 }
85
86 let current_encoding = parts.headers.content_encoding().into();
87
88 if *encoding == current_encoding {
89 tracing::debug!("already encoded as {}", encoding);
90 return Response::from_parts(parts, body.into_transcoding_passthrough_with_first_bytes(first_bytes));
91 }
92
93 if current_encoding != Encoding::Identity {
94 tracing::debug!("not reencoding from {} to {})", current_encoding, encoding);
95 return Response::from_parts(parts, body.into_transcoding_passthrough_with_first_bytes(first_bytes));
96
97 }
109
110 parts.headers.set_into_header_value(CONTENT_ENCODING, encoding.clone());
111
112 parts.headers.remove(CONTENT_LENGTH);
114
115 parts.headers.remove(CONTENT_DIGEST);
117
118 Response::from_parts(parts, body.into_encoding_with_first_bytes(first_bytes, encoding))
119 }
120}
121
122pub fn error_transcoding_response<BodyT>() -> Response<TranscodingBody<BodyT>>
124where
125 BodyT: Body + From<Bytes>,
126 BodyT::Error: Into<CapturedError>,
127{
128 let mut response = Response::new(Bytes::new().into()).with_transcoding_body_passthrough_with_first_bytes(None);
129 *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
130 response
131}
132
133pub fn not_modified_transcoding_response<BodyT>() -> Response<TranscodingBody<BodyT>>
135where
136 BodyT: Body + From<Bytes>,
137 BodyT::Error: Into<CapturedError>,
138{
139 let mut response = Response::new(Bytes::new().into()).with_transcoding_body_passthrough_with_first_bytes(None);
140 *response.status_mut() = StatusCode::NOT_MODIFIED;
141 response
142}