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