1use std::{
4 cell::{Ref, RefCell, RefMut},
5 fmt, str,
6};
7
8use bytes::{Bytes, BytesMut};
9use bytestring::ByteString;
10
11use crate::{
12 body::{BoxBody, EitherBody, MessageBody},
13 header::{self, HeaderMap, TryIntoHeaderValue},
14 responses::BoxedResponseHead,
15 Error, Extensions, ResponseBuilder, ResponseHead, StatusCode,
16};
17
18pub struct Response<B> {
20 pub(crate) head: BoxedResponseHead,
21 pub(crate) body: B,
22 pub(crate) extensions: RefCell<Extensions>,
23}
24
25impl Response<BoxBody> {
26 #[inline]
28 pub fn new(status: StatusCode) -> Self {
29 Response {
30 head: BoxedResponseHead::new(status),
31 body: BoxBody::new(()),
32 extensions: RefCell::new(Extensions::new()),
33 }
34 }
35
36 #[inline]
38 pub fn build(status: StatusCode) -> ResponseBuilder {
39 ResponseBuilder::new(status)
40 }
41
42 #[inline]
47 pub fn ok() -> Self {
48 Response::new(StatusCode::OK)
49 }
50
51 #[inline]
53 pub fn bad_request() -> Self {
54 Response::new(StatusCode::BAD_REQUEST)
55 }
56
57 #[inline]
59 pub fn not_found() -> Self {
60 Response::new(StatusCode::NOT_FOUND)
61 }
62
63 #[inline]
65 pub fn internal_server_error() -> Self {
66 Response::new(StatusCode::INTERNAL_SERVER_ERROR)
67 }
68
69 }
71
72impl<B> Response<B> {
73 #[inline]
75 pub fn with_body(status: StatusCode, body: B) -> Response<B> {
76 Response {
77 head: BoxedResponseHead::new(status),
78 body,
79 extensions: RefCell::new(Extensions::new()),
80 }
81 }
82
83 #[inline]
85 pub fn head(&self) -> &ResponseHead {
86 &self.head
87 }
88
89 #[inline]
91 pub fn head_mut(&mut self) -> &mut ResponseHead {
92 &mut self.head
93 }
94
95 #[inline]
97 pub fn status(&self) -> StatusCode {
98 self.head.status
99 }
100
101 #[inline]
103 pub fn status_mut(&mut self) -> &mut StatusCode {
104 &mut self.head.status
105 }
106
107 #[inline]
109 pub fn headers(&self) -> &HeaderMap {
110 &self.head.headers
111 }
112
113 #[inline]
115 pub fn headers_mut(&mut self) -> &mut HeaderMap {
116 &mut self.head.headers
117 }
118
119 #[inline]
121 pub fn upgrade(&self) -> bool {
122 self.head.upgrade()
123 }
124
125 #[inline]
127 pub fn keep_alive(&self) -> bool {
128 self.head.keep_alive()
129 }
130
131 #[inline]
133 pub fn extensions(&self) -> Ref<'_, Extensions> {
134 self.extensions.borrow()
135 }
136
137 #[inline]
139 pub fn extensions_mut(&mut self) -> RefMut<'_, Extensions> {
140 self.extensions.borrow_mut()
141 }
142
143 #[inline]
145 pub fn body(&self) -> &B {
146 &self.body
147 }
148
149 #[inline]
151 pub fn set_body<B2>(self, body: B2) -> Response<B2> {
152 Response {
153 head: self.head,
154 body,
155 extensions: self.extensions,
156 }
157 }
158
159 #[inline]
161 pub fn drop_body(self) -> Response<()> {
162 self.set_body(())
163 }
164
165 #[inline]
167 pub(crate) fn replace_body<B2>(self, body: B2) -> (Response<B2>, B) {
168 (
169 Response {
170 head: self.head,
171 body,
172 extensions: self.extensions,
173 },
174 self.body,
175 )
176 }
177
178 #[inline]
184 pub fn into_parts(self) -> (Response<()>, B) {
185 self.replace_body(())
186 }
187
188 #[inline]
192 pub fn map_body<F, B2>(mut self, f: F) -> Response<B2>
193 where
194 F: FnOnce(&mut ResponseHead, B) -> B2,
195 {
196 let body = f(&mut self.head, self.body);
197
198 Response {
199 head: self.head,
200 body,
201 extensions: self.extensions,
202 }
203 }
204
205 #[inline]
207 pub fn map_into_boxed_body(self) -> Response<BoxBody>
208 where
209 B: MessageBody + 'static,
210 {
211 self.map_body(|_, body| body.boxed())
212 }
213
214 #[inline]
216 pub fn into_body(self) -> B {
217 self.body
218 }
219}
220
221impl<B> fmt::Debug for Response<B>
222where
223 B: MessageBody,
224{
225 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
226 let res = writeln!(
227 f,
228 "\nResponse {:?} {}{}",
229 self.head.version,
230 self.head.status,
231 self.head.reason.unwrap_or(""),
232 );
233 let _ = writeln!(f, " headers:");
234 for (key, val) in self.head.headers.iter() {
235 let _ = writeln!(f, " {:?}: {:?}", key, val);
236 }
237 let _ = writeln!(f, " body: {:?}", self.body.size());
238 res
239 }
240}
241
242impl<B: Default> Default for Response<B> {
243 #[inline]
244 fn default() -> Response<B> {
245 Response::with_body(StatusCode::default(), B::default())
246 }
247}
248
249impl<I: Into<Response<BoxBody>>, E: Into<Error>> From<Result<I, E>> for Response<BoxBody> {
250 fn from(res: Result<I, E>) -> Self {
251 match res {
252 Ok(val) => val.into(),
253 Err(err) => Response::from(err.into()),
254 }
255 }
256}
257
258impl From<ResponseBuilder> for Response<EitherBody<()>> {
259 fn from(mut builder: ResponseBuilder) -> Self {
260 builder.finish()
261 }
262}
263
264impl From<std::convert::Infallible> for Response<BoxBody> {
265 fn from(val: std::convert::Infallible) -> Self {
266 match val {}
267 }
268}
269
270impl From<&'static str> for Response<&'static str> {
271 fn from(val: &'static str) -> Self {
272 let mut res = Response::with_body(StatusCode::OK, val);
273 let mime = mime::TEXT_PLAIN_UTF_8.try_into_value().unwrap();
274 res.headers_mut().insert(header::CONTENT_TYPE, mime);
275 res
276 }
277}
278
279impl From<&'static [u8]> for Response<&'static [u8]> {
280 fn from(val: &'static [u8]) -> Self {
281 let mut res = Response::with_body(StatusCode::OK, val);
282 let mime = mime::APPLICATION_OCTET_STREAM.try_into_value().unwrap();
283 res.headers_mut().insert(header::CONTENT_TYPE, mime);
284 res
285 }
286}
287
288impl From<Vec<u8>> for Response<Vec<u8>> {
289 fn from(val: Vec<u8>) -> Self {
290 let mut res = Response::with_body(StatusCode::OK, val);
291 let mime = mime::APPLICATION_OCTET_STREAM.try_into_value().unwrap();
292 res.headers_mut().insert(header::CONTENT_TYPE, mime);
293 res
294 }
295}
296
297impl From<&Vec<u8>> for Response<Vec<u8>> {
298 fn from(val: &Vec<u8>) -> Self {
299 let mut res = Response::with_body(StatusCode::OK, val.clone());
300 let mime = mime::APPLICATION_OCTET_STREAM.try_into_value().unwrap();
301 res.headers_mut().insert(header::CONTENT_TYPE, mime);
302 res
303 }
304}
305
306impl From<String> for Response<String> {
307 fn from(val: String) -> Self {
308 let mut res = Response::with_body(StatusCode::OK, val);
309 let mime = mime::TEXT_PLAIN_UTF_8.try_into_value().unwrap();
310 res.headers_mut().insert(header::CONTENT_TYPE, mime);
311 res
312 }
313}
314
315impl From<&String> for Response<String> {
316 fn from(val: &String) -> Self {
317 let mut res = Response::with_body(StatusCode::OK, val.clone());
318 let mime = mime::TEXT_PLAIN_UTF_8.try_into_value().unwrap();
319 res.headers_mut().insert(header::CONTENT_TYPE, mime);
320 res
321 }
322}
323
324impl From<Bytes> for Response<Bytes> {
325 fn from(val: Bytes) -> Self {
326 let mut res = Response::with_body(StatusCode::OK, val);
327 let mime = mime::APPLICATION_OCTET_STREAM.try_into_value().unwrap();
328 res.headers_mut().insert(header::CONTENT_TYPE, mime);
329 res
330 }
331}
332
333impl From<BytesMut> for Response<BytesMut> {
334 fn from(val: BytesMut) -> Self {
335 let mut res = Response::with_body(StatusCode::OK, val);
336 let mime = mime::APPLICATION_OCTET_STREAM.try_into_value().unwrap();
337 res.headers_mut().insert(header::CONTENT_TYPE, mime);
338 res
339 }
340}
341
342impl From<ByteString> for Response<ByteString> {
343 fn from(val: ByteString) -> Self {
344 let mut res = Response::with_body(StatusCode::OK, val);
345 let mime = mime::TEXT_PLAIN_UTF_8.try_into_value().unwrap();
346 res.headers_mut().insert(header::CONTENT_TYPE, mime);
347 res
348 }
349}
350
351#[cfg(test)]
352mod tests {
353 use super::*;
354 use crate::{
355 body::to_bytes,
356 header::{HeaderValue, CONTENT_TYPE, COOKIE},
357 };
358
359 #[test]
360 fn test_debug() {
361 let resp = Response::build(StatusCode::OK)
362 .append_header((COOKIE, HeaderValue::from_static("cookie1=value1; ")))
363 .append_header((COOKIE, HeaderValue::from_static("cookie2=value2; ")))
364 .finish();
365 let dbg = format!("{:?}", resp);
366 assert!(dbg.contains("Response"));
367 }
368
369 #[actix_rt::test]
370 async fn test_into_response() {
371 let res = Response::from("test");
372 assert_eq!(res.status(), StatusCode::OK);
373 assert_eq!(
374 res.headers().get(CONTENT_TYPE).unwrap(),
375 HeaderValue::from_static("text/plain; charset=utf-8")
376 );
377 assert_eq!(res.status(), StatusCode::OK);
378 assert_eq!(to_bytes(res.into_body()).await.unwrap(), &b"test"[..]);
379
380 let res = Response::from(b"test".as_ref());
381 assert_eq!(res.status(), StatusCode::OK);
382 assert_eq!(
383 res.headers().get(CONTENT_TYPE).unwrap(),
384 HeaderValue::from_static("application/octet-stream")
385 );
386 assert_eq!(res.status(), StatusCode::OK);
387 assert_eq!(to_bytes(res.into_body()).await.unwrap(), &b"test"[..]);
388
389 let res = Response::from("test".to_owned());
390 assert_eq!(res.status(), StatusCode::OK);
391 assert_eq!(
392 res.headers().get(CONTENT_TYPE).unwrap(),
393 HeaderValue::from_static("text/plain; charset=utf-8")
394 );
395 assert_eq!(res.status(), StatusCode::OK);
396 assert_eq!(to_bytes(res.into_body()).await.unwrap(), &b"test"[..]);
397
398 let res = Response::from("test".to_owned());
399 assert_eq!(res.status(), StatusCode::OK);
400 assert_eq!(
401 res.headers().get(CONTENT_TYPE).unwrap(),
402 HeaderValue::from_static("text/plain; charset=utf-8")
403 );
404 assert_eq!(res.status(), StatusCode::OK);
405 assert_eq!(to_bytes(res.into_body()).await.unwrap(), &b"test"[..]);
406
407 let b = Bytes::from_static(b"test");
408 let res = Response::from(b);
409 assert_eq!(res.status(), StatusCode::OK);
410 assert_eq!(
411 res.headers().get(CONTENT_TYPE).unwrap(),
412 HeaderValue::from_static("application/octet-stream")
413 );
414 assert_eq!(res.status(), StatusCode::OK);
415 assert_eq!(to_bytes(res.into_body()).await.unwrap(), &b"test"[..]);
416
417 let b = Bytes::from_static(b"test");
418 let res = Response::from(b);
419 assert_eq!(res.status(), StatusCode::OK);
420 assert_eq!(
421 res.headers().get(CONTENT_TYPE).unwrap(),
422 HeaderValue::from_static("application/octet-stream")
423 );
424 assert_eq!(res.status(), StatusCode::OK);
425 assert_eq!(to_bytes(res.into_body()).await.unwrap(), &b"test"[..]);
426
427 let b = BytesMut::from("test");
428 let res = Response::from(b);
429 assert_eq!(res.status(), StatusCode::OK);
430 assert_eq!(
431 res.headers().get(CONTENT_TYPE).unwrap(),
432 HeaderValue::from_static("application/octet-stream")
433 );
434
435 assert_eq!(res.status(), StatusCode::OK);
436 assert_eq!(to_bytes(res.into_body()).await.unwrap(), &b"test"[..]);
437 }
438}