1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use core::convert::TryFrom;
15 use core::mem::take;
16 use std::io::Read;
17 
18 use crate::body::mime::{MixFrom, CR, LF};
19 use crate::error::HttpError;
20 use crate::headers::{Header, HeaderName, HeaderValue, Headers};
21 use crate::AsyncRead;
22 
23 /// `MimePart` is a body part of a Composite MIME body which is defined in
24 /// [`RFC2046`]:  The body must then contain one or more body parts, each
25 /// preceded by a boundary delimiter line, and the last one followed by a
26 /// closing boundary delimiter line. Each body part then consists of a header
27 /// area, a blank line, and a body area.
28 ///
29 /// `MimePart` can be built by [`MimePartBuilder`], then sets headers and body.
30 ///
31 /// [`RFC2046`]: https://www.rfc-editor.org/rfc/rfc2046#section-5.1
32 /// [`MimePartBuilder`]: MimePartBuilder
33 ///
34 /// # Examples
35 /// ```
36 /// use ylong_http::body::MimePart;
37 ///
38 /// let part = MimePart::builder()
39 ///     .header("accept", "text/html")
40 ///     .body_from_bytes(b"9876543210\r\n")
41 ///     .build()
42 ///     .unwrap();
43 /// ```
44 #[derive(Debug, Default, PartialEq)]
45 pub struct MimePart<'a> {
46     // |========================================================================
47     // | Headers [CRLF Field-body]                                             |
48     // |========================================================================
49     // if it has body, it has CRLF.
50     //
51     // [`RFC2046`]: https://www.rfc-editor.org/rfc/rfc2046#section-5.1
52     // body-part := MIME-part-headers [CRLF *OCTET]
53     //               ; Lines in a body-part must not start
54     //               ; with the specified dash-boundary and
55     //               ; the delimiter must not appear anywhere
56     //               ; in the body part.  Note that the
57     //               ; semantics of a body-part differ from
58     //               ; the semantics of a message, as
59     //               ; described in the text.
60     //
61     // OCTET := <any 0-255 octet value>
62     pub(crate) headers: Headers,
63     // all use for encode; owned use for decode
64     pub(crate) body: MixFrom<'a>,
65 }
66 
67 impl<'a> MimePart<'a> {
new() -> Self68     pub(crate) fn new() -> Self {
69         Self {
70             headers: Headers::new(),
71             body: MixFrom::new(),
72         }
73     }
74 
set_headers(&mut self, headers: Headers)75     pub(crate) fn set_headers(&mut self, headers: Headers) {
76         self.headers = headers;
77     }
78 
header<N, V>(&mut self, name: N, value: V) -> Result<&mut Headers, HttpError> where HeaderName: TryFrom<N>, <HeaderName as TryFrom<N>>::Error: Into<HttpError>, HeaderValue: TryFrom<V>, <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,79     pub(crate) fn header<N, V>(&mut self, name: N, value: V) -> Result<&mut Headers, HttpError>
80     where
81         HeaderName: TryFrom<N>,
82         <HeaderName as TryFrom<N>>::Error: Into<HttpError>,
83         HeaderValue: TryFrom<V>,
84         <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,
85     {
86         self.headers.insert(name, value)?;
87         Ok(self.headers_mut())
88     }
89 
append_header<N, V>( &mut self, name: N, value: V, ) -> Result<&mut Headers, HttpError> where HeaderName: TryFrom<N>, <HeaderName as TryFrom<N>>::Error: Into<HttpError>, HeaderValue: TryFrom<V>, <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,90     pub(crate) fn append_header<N, V>(
91         &mut self,
92         name: N,
93         value: V,
94     ) -> Result<&mut Headers, HttpError>
95     where
96         HeaderName: TryFrom<N>,
97         <HeaderName as TryFrom<N>>::Error: Into<HttpError>,
98         HeaderValue: TryFrom<V>,
99         <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,
100     {
101         self.headers.append(name, value)?;
102         Ok(self.headers_mut())
103     }
104 
body_from_owned(&mut self, data: Vec<u8>)105     pub(crate) fn body_from_owned(&mut self, data: Vec<u8>) {
106         self.body.set_owned(data);
107     }
108 
body_from_bytes(&mut self, data: &'a [u8])109     pub(crate) fn body_from_bytes(&mut self, data: &'a [u8]) {
110         self.body.set_bytes(data);
111     }
112 
body_from_reader<T>(&mut self, data: T) where T: Read + Send + Sync + 'static,113     pub(crate) fn body_from_reader<T>(&mut self, data: T)
114     where
115         T: Read + Send + Sync + 'static,
116     {
117         self.body.set_reader(data);
118     }
119 
body_from_async_reader<T>(&mut self, data: T) where T: AsyncRead + Send + Sync + Unpin + 'static,120     pub(crate) fn body_from_async_reader<T>(&mut self, data: T)
121     where
122         T: AsyncRead + Send + Sync + Unpin + 'static,
123     {
124         self.body.set_async_reader(data);
125     }
126 
body_extend_from_slice(&mut self, src: &[u8])127     pub(crate) fn body_extend_from_slice(&mut self, src: &[u8]) {
128         if let MixFrom::Owned { bytes, index: _ } = &mut self.body {
129             bytes.extend_from_slice(src)
130         }
131     }
132 
133     /// Keeps the first len elements and discard the others.
body_truncate(&mut self, len: usize)134     pub(crate) fn body_truncate(&mut self, len: usize) {
135         if let MixFrom::Owned { bytes, index: _ } = &mut self.body {
136             bytes.truncate(len);
137         }
138     }
139 
140     /// Trims the back '\n' or '\r\n' once.
body_trim_crlf_once(&mut self)141     pub(crate) fn body_trim_crlf_once(&mut self) {
142         if let MixFrom::Owned { bytes, index: _ } = &mut self.body {
143             if bytes.ends_with(&[LF]) {
144                 bytes.pop();
145             }
146             if bytes.ends_with(&[CR]) {
147                 bytes.pop();
148             }
149         }
150     }
151 
152     /// Creates a [`MimePartBuilder`].
153     ///
154     /// [`MimePartBuilder`]: MimePartBuilder
155     ///
156     /// # Examples
157     ///
158     /// ```
159     /// use ylong_http::body::MimePart;
160     ///
161     /// let part = MimePart::builder().build().unwrap();
162     /// ```
builder() -> MimePartBuilder<'a>163     pub fn builder() -> MimePartBuilder<'a> {
164         MimePartBuilder::new()
165     }
166 
167     /// Gets the reference of headers.
headers(&self) -> &Headers168     pub fn headers(&self) -> &Headers {
169         &self.headers
170     }
171 
172     /// Gets the mutable reference of headers.
headers_mut(&mut self) -> &mut Headers173     pub fn headers_mut(&mut self) -> &mut Headers {
174         &mut self.headers
175     }
176 
177     /// Gets the ownership of headers by replacing it with an default value.
headers_once(&mut self) -> Headers178     pub fn headers_once(&mut self) -> Headers {
179         take(&mut self.headers)
180     }
181 
182     /// Gets the reference of body.
body(&self) -> Option<&Vec<u8>>183     pub fn body(&self) -> Option<&Vec<u8>> {
184         match &self.body {
185             MixFrom::Owned { bytes, index: _ } => Some(bytes),
186             _ => None,
187         }
188     }
189 
190     /// Gets the mutable reference of body.
body_mut(&mut self) -> Option<&mut Vec<u8>>191     pub fn body_mut(&mut self) -> Option<&mut Vec<u8>> {
192         match &mut self.body {
193             MixFrom::Owned { bytes, index: _ } => Some(bytes),
194             _ => None,
195         }
196     }
197 
198     /// Gets the ownership of body by replacing it with an default value.
body_once(&mut self) -> Option<Vec<u8>>199     pub fn body_once(&mut self) -> Option<Vec<u8>> {
200         match &mut self.body {
201             MixFrom::Owned { bytes, index: _ } => Some(take(bytes)),
202             _ => None,
203         }
204     }
205 }
206 
207 /// `MimePartBuilder` can set a body part of a Composite MIME body [`MimePart`].
208 /// `MimePartBuilder` can set headers and body, then builds a [`MimePart`].
209 ///
210 /// [`MimePart`]: MimePart
211 ///
212 /// # Examples
213 /// ```
214 /// use ylong_http::body::MimePartBuilder;
215 ///
216 /// let part = MimePartBuilder::new()
217 ///     .header("accept", "text/html")
218 ///     .body_from_bytes(b"9876543210\r\n")
219 ///     .build()
220 ///     .unwrap();
221 /// ```
222 pub struct MimePartBuilder<'a> {
223     inner: Result<MimePart<'a>, HttpError>,
224 }
225 
226 impl<'a> MimePartBuilder<'a> {
227     /// Creates a new [`MimePartBuilder`].
228     ///
229     /// [`MimePartBuilder`]: MimePartBuilder
230     ///
231     /// # Examples
232     ///
233     /// ```
234     /// use ylong_http::body::MimePartBuilder;
235     ///
236     /// let part = MimePartBuilder::new();
237     /// ```
new() -> Self238     pub fn new() -> Self {
239         MimePartBuilder {
240             inner: Ok(MimePart::new()),
241         }
242     }
243 
244     /// Sets headers of [`MimePartBuilder`].
245     ///
246     /// [`MimePartBuilder`]: MimePartBuilder
247     ///
248     /// # Examples
249     ///
250     /// ```
251     /// use ylong_http::body::MimePartBuilder;
252     /// use ylong_http::headers::Headers;
253     ///
254     /// let part = MimePartBuilder::new().set_headers({
255     ///     let mut headers = Headers::new();
256     ///     headers.append("accept", "text/html").unwrap();
257     ///     headers.append("key1", "value1").unwrap();
258     ///     headers
259     /// });
260     /// ```
set_headers(mut self, headers: Headers) -> Self261     pub fn set_headers(mut self, headers: Headers) -> Self {
262         self.inner = self.inner.map(move |mut inner| {
263             inner.set_headers(headers);
264             inner
265         });
266         self
267     }
268 
269     /// Inserts header to the MIME body part.
270     ///
271     /// # Examples
272     ///
273     /// ```
274     /// use ylong_http::body::MimePartBuilder;
275     ///
276     /// let part = MimePartBuilder::new()
277     ///     .header("accept", "text/html")
278     ///     .header("accept", "text/plain");
279     /// ```
header<N, V>(mut self, name: N, value: V) -> Self where HeaderName: TryFrom<N>, <HeaderName as TryFrom<N>>::Error: Into<HttpError>, HeaderValue: TryFrom<V>, <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,280     pub fn header<N, V>(mut self, name: N, value: V) -> Self
281     where
282         HeaderName: TryFrom<N>,
283         <HeaderName as TryFrom<N>>::Error: Into<HttpError>,
284         HeaderValue: TryFrom<V>,
285         <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,
286     {
287         self.inner = self.inner.and_then(move |mut inner| {
288             inner.header(name, value)?;
289             Ok(inner)
290         });
291         self
292     }
293 
294     /// Appends header to the MIME body part.
295     ///
296     /// # Examples
297     ///
298     /// ```
299     /// use ylong_http::body::MimePartBuilder;
300     ///
301     /// let part = MimePartBuilder::new()
302     ///     .append_header("accept", "text/html")
303     ///     .append_header("accept", "text/plain");
304     /// ```
append_header<N, V>(mut self, name: N, value: V) -> Self where HeaderName: TryFrom<N>, <HeaderName as TryFrom<N>>::Error: Into<HttpError>, HeaderValue: TryFrom<V>, <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,305     pub fn append_header<N, V>(mut self, name: N, value: V) -> Self
306     where
307         HeaderName: TryFrom<N>,
308         <HeaderName as TryFrom<N>>::Error: Into<HttpError>,
309         HeaderValue: TryFrom<V>,
310         <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,
311     {
312         self.inner = self.inner.and_then(move |mut inner| {
313             inner.append_header(name, value)?;
314             Ok(inner)
315         });
316         self
317     }
318 
319     /// Sets body to the MIME body part, the read content is from `Vec<u8>`.
320     ///
321     /// # Examples
322     ///
323     /// ```
324     /// use ylong_http::body::MimePartBuilder;
325     ///
326     /// let part = MimePartBuilder::new().body_from_owned(b"123456".to_vec());
327     /// ```
body_from_owned(mut self, data: Vec<u8>) -> Self328     pub fn body_from_owned(mut self, data: Vec<u8>) -> Self {
329         self.inner = self.inner.map(move |mut inner| {
330             inner.body_from_owned(data);
331             inner
332         });
333         self
334     }
335 
336     /// Sets body to the MIME body part, the read content is from memory.
337     ///
338     /// # Examples
339     ///
340     /// ```
341     /// use ylong_http::body::MimePartBuilder;
342     ///
343     /// let part = MimePartBuilder::new().body_from_bytes("123456".as_bytes());
344     /// ```
body_from_bytes(mut self, data: &'a [u8]) -> Self345     pub fn body_from_bytes(mut self, data: &'a [u8]) -> Self {
346         self.inner = self.inner.map(move |mut inner| {
347             inner.body_from_bytes(data);
348             inner
349         });
350         self
351     }
352 
353     /// Sets body to the MIME body part, the read content is from a synchronous
354     /// reader.
355     ///
356     /// # Examples
357     ///
358     /// ```
359     /// use ylong_http::body::MimePartBuilder;
360     ///
361     /// let part = MimePartBuilder::new().body_from_reader("123456".as_bytes());
362     /// ```
body_from_reader<T>(mut self, data: T) -> Self where T: Read + Send + Sync + 'static,363     pub fn body_from_reader<T>(mut self, data: T) -> Self
364     where
365         T: Read + Send + Sync + 'static,
366     {
367         self.inner = self.inner.map(move |mut inner| {
368             inner.body_from_reader(data);
369             inner
370         });
371         self
372     }
373 
374     /// Sets body to the MIME body part, the read content is from a asynchronous
375     /// reader.
body_from_async_reader<T>(mut self, data: T) -> Self where T: AsyncRead + Send + Sync + Unpin + 'static,376     pub fn body_from_async_reader<T>(mut self, data: T) -> Self
377     where
378         T: AsyncRead + Send + Sync + Unpin + 'static,
379     {
380         self.inner = self.inner.map(move |mut inner| {
381             inner.body_from_async_reader(data);
382             inner
383         });
384         self
385     }
386 
387     /// Builds a [`MimePart`].
388     ///
389     /// [`MimePart`]: MimePart
390     ///
391     /// # Examples
392     ///
393     /// ```
394     /// use ylong_http::body::MimePartBuilder;
395     ///
396     /// let part = MimePartBuilder::new().build();
397     /// ```
build(self) -> Result<MimePart<'a>, HttpError>398     pub fn build(self) -> Result<MimePart<'a>, HttpError> {
399         self.inner
400     }
401 }
402 
403 impl<'a> Default for MimePartBuilder<'a> {
default() -> Self404     fn default() -> Self {
405         Self::new()
406     }
407 }
408 
409 #[derive(Debug, Eq, PartialEq)]
410 pub(crate) enum PartStatus {
411     Start,
412     Headers,
413     Crlf,
414     Body,
415     End,
416 }
417 
418 #[cfg(test)]
419 mod ut_mime_part {
420     use crate::body::{MimePart, MimePartBuilder};
421     use crate::headers::Headers;
422 
423     /// UT test cases for `MimePartBuilder::new`.
424     ///
425     /// # Brief
426     /// 1. Creates a `MimePartBuilder` by `MimePartBuilder::new`.
427     /// 2. Checks whether the result is correct.
428     #[test]
ut_mime_part_builder_new()429     fn ut_mime_part_builder_new() {
430         let part_builder = MimePartBuilder::new();
431         assert!(part_builder.inner.is_ok());
432     }
433 
434     /// UT test cases for `MimePartBuilder::set_headers`.
435     ///
436     /// # Brief
437     /// 1. Creates a `MimePartBuilder`.
438     /// 2. Sets headers.
439     /// 3. Checks whether the result is correct.
440     #[test]
ut_mime_part_builder_set_headers()441     fn ut_mime_part_builder_set_headers() {
442         let part = MimePartBuilder::new().set_headers({
443             let mut headers = Headers::new();
444             headers.append("accept", "text/html").unwrap();
445             headers.append("key1", "value1").unwrap();
446             headers.append("key2", "value2").unwrap();
447             headers.append("key3", "\"value3\"").unwrap();
448             headers
449         });
450         assert_eq!(part.inner.unwrap().headers, {
451             let mut headers = Headers::new();
452             headers.append("accept", "text/html").unwrap();
453             headers.append("key1", "value1").unwrap();
454             headers.append("key2", "value2").unwrap();
455             headers.append("key3", "\"value3\"").unwrap();
456             headers
457         });
458     }
459 
460     /// UT test cases for `MimePartBuilder::insert_header`.
461     ///
462     /// # Brief
463     /// 1. Creates a `MimePartBuilder`.
464     /// 2. Inserts header.
465     /// 3. Checks whether the result is correct.
466     #[test]
ut_mime_part_builder_insert_header()467     fn ut_mime_part_builder_insert_header() {
468         let part = MimePartBuilder::new()
469             .header("accept", "text/html")
470             .header("accept", "text/plain");
471         assert_eq!(part.inner.unwrap().headers, {
472             let mut headers = Headers::new();
473             headers.append("accept", "text/plain").unwrap();
474             headers
475         });
476     }
477 
478     /// UT test cases for `MimePartBuilder::append_header`.
479     ///
480     /// # Brief
481     /// 1. Creates a `MimePartBuilder`.
482     /// 2. Appends header.
483     /// 3. Checks whether the result is correct.
484     #[test]
ut_mime_part_builder_append_header()485     fn ut_mime_part_builder_append_header() {
486         let part = MimePartBuilder::new()
487             .append_header("accept", "text/html")
488             .append_header("accept", "text/plain");
489         let binding = part.inner.unwrap();
490         let value = binding.headers.get("accept");
491         assert_eq!(value.unwrap().to_string().unwrap(), "text/html, text/plain");
492     }
493 
494     /// UT test cases for `MimePart::builder`.
495     ///
496     /// # Brief
497     /// 1. Creates a `MimePartBuilder` by `MimePart::builder`.
498     /// 2. Sets headers.
499     /// 3. Checks whether the result is correct.
500     #[test]
ut_mime_part_builder()501     fn ut_mime_part_builder() {
502         let part = MimePart::builder()
503             .header("key1", "value1")
504             .build()
505             .unwrap();
506         assert_eq!(part.headers().to_owned(), {
507             let mut headers = Headers::new();
508             headers.insert("key1", "value1").unwrap();
509             headers
510         });
511     }
512 
513     /// UT test cases for `MimePart::headers`.
514     ///
515     /// # Brief
516     /// 1. Creates a `MimePartBuilder` by `MimePart::builder`.
517     /// 2. Sets headers.
518     /// 3. Gets the reference of headers then compares.
519     /// 4. Checks whether the result is correct.
520     #[test]
ut_mime_part_headers()521     fn ut_mime_part_headers() {
522         let part = MimePart::builder()
523             .header("key1", "value1")
524             .build()
525             .unwrap();
526         assert_eq!(part.headers().to_owned(), {
527             let mut headers = Headers::new();
528             headers.insert("key1", "value1").unwrap();
529             headers
530         });
531     }
532 
533     /// UT test cases for `MimePart::headers_mut`.
534     ///
535     /// # Brief
536     /// 1. Creates a `MimePartBuilder` by `MimePart::builder`.
537     /// 2. Sets headers.
538     /// 3. Gets the mutable reference of headers then compares.
539     /// 4. Checks whether the result is correct.
540     #[test]
ut_mime_part_headers_mut()541     fn ut_mime_part_headers_mut() {
542         let part = MimePart::builder()
543             .header("key1", "value1")
544             .build()
545             .unwrap();
546         assert_eq!(part.headers().to_owned(), {
547             let mut headers = Headers::new();
548             headers.insert("key1", "value1").unwrap();
549             headers
550         });
551     }
552 
553     /// UT test cases for `MimePart::headers_once`.
554     ///
555     /// # Brief
556     /// 1. Creates a `MimePartBuilder` by `MimePart::builder`.
557     /// 2. Sets headers.
558     /// 3. Gets the ownership of headers then compares.
559     /// 4. Checks whether the result is correct.
560     #[test]
ut_mime_part_headers_once()561     fn ut_mime_part_headers_once() {
562         let mut part = MimePart::builder()
563             .header("key1", "value1")
564             .build()
565             .unwrap();
566         assert_eq!(part.headers_once(), {
567             let mut headers = Headers::new();
568             headers.insert("key1", "value1").unwrap();
569             headers
570         });
571     }
572 
573     /// UT test cases for `MimePart::body`.
574     ///
575     /// # Brief
576     /// 1. Creates a `MimePartBuilder` by `MimePart::builder`.
577     /// 2. Sets body.
578     /// 3. Gets the reference of body then compares.
579     /// 4. Checks whether the result is correct.
580     #[test]
ut_mime_part_body()581     fn ut_mime_part_body() {
582         let part = MimePart::builder()
583             .body_from_owned(b"1111".to_vec())
584             .build()
585             .unwrap();
586         assert_eq!(part.body().unwrap(), b"1111");
587     }
588 
589     /// UT test cases for `MimePart::body_mut`.
590     ///
591     /// # Brief
592     /// 1. Creates a `MimePartBuilder` by `MimePart::builder`.
593     /// 2. Sets body.
594     /// 3. Gets the mutable reference of body then compares.
595     /// 4. Checks whether the result is correct.
596     #[test]
ut_mime_part_body_mut()597     fn ut_mime_part_body_mut() {
598         let mut part = MimePart::builder()
599             .body_from_owned(b"1111".to_vec())
600             .build()
601             .unwrap();
602         part.body_mut().unwrap()[0] = b'2';
603         assert_eq!(part.body().unwrap(), b"2111");
604     }
605 
606     /// UT test cases for `MimePart::body_once`.
607     ///
608     /// # Brief
609     /// 1. Creates a `MimePartBuilder` by `MimePart::builder`.
610     /// 2. Sets body.
611     /// 3. Gets the ownership of body then compares.
612     /// 4. Checks whether the result is correct.
613     #[test]
ut_mime_part_body_once()614     fn ut_mime_part_body_once() {
615         let mut part = MimePart::builder()
616             .body_from_owned(b"1111".to_vec())
617             .build()
618             .unwrap();
619         assert_eq!(part.body_once().unwrap(), b"1111".to_vec());
620         assert_eq!(part.body().unwrap(), b"");
621     }
622 }
623