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}