1 use crate::{metadata::MetadataMap, Extensions};
2 
3 /// A gRPC response and metadata from an RPC call.
4 #[derive(Debug)]
5 pub struct Response<T> {
6     metadata: MetadataMap,
7     message: T,
8     extensions: Extensions,
9 }
10 
11 impl<T> Response<T> {
12     /// Create a new gRPC response.
13     ///
14     /// ```rust
15     /// # use tonic::Response;
16     /// # pub struct HelloReply {
17     /// #   pub message: String,
18     /// # }
19     /// # let name = "";
20     /// Response::new(HelloReply {
21     ///     message: format!("Hello, {}!", name).into(),
22     /// });
23     /// ```
new(message: T) -> Self24     pub fn new(message: T) -> Self {
25         Response {
26             metadata: MetadataMap::new(),
27             message,
28             extensions: Extensions::new(),
29         }
30     }
31 
32     /// Get a immutable reference to `T`.
get_ref(&self) -> &T33     pub fn get_ref(&self) -> &T {
34         &self.message
35     }
36 
37     /// Get a mutable reference to the message
get_mut(&mut self) -> &mut T38     pub fn get_mut(&mut self) -> &mut T {
39         &mut self.message
40     }
41 
42     /// Get a reference to the custom response metadata.
metadata(&self) -> &MetadataMap43     pub fn metadata(&self) -> &MetadataMap {
44         &self.metadata
45     }
46 
47     /// Get a mutable reference to the response metadata.
metadata_mut(&mut self) -> &mut MetadataMap48     pub fn metadata_mut(&mut self) -> &mut MetadataMap {
49         &mut self.metadata
50     }
51 
52     /// Consumes `self`, returning the message
into_inner(self) -> T53     pub fn into_inner(self) -> T {
54         self.message
55     }
56 
57     /// Consumes `self` returning the parts of the response.
into_parts(self) -> (MetadataMap, T, Extensions)58     pub fn into_parts(self) -> (MetadataMap, T, Extensions) {
59         (self.metadata, self.message, self.extensions)
60     }
61 
62     /// Create a new gRPC response from metadata, message and extensions.
from_parts(metadata: MetadataMap, message: T, extensions: Extensions) -> Self63     pub fn from_parts(metadata: MetadataMap, message: T, extensions: Extensions) -> Self {
64         Self {
65             metadata,
66             message,
67             extensions,
68         }
69     }
70 
from_http(res: http::Response<T>) -> Self71     pub(crate) fn from_http(res: http::Response<T>) -> Self {
72         let (head, message) = res.into_parts();
73         Response {
74             metadata: MetadataMap::from_headers(head.headers),
75             message,
76             extensions: Extensions::from_http(head.extensions),
77         }
78     }
79 
into_http(self) -> http::Response<T>80     pub(crate) fn into_http(self) -> http::Response<T> {
81         let mut res = http::Response::new(self.message);
82 
83         *res.version_mut() = http::Version::HTTP_2;
84         *res.headers_mut() = self.metadata.into_sanitized_headers();
85         *res.extensions_mut() = self.extensions.into_http();
86 
87         res
88     }
89 
90     #[doc(hidden)]
map<F, U>(self, f: F) -> Response<U> where F: FnOnce(T) -> U,91     pub fn map<F, U>(self, f: F) -> Response<U>
92     where
93         F: FnOnce(T) -> U,
94     {
95         let message = f(self.message);
96         Response {
97             metadata: self.metadata,
98             message,
99             extensions: self.extensions,
100         }
101     }
102 
103     /// Returns a reference to the associated extensions.
extensions(&self) -> &Extensions104     pub fn extensions(&self) -> &Extensions {
105         &self.extensions
106     }
107 
108     /// Returns a mutable reference to the associated extensions.
extensions_mut(&mut self) -> &mut Extensions109     pub fn extensions_mut(&mut self) -> &mut Extensions {
110         &mut self.extensions
111     }
112 
113     /// Disable compression of the response body.
114     ///
115     /// This disables compression of the body of this response, even if compression is enabled on
116     /// the server.
117     ///
118     /// **Note**: This only has effect on responses to unary requests and responses to client to
119     /// server streams. Response streams (server to client stream and bidirectional streams) will
120     /// still be compressed according to the configuration of the server.
121     #[cfg(feature = "gzip")]
122     #[cfg_attr(docsrs, doc(cfg(feature = "gzip")))]
disable_compression(&mut self)123     pub fn disable_compression(&mut self) {
124         self.extensions_mut()
125             .insert(crate::codec::compression::SingleMessageCompressionOverride::Disable);
126     }
127 }
128 
129 #[cfg(test)]
130 mod tests {
131     use super::*;
132     use crate::metadata::MetadataValue;
133 
134     #[test]
reserved_headers_are_excluded()135     fn reserved_headers_are_excluded() {
136         let mut r = Response::new(1);
137 
138         for header in &MetadataMap::GRPC_RESERVED_HEADERS {
139             r.metadata_mut()
140                 .insert(*header, MetadataValue::from_static("invalid"));
141         }
142 
143         let http_response = r.into_http();
144         assert!(http_response.headers().is_empty());
145     }
146 }
147