boluo_core/response/mod.rs
1//! HTTP 响应。
2
3mod into_response;
4
5pub use into_response::{HeaderResponseError, IntoResponse, IntoResponseParts};
6
7use std::convert::TryFrom;
8
9use http::header::{HeaderMap, HeaderName, HeaderValue};
10use http::status::StatusCode;
11use http::version::Version;
12use http::{Extensions, Result};
13use sync_wrapper::SyncWrapper;
14
15use crate::body::Body;
16
17/// HTTP 响应。
18///
19/// HTTP 响应由头部和可选的主体组成。主体是泛型的,允许任意类型来表示 HTTP 响应的主体。
20#[derive(Default)]
21pub struct Response<T = Body> {
22 head: ResponseParts,
23 body: SyncWrapper<T>,
24}
25
26/// HTTP 响应的头部。
27///
28/// HTTP 响应的头部由状态码、版本、一组标头和扩展组成。
29#[derive(Default, Clone)]
30pub struct ResponseParts {
31 /// HTTP 响应的状态码。
32 pub status: StatusCode,
33 /// HTTP 响应的版本。
34 pub version: Version,
35 /// HTTP 响应的标头集。
36 pub headers: HeaderMap<HeaderValue>,
37 /// HTTP 响应的扩展。
38 pub extensions: Extensions,
39}
40
41/// HTTP 响应的构建器。
42#[derive(Debug)]
43pub struct ResponseBuilder {
44 inner: Result<Response<()>>,
45}
46
47impl Response<()> {
48 /// 创建新的构建器以构建响应。
49 ///
50 /// # 例子
51 ///
52 /// ```
53 /// use boluo_core::response::Response;
54 ///
55 /// let response = Response::builder()
56 /// .status(200)
57 /// .header("X-Custom-Foo", "Bar")
58 /// .body(())
59 /// .unwrap();
60 /// ```
61 #[inline]
62 pub fn builder() -> ResponseBuilder {
63 ResponseBuilder::new()
64 }
65}
66
67impl<T> Response<T> {
68 /// 使用给定的主体创建一个空白的响应。
69 ///
70 /// 此响应的头部将被设置为默认值。
71 ///
72 /// # 例子
73 ///
74 /// ```
75 /// use boluo_core::http::StatusCode;
76 /// use boluo_core::response::Response;
77 ///
78 /// let mut response = Response::new("hello world");
79 ///
80 /// assert_eq!(response.status(), StatusCode::OK);
81 /// assert_eq!(*response.body_mut(), "hello world");
82 /// ```
83 #[inline]
84 pub fn new(body: T) -> Response<T> {
85 Response {
86 head: ResponseParts::new(),
87 body: SyncWrapper::new(body),
88 }
89 }
90
91 /// 使用给定的头部和主体创建响应。
92 ///
93 /// # 例子
94 ///
95 /// ```
96 /// use boluo_core::http::StatusCode;
97 /// use boluo_core::response::Response;
98 ///
99 /// let response = Response::new("hello world");
100 /// let (mut parts, body) = response.into_inner();
101 ///
102 /// parts.status = StatusCode::BAD_REQUEST;
103 /// let mut response = Response::from_parts(parts, body);
104 ///
105 /// assert_eq!(response.status(), StatusCode::BAD_REQUEST);
106 /// assert_eq!(*response.body_mut(), "hello world");
107 /// ```
108 #[inline]
109 pub fn from_parts(parts: ResponseParts, body: T) -> Response<T> {
110 Response {
111 head: parts,
112 body: SyncWrapper::new(body),
113 }
114 }
115
116 /// 获取响应的状态码。
117 ///
118 /// # 例子
119 ///
120 /// ```
121 /// use boluo_core::http::StatusCode;
122 /// use boluo_core::response::Response;
123 ///
124 /// let response: Response<()> = Response::default();
125 ///
126 /// assert_eq!(response.status(), StatusCode::OK);
127 /// ```
128 #[inline]
129 pub fn status(&self) -> StatusCode {
130 self.head.status
131 }
132
133 /// 获取响应的状态码的可变引用。
134 ///
135 /// # 例子
136 ///
137 /// ```
138 /// use boluo_core::http::StatusCode;
139 /// use boluo_core::response::Response;
140 ///
141 /// let mut response: Response<()> = Response::default();
142 /// *response.status_mut() = StatusCode::CREATED;
143 ///
144 /// assert_eq!(response.status(), StatusCode::CREATED);
145 /// ```
146 #[inline]
147 pub fn status_mut(&mut self) -> &mut StatusCode {
148 &mut self.head.status
149 }
150
151 /// 获取响应的 HTTP 版本。
152 ///
153 /// # 例子
154 ///
155 /// ```
156 /// use boluo_core::http::Version;
157 /// use boluo_core::response::Response;
158 ///
159 /// let response: Response<()> = Response::default();
160 ///
161 /// assert_eq!(response.version(), Version::HTTP_11);
162 /// ```
163 #[inline]
164 pub fn version(&self) -> Version {
165 self.head.version
166 }
167
168 /// 获取响应的 HTTP 版本的可变引用。
169 ///
170 /// # 例子
171 ///
172 /// ```
173 /// use boluo_core::http::Version;
174 /// use boluo_core::response::Response;
175 ///
176 /// let mut response: Response<()> = Response::default();
177 /// *response.version_mut() = Version::HTTP_2;
178 ///
179 /// assert_eq!(response.version(), Version::HTTP_2);
180 /// ```
181 #[inline]
182 pub fn version_mut(&mut self) -> &mut Version {
183 &mut self.head.version
184 }
185
186 /// 获取响应的标头集的引用。
187 ///
188 /// # 例子
189 ///
190 /// ```
191 /// use boluo_core::response::Response;
192 ///
193 /// let response: Response<()> = Response::default();
194 ///
195 /// assert!(response.headers().is_empty());
196 /// ```
197 #[inline]
198 pub fn headers(&self) -> &HeaderMap<HeaderValue> {
199 &self.head.headers
200 }
201
202 /// 获取响应的标头集的可变引用。
203 ///
204 /// # 例子
205 ///
206 /// ```
207 /// use boluo_core::http::header::*;
208 /// use boluo_core::response::Response;
209 ///
210 /// let mut response: Response<()> = Response::default();
211 /// response.headers_mut().insert(HOST, HeaderValue::from_static("world"));
212 ///
213 /// assert!(!response.headers().is_empty());
214 /// ```
215 #[inline]
216 pub fn headers_mut(&mut self) -> &mut HeaderMap<HeaderValue> {
217 &mut self.head.headers
218 }
219
220 /// 获取响应的扩展的引用。
221 ///
222 /// # 例子
223 ///
224 /// ```
225 /// use boluo_core::response::Response;
226 ///
227 /// let response: Response<()> = Response::default();
228 ///
229 /// assert!(response.extensions().get::<i32>().is_none());
230 /// ```
231 #[inline]
232 pub fn extensions(&self) -> &Extensions {
233 &self.head.extensions
234 }
235
236 /// 获取响应的扩展的可变引用。
237 ///
238 /// # 例子
239 ///
240 /// ```
241 /// use boluo_core::response::Response;
242 ///
243 /// let mut response: Response<()> = Response::default();
244 /// response.extensions_mut().insert("hello");
245 ///
246 /// assert_eq!(response.extensions().get(), Some(&"hello"));
247 /// ```
248 #[inline]
249 pub fn extensions_mut(&mut self) -> &mut Extensions {
250 &mut self.head.extensions
251 }
252
253 /// 获取响应的主体的可变引用。
254 ///
255 /// # 例子
256 ///
257 /// ```
258 /// use boluo_core::response::Response;
259 ///
260 /// let mut response: Response<String> = Response::default();
261 /// response.body_mut().push_str("hello world");
262 ///
263 /// assert!(!response.body_mut().is_empty());
264 /// ```
265 #[inline]
266 pub fn body_mut(&mut self) -> &mut T {
267 self.body.get_mut()
268 }
269
270 /// 消耗响应,返回响应的主体。
271 ///
272 /// # 例子
273 ///
274 /// ```
275 /// use boluo_core::response::Response;
276 ///
277 /// let response = Response::new(10);
278 /// let body = response.into_body();
279 ///
280 /// assert_eq!(body, 10);
281 /// ```
282 #[inline]
283 pub fn into_body(self) -> T {
284 self.body.into_inner()
285 }
286
287 /// 获取响应的头部的引用。
288 ///
289 /// # 例子
290 ///
291 /// ```
292 /// use boluo_core::http::StatusCode;
293 /// use boluo_core::response::Response;
294 ///
295 /// let response: Response<()> = Response::default();
296 ///
297 /// assert_eq!(response.parts().status, StatusCode::OK);
298 /// ```
299 #[inline]
300 pub fn parts(&self) -> &ResponseParts {
301 &self.head
302 }
303
304 /// 获取响应的头部的可变引用。
305 ///
306 /// # 例子
307 ///
308 /// ```
309 /// use boluo_core::http::StatusCode;
310 /// use boluo_core::response::Response;
311 ///
312 /// let mut response: Response<()> = Response::default();
313 /// response.parts_mut().status = StatusCode::CREATED;
314 ///
315 /// assert_eq!(response.status(), StatusCode::CREATED);
316 /// ```
317 #[inline]
318 pub fn parts_mut(&mut self) -> &mut ResponseParts {
319 &mut self.head
320 }
321
322 /// 消耗响应,返回响应的头部。
323 ///
324 /// # 例子
325 ///
326 /// ```
327 /// use boluo_core::http::StatusCode;
328 /// use boluo_core::response::Response;
329 ///
330 /// let response = Response::new(());
331 /// let parts = response.into_parts();
332 ///
333 /// assert_eq!(parts.status, StatusCode::OK);
334 /// ```
335 #[inline]
336 pub fn into_parts(self) -> ResponseParts {
337 self.head
338 }
339
340 /// 消耗响应,返回响应的头部和主体。
341 ///
342 /// # 例子
343 ///
344 /// ```
345 /// use boluo_core::http::StatusCode;
346 /// use boluo_core::response::Response;
347 ///
348 /// let response: Response<()> = Response::default();
349 /// let (parts, body) = response.into_inner();
350 ///
351 /// assert_eq!(parts.status, StatusCode::OK);
352 /// ```
353 #[inline]
354 pub fn into_inner(self) -> (ResponseParts, T) {
355 (self.head, self.body.into_inner())
356 }
357
358 /// 消耗响应,返回带有给定主体的新响应,其主体为传入闭包的返回值。
359 ///
360 /// # 例子
361 ///
362 /// ```
363 /// use boluo_core::response::Response;
364 ///
365 /// let response = Response::builder().body("some string").unwrap();
366 /// let mut mapped_response: Response<&[u8]> = response.map(|b| {
367 /// assert_eq!(b, "some string");
368 /// b.as_bytes()
369 /// });
370 ///
371 /// assert_eq!(mapped_response.body_mut(), &"some string".as_bytes());
372 /// ```
373 #[inline]
374 pub fn map<F, U>(self, f: F) -> Response<U>
375 where
376 F: FnOnce(T) -> U,
377 {
378 Response {
379 body: SyncWrapper::new(f(self.body.into_inner())),
380 head: self.head,
381 }
382 }
383}
384
385impl<T: std::fmt::Debug> std::fmt::Debug for Response<T> {
386 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
387 f.debug_struct("Response")
388 .field("status", &self.status())
389 .field("version", &self.version())
390 .field("headers", self.headers())
391 .field("body", &std::any::type_name::<T>())
392 .finish()
393 }
394}
395
396impl ResponseParts {
397 fn new() -> ResponseParts {
398 ResponseParts {
399 status: StatusCode::default(),
400 version: Version::default(),
401 headers: HeaderMap::default(),
402 extensions: Extensions::default(),
403 }
404 }
405}
406
407impl std::fmt::Debug for ResponseParts {
408 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
409 f.debug_struct("ResponseParts")
410 .field("status", &self.status)
411 .field("version", &self.version)
412 .field("headers", &self.headers)
413 .finish()
414 }
415}
416
417impl ResponseBuilder {
418 /// 创建构建器的默认实例以构建响应。
419 ///
420 /// # 例子
421 ///
422 /// ```
423 /// use boluo_core::response::ResponseBuilder;
424 ///
425 /// let response = ResponseBuilder::new()
426 /// .status(200)
427 /// .body(())
428 /// .unwrap();
429 /// ```
430 #[inline]
431 pub fn new() -> ResponseBuilder {
432 ResponseBuilder::default()
433 }
434
435 /// 设置响应的状态码。
436 ///
437 /// 默认情况下,这是 `200`。
438 ///
439 /// # 例子
440 ///
441 /// ```
442 /// use boluo_core::response::Response;
443 ///
444 /// let response = Response::builder()
445 /// .status(200)
446 /// .body(())
447 /// .unwrap();
448 /// ```
449 pub fn status<T>(self, status: T) -> ResponseBuilder
450 where
451 StatusCode: TryFrom<T>,
452 <StatusCode as TryFrom<T>>::Error: Into<http::Error>,
453 {
454 self.and_then(move |mut res| {
455 let status = TryFrom::try_from(status).map_err(Into::into)?;
456 res.head.status = status;
457 Ok(res)
458 })
459 }
460
461 /// 获取响应的状态码的引用。
462 ///
463 /// 默认情况下,这是 `200`。如果构建器有错误,则返回 [`None`]。
464 ///
465 /// # 例子
466 ///
467 /// ```
468 /// use boluo_core::http::StatusCode;
469 /// use boluo_core::response::Response;
470 ///
471 /// let mut res = Response::builder();
472 /// assert_eq!(res.status_ref().unwrap(), &StatusCode::OK);
473 ///
474 /// res = res.status(StatusCode::BAD_REQUEST);
475 /// assert_eq!(res.status_ref().unwrap(), &StatusCode::BAD_REQUEST);
476 /// ```
477 pub fn status_ref(&self) -> Option<&StatusCode> {
478 self.inner.as_ref().ok().map(|res| &res.head.status)
479 }
480
481 /// 获取响应的状态码的可变引用。
482 ///
483 /// 默认情况下,这是 `200`。如果构建器有错误,则返回 [`None`]。
484 ///
485 /// # 例子
486 ///
487 /// ```
488 /// use boluo_core::http::StatusCode;
489 /// use boluo_core::response::Response;
490 ///
491 /// let mut res = Response::builder();
492 /// assert_eq!(res.status_ref().unwrap(), &StatusCode::OK);
493 ///
494 /// *res.status_mut().unwrap() = StatusCode::BAD_REQUEST;
495 /// assert_eq!(res.status_ref().unwrap(), &StatusCode::BAD_REQUEST);
496 /// ```
497 pub fn status_mut(&mut self) -> Option<&mut StatusCode> {
498 self.inner.as_mut().ok().map(|res| &mut res.head.status)
499 }
500
501 /// 设置响应的 HTTP 版本。
502 ///
503 /// 默认情况下,这是 `HTTP/1.1`。
504 ///
505 /// # 例子
506 ///
507 /// ```
508 /// use boluo_core::http::Version;
509 /// use boluo_core::response::Response;
510 ///
511 /// let response = Response::builder()
512 /// .version(Version::HTTP_2)
513 /// .body(())
514 /// .unwrap();
515 /// ```
516 pub fn version(self, version: Version) -> ResponseBuilder {
517 self.and_then(move |mut res| {
518 res.head.version = version;
519 Ok(res)
520 })
521 }
522
523 /// 获取响应的 HTTP 版本的引用。
524 ///
525 /// 默认情况下,这是 `HTTP/1.1`。如果构建器有错误,则返回 [`None`]。
526 ///
527 /// # 例子
528 ///
529 /// ```
530 /// use boluo_core::http::Version;
531 /// use boluo_core::response::Response;
532 ///
533 /// let mut res = Response::builder();
534 /// assert_eq!(res.version_ref().unwrap(), &Version::HTTP_11);
535 ///
536 /// res = res.version(Version::HTTP_2);
537 /// assert_eq!(res.version_ref().unwrap(), &Version::HTTP_2);
538 /// ```
539 pub fn version_ref(&self) -> Option<&Version> {
540 self.inner.as_ref().ok().map(|res| &res.head.version)
541 }
542
543 /// 获取响应的 HTTP 版本的可变引用。
544 ///
545 /// 默认情况下,这是 `HTTP/1.1`。如果构建器有错误,则返回 [`None`]。
546 ///
547 /// # 例子
548 ///
549 /// ```
550 /// use boluo_core::http::Version;
551 /// use boluo_core::response::Response;
552 ///
553 /// let mut res = Response::builder();
554 /// assert_eq!(res.version_ref().unwrap(), &Version::HTTP_11);
555 ///
556 /// *res.version_mut().unwrap() = Version::HTTP_2;
557 /// assert_eq!(res.version_ref().unwrap(), &Version::HTTP_2);
558 /// ```
559 pub fn version_mut(&mut self) -> Option<&mut Version> {
560 self.inner.as_mut().ok().map(|res| &mut res.head.version)
561 }
562
563 /// 将标头追加到响应中。
564 ///
565 /// 此函数将提供的键值对追加到响应内部的 [`HeaderMap`] 中。本质上,
566 /// 这相当于调用 [`HeaderMap::append`]。
567 ///
568 /// # 例子
569 ///
570 /// ```
571 /// use boluo_core::response::Response;
572 ///
573 /// let response = Response::builder()
574 /// .header("Content-Type", "text/html")
575 /// .header("X-Custom-Foo", "bar")
576 /// .header("Content-Length", 0)
577 /// .body(())
578 /// .unwrap();
579 /// ```
580 pub fn header<K, V>(self, key: K, value: V) -> ResponseBuilder
581 where
582 HeaderName: TryFrom<K>,
583 <HeaderName as TryFrom<K>>::Error: Into<http::Error>,
584 HeaderValue: TryFrom<V>,
585 <HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
586 {
587 self.and_then(move |mut res| {
588 let name = <HeaderName as TryFrom<K>>::try_from(key).map_err(Into::into)?;
589 let value = <HeaderValue as TryFrom<V>>::try_from(value).map_err(Into::into)?;
590 res.head.headers.append(name, value);
591 Ok(res)
592 })
593 }
594
595 /// 获取响应的标头集的引用。
596 ///
597 /// 如果构建器有错误,则返回 [`None`]。
598 ///
599 /// # 例子
600 ///
601 /// ```
602 /// use boluo_core::response::Response;
603 ///
604 /// let res = Response::builder()
605 /// .header("Accept", "text/html")
606 /// .header("X-Custom-Foo", "bar");
607 ///
608 /// let headers = res.headers_ref().unwrap();
609 ///
610 /// assert_eq!(headers["Accept"], "text/html");
611 /// assert_eq!(headers["X-Custom-Foo"], "bar");
612 /// ```
613 pub fn headers_ref(&self) -> Option<&HeaderMap<HeaderValue>> {
614 self.inner.as_ref().ok().map(|res| &res.head.headers)
615 }
616
617 /// 获取响应的标头集的可变引用。
618 ///
619 /// 如果构建器有错误,则返回 [`None`]。
620 ///
621 /// # 例子
622 ///
623 /// ```
624 /// use boluo_core::http::HeaderValue;
625 /// use boluo_core::response::Response;
626 ///
627 /// let mut res = Response::builder();
628 ///
629 /// let headers = res.headers_mut().unwrap();
630 /// headers.insert("Accept", HeaderValue::from_static("text/html"));
631 /// headers.insert("X-Custom-Foo", HeaderValue::from_static("bar"));
632 ///
633 /// let headers = res.headers_ref().unwrap();
634 /// assert_eq!( headers["Accept"], "text/html" );
635 /// assert_eq!( headers["X-Custom-Foo"], "bar" );
636 /// ```
637 pub fn headers_mut(&mut self) -> Option<&mut HeaderMap<HeaderValue>> {
638 self.inner.as_mut().ok().map(|res| &mut res.head.headers)
639 }
640
641 /// 将一个类型添加到响应的扩展中。
642 ///
643 /// # 例子
644 ///
645 /// ```
646 /// use boluo_core::response::Response;
647 ///
648 /// let response = Response::builder()
649 /// .extension("My Extension")
650 /// .body(())
651 /// .unwrap();
652 ///
653 /// assert_eq!(response.extensions().get::<&'static str>(),
654 /// Some(&"My Extension"));
655 /// ```
656 pub fn extension<T>(self, extension: T) -> ResponseBuilder
657 where
658 T: Clone + Send + Sync + 'static,
659 {
660 self.and_then(move |mut res| {
661 res.head.extensions.insert(extension);
662 Ok(res)
663 })
664 }
665
666 /// 获取响应的扩展的引用。
667 ///
668 /// 如果构建器有错误,则返回 [`None`]。
669 ///
670 /// # 例子
671 ///
672 /// ```
673 /// use boluo_core::response::Response;
674 ///
675 /// let res = Response::builder().extension("My Extension").extension(5u32);
676 /// let extensions = res.extensions_ref().unwrap();
677 ///
678 /// assert_eq!(extensions.get::<&'static str>(), Some(&"My Extension"));
679 /// assert_eq!(extensions.get::<u32>(), Some(&5u32));
680 /// ```
681 pub fn extensions_ref(&self) -> Option<&Extensions> {
682 self.inner.as_ref().ok().map(|res| &res.head.extensions)
683 }
684
685 /// 获取响应的扩展的可变引用。
686 ///
687 /// 如果构建器有错误,则返回 [`None`]。
688 ///
689 /// # 例子
690 ///
691 /// ```
692 /// use boluo_core::response::Response;
693 ///
694 /// let mut res = Response::builder().extension("My Extension");
695 /// let mut extensions = res.extensions_mut().unwrap();
696 /// assert_eq!(extensions.get::<&'static str>(), Some(&"My Extension"));
697 ///
698 /// extensions.insert(5u32);
699 /// assert_eq!(extensions.get::<u32>(), Some(&5u32));
700 /// ```
701 pub fn extensions_mut(&mut self) -> Option<&mut Extensions> {
702 self.inner.as_mut().ok().map(|res| &mut res.head.extensions)
703 }
704
705 /// 消耗构建器,使用给定的主体构建响应。
706 ///
707 /// # 错误
708 ///
709 /// 如果之前配置的任意一个参数发生错误,则在调用此函数时将返回错误。
710 ///
711 /// # 例子
712 ///
713 /// ```
714 /// use boluo_core::response::Response;
715 ///
716 /// let response = Response::builder()
717 /// .body(())
718 /// .unwrap();
719 /// ```
720 pub fn body<T>(self, body: T) -> Result<Response<T>> {
721 self.inner.map(move |res| res.map(|_| body))
722 }
723
724 fn and_then<F>(self, func: F) -> Self
725 where
726 F: FnOnce(Response<()>) -> Result<Response<()>>,
727 {
728 ResponseBuilder {
729 inner: self.inner.and_then(func),
730 }
731 }
732}
733
734impl Default for ResponseBuilder {
735 #[inline]
736 fn default() -> ResponseBuilder {
737 ResponseBuilder {
738 inner: Ok(Response::new(())),
739 }
740 }
741}