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 //! HTTP [`Header`][header], which is called `Field` in [`RFC9110`]. 15 //! 16 //! The module provides [`Header`], [`HeaderName`], [`HeaderValue`], [`Headers`] 17 //! and a number of types used for interacting with `Headers`. 18 //! 19 //! These types allow representing both `HTTP/1.1` and `HTTP/2` headers. 20 //! 21 //! [header]: https://httpwg.org/specs/rfc9110.html#fields 22 //! [`RFC9110`]: https://httpwg.org/specs/rfc9110.html 23 //! [`Header`]: Header 24 //! [`HeaderName`]: HeaderName 25 //! [`HeaderValue`]: HeaderValue 26 //! [`Headers`]: Headers 27 //! 28 //! # Examples 29 //! 30 //! ``` 31 //! use ylong_http::headers::Headers; 32 //! 33 //! let mut headers = Headers::new(); 34 //! headers.insert("Accept", "text/html").unwrap(); 35 //! headers.insert("Content-Length", "3495").unwrap(); 36 //! 37 //! assert_eq!( 38 //! headers.get("accept").unwrap().to_str().unwrap(), 39 //! "text/html" 40 //! ); 41 //! assert_eq!( 42 //! headers.get("content-length").unwrap().to_str().unwrap(), 43 //! "3495" 44 //! ); 45 //! ``` 46 47 use core::convert::TryFrom; 48 use core::{fmt, slice, str}; 49 use std::collections::hash_map::Entry; 50 use std::collections::{hash_map, HashMap}; 51 52 use crate::error::{ErrorKind, HttpError}; 53 54 /// HTTP `Header`, which consists of [`HeaderName`] and [`HeaderValue`]. 55 /// 56 /// `Header` is called `Field` in RFC9110. HTTP uses fields to provide data in 57 /// the form of extensible name/value pairs with a registered key namespace. 58 /// 59 /// [`HeaderName`]: HeaderName 60 /// [`HeaderValue`]: HeaderValue 61 /// 62 /// # Examples 63 /// 64 /// ``` 65 /// use core::convert::TryFrom; 66 /// 67 /// use ylong_http::headers::Header; 68 /// 69 /// // This header name string will be normalized to lowercase. 70 /// let header = Header::try_from(("Example-Field", "Foo")).unwrap(); 71 /// assert_eq!(header.name().as_bytes(), b"example-field"); 72 /// 73 /// // All characters of this header string can be displayed, so the `to_string` 74 /// // interface can be used to output. 75 /// assert_eq!(header.value().to_str().unwrap(), "Foo"); 76 /// ``` 77 #[derive(Clone, Debug, Eq, PartialEq)] 78 pub struct Header { 79 name: HeaderName, 80 value: HeaderValue, 81 } 82 83 impl Header { 84 /// Combines a `HeaderName` and a `HeaderValue` into a `Header`. 85 /// 86 /// # Examples 87 /// 88 /// ``` 89 /// use ylong_http::headers::{Header, HeaderName, HeaderValue}; 90 /// 91 /// let name = HeaderName::from_bytes(b"Example-Field").unwrap(); 92 /// let value = HeaderValue::from_bytes(b"Foo").unwrap(); 93 /// 94 /// let header = Header::from_raw_parts(name, value); 95 /// assert_eq!(header.name().as_bytes(), b"example-field"); 96 /// assert_eq!(header.value().to_str().unwrap(), "Foo"); 97 /// ``` from_raw_parts(name: HeaderName, value: HeaderValue) -> Self98 pub fn from_raw_parts(name: HeaderName, value: HeaderValue) -> Self { 99 Self { name, value } 100 } 101 102 /// Gets a reference to the underlying `HeaderName`. 103 /// 104 /// # Examples 105 /// 106 /// ``` 107 /// use core::convert::TryFrom; 108 /// 109 /// use ylong_http::headers::Header; 110 /// 111 /// let header = Header::try_from(("Example-Field", "Foo")).unwrap(); 112 /// 113 /// let name = header.name(); 114 /// assert_eq!(name.as_bytes(), b"example-field"); 115 /// ``` name(&self) -> &HeaderName116 pub fn name(&self) -> &HeaderName { 117 &self.name 118 } 119 120 /// Gets a reference to the underlying `HeaderValue`. 121 /// 122 /// # Examples 123 /// 124 /// ``` 125 /// use core::convert::TryFrom; 126 /// 127 /// use ylong_http::headers::Header; 128 /// 129 /// let header = Header::try_from(("Example-Field", "Foo")).unwrap(); 130 /// 131 /// let value = header.value(); 132 /// assert_eq!(value.to_str().unwrap(), "Foo"); 133 /// ``` value(&self) -> &HeaderValue134 pub fn value(&self) -> &HeaderValue { 135 &self.value 136 } 137 138 /// Consumes this `Header`, get the underlying `HeaderName` and 139 /// `HeaderValue`. 140 /// 141 /// # Examples 142 /// 143 /// ``` 144 /// use core::convert::TryFrom; 145 /// 146 /// use ylong_http::headers::Header; 147 /// 148 /// let header = Header::try_from(("Example-Field", "Foo")).unwrap(); 149 /// let (name, value) = header.into_parts(); 150 /// 151 /// assert_eq!(name.as_bytes(), b"example-field"); 152 /// assert_eq!(value.to_str().unwrap(), "Foo"); 153 /// ``` into_parts(self) -> (HeaderName, HeaderValue)154 pub fn into_parts(self) -> (HeaderName, HeaderValue) { 155 (self.name, self.value) 156 } 157 } 158 159 impl<N, V> TryFrom<(N, V)> for Header 160 where 161 HeaderName: TryFrom<N>, 162 <HeaderName as TryFrom<N>>::Error: Into<HttpError>, 163 HeaderValue: TryFrom<V>, 164 <HeaderValue as TryFrom<V>>::Error: Into<HttpError>, 165 { 166 type Error = HttpError; 167 try_from(pair: (N, V)) -> Result<Self, Self::Error>168 fn try_from(pair: (N, V)) -> Result<Self, Self::Error> { 169 Ok(Self::from_raw_parts( 170 HeaderName::try_from(pair.0).map_err(Into::into)?, 171 HeaderValue::try_from(pair.1).map_err(Into::into)?, 172 )) 173 } 174 } 175 176 /// HTTP `Header Name`, which is called [`Field Name`] in RFC9110. 177 /// 178 /// A field name labels the corresponding field value as having the semantics 179 /// defined by that name. 180 /// 181 /// [`Field Name`]: https://httpwg.org/specs/rfc9110.html#fields.names 182 /// 183 /// # Examples 184 /// 185 /// ``` 186 /// use ylong_http::headers::HeaderName; 187 /// 188 /// let name = HeaderName::from_bytes(b"Example-Field").unwrap(); 189 /// assert_eq!(name.as_bytes(), b"example-field"); 190 /// ``` 191 // TODO: `StandardHeader` implementation. 192 #[derive(Clone, Debug, Eq, Hash, PartialEq)] 193 pub struct HeaderName { 194 name: String, 195 } 196 197 impl HeaderName { 198 /// Converts a slice of bytes to a `HeaderName`. 199 /// 200 /// Since `HeaderName` is case-insensitive, characters of the input will be 201 /// checked and then converted to lowercase. 202 /// 203 /// # Examples 204 /// 205 /// ``` 206 /// use ylong_http::headers::HeaderName; 207 /// 208 /// let name = HeaderName::from_bytes(b"Example-Field").unwrap(); 209 /// ``` from_bytes(bytes: &[u8]) -> Result<Self, HttpError>210 pub fn from_bytes(bytes: &[u8]) -> Result<Self, HttpError> { 211 Ok(Self { 212 name: Self::normalize(bytes)?, 213 }) 214 } 215 216 /// Returns a bytes representation of the `HeaderName`. 217 /// 218 /// # Examples 219 /// 220 /// ``` 221 /// use ylong_http::headers::HeaderName; 222 /// 223 /// let name = HeaderName::from_bytes(b"Example-Field").unwrap(); 224 /// let bytes = name.as_bytes(); 225 /// assert_eq!(bytes, b"example-field"); 226 /// ``` as_bytes(&self) -> &[u8]227 pub fn as_bytes(&self) -> &[u8] { 228 self.name.as_bytes() 229 } 230 231 // Returns a Vec<u8> of the `HeaderName`. into_bytes(self) -> Vec<u8>232 pub(crate) fn into_bytes(self) -> Vec<u8> { 233 self.name.into_bytes() 234 } 235 236 /// Normalizes the input bytes. normalize(input: &[u8]) -> Result<String, HttpError>237 fn normalize(input: &[u8]) -> Result<String, HttpError> { 238 let mut dst = Vec::new(); 239 for b in input.iter() { 240 // HEADER_CHARS maps all bytes to valid single-byte UTF-8. 241 let b = HEADER_CHARS[*b as usize]; 242 if b == 0 { 243 return Err(ErrorKind::InvalidInput.into()); 244 } 245 dst.push(b); 246 } 247 Ok(unsafe { String::from_utf8_unchecked(dst) }) 248 } 249 } 250 251 impl ToString for HeaderName { to_string(&self) -> String252 fn to_string(&self) -> String { 253 self.name.clone() 254 } 255 } 256 257 impl TryFrom<&str> for HeaderName { 258 type Error = HttpError; 259 try_from(name: &str) -> Result<Self, Self::Error>260 fn try_from(name: &str) -> Result<Self, Self::Error> { 261 Self::from_bytes(name.as_bytes()) 262 } 263 } 264 265 impl TryFrom<&[u8]> for HeaderName { 266 type Error = HttpError; 267 try_from(bytes: &[u8]) -> Result<Self, Self::Error>268 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> { 269 Self::from_bytes(bytes) 270 } 271 } 272 273 /// HTTP `Header Value`, which is called [`Field Value`] in RFC9110. 274 /// 275 /// HTTP field values consist of a sequence of characters in a format defined by 276 /// the field's grammar. 277 /// 278 /// [`Field Value`]: https://httpwg.org/specs/rfc9110.html#fields.values 279 /// 280 /// # Examples 281 /// 282 /// ``` 283 /// use ylong_http::headers::HeaderValue; 284 /// 285 /// let mut value = HeaderValue::from_bytes(b"text/html").unwrap(); 286 /// value.append_bytes(b"application/xml").unwrap(); 287 /// 288 /// assert_eq!(value.to_str().unwrap(), "text/html, application/xml"); 289 /// assert!(!value.is_sensitive()); 290 /// ``` 291 #[derive(Clone, Debug, Eq, PartialEq)] 292 pub struct HeaderValue { 293 inner: Vec<Vec<u8>>, 294 // sensitive data: password etc. 295 is_sensitive: bool, 296 } 297 298 impl HeaderValue { 299 /// Attempts to convert a byte slice to a non-sensitive `HeaderValue`. 300 /// 301 /// `HeaderValue` is case-sensitive. Legal characters will remain unchanged. 302 /// 303 /// # Examples 304 /// 305 /// ``` 306 /// use ylong_http::headers::HeaderValue; 307 /// 308 /// let value = HeaderValue::from_bytes(b"text/html").unwrap(); 309 /// assert_eq!(value.to_str().unwrap(), "text/html"); 310 /// assert!(!value.is_sensitive()); 311 /// 312 /// // `HeaderValue` is case-sensitive. Legal characters will remain unchanged. 313 /// let value = HeaderValue::from_bytes(b"TEXT/HTML").unwrap(); 314 /// assert_eq!(value.to_str().unwrap(), "TEXT/HTML"); 315 /// ``` from_bytes(bytes: &[u8]) -> Result<Self, HttpError>316 pub fn from_bytes(bytes: &[u8]) -> Result<Self, HttpError> { 317 if !bytes.iter().all(|b| Self::is_valid(*b)) { 318 return Err(ErrorKind::InvalidInput.into()); 319 } 320 321 Ok(HeaderValue { 322 inner: vec![bytes.to_vec()], 323 is_sensitive: false, 324 }) 325 } 326 327 /// Consume another `HeaderValue`, and then appends it to this 328 /// `HeaderValue`. 329 /// 330 /// # Examples 331 /// 332 /// ``` 333 /// use ylong_http::headers::HeaderValue; 334 /// 335 /// let mut value = HeaderValue::from_bytes(b"text/html").unwrap(); 336 /// let other = HeaderValue::from_bytes(b"text/plain").unwrap(); 337 /// 338 /// value.append(other); 339 /// assert_eq!(value.to_str().unwrap(), "text/html, text/plain"); 340 /// ``` append(&mut self, mut other: Self)341 pub fn append(&mut self, mut other: Self) { 342 self.inner.append(&mut other.inner) 343 } 344 345 /// Appends a new bytes to `HeaderValue`. 346 /// 347 /// # Examples 348 /// 349 /// ``` 350 /// use ylong_http::headers::HeaderValue; 351 /// 352 /// let mut value = HeaderValue::from_bytes(b"text/html").unwrap(); 353 /// value.append_bytes(b"application/xml").unwrap(); 354 /// 355 /// assert_eq!(value.to_str().unwrap(), "text/html, application/xml"); 356 /// ``` append_bytes(&mut self, bytes: &[u8]) -> Result<(), HttpError>357 pub fn append_bytes(&mut self, bytes: &[u8]) -> Result<(), HttpError> { 358 if !bytes.iter().all(|b| Self::is_valid(*b)) { 359 return Err(ErrorKind::InvalidInput.into()); 360 } 361 self.inner.push(bytes.to_vec()); 362 Ok(()) 363 } 364 365 /// Outputs the content of value as a string in a certain way. 366 /// 367 /// If there are characters that cannot be displayed in value, return `Err`. 368 /// Extra comma and whitespace(", ") will be added between each element of 369 /// value. 370 /// 371 /// # Examples 372 /// 373 /// ``` 374 /// use ylong_http::headers::HeaderValue; 375 /// 376 /// let mut value = HeaderValue::from_bytes(b"text/html").unwrap(); 377 /// value.append_bytes(b"application/xml").unwrap(); 378 /// 379 /// assert_eq!(value.to_str().unwrap(), "text/html, application/xml"); 380 /// ``` 381 // TODO: change this name to `to_string`? to_str(&self) -> Result<String, HttpError>382 pub fn to_str(&self) -> Result<String, HttpError> { 383 let mut content = Vec::new(); 384 for (n, i) in self.inner.iter().enumerate() { 385 if n != 0 { 386 content.extend_from_slice(b", "); 387 } 388 content.extend_from_slice(i.as_slice()); 389 } 390 Ok(unsafe { String::from_utf8_unchecked(content) }) 391 } 392 393 /// Outputs the content of value as a Vec<u8> in a certain way. to_vec(&self) -> Vec<u8>394 pub(crate) fn to_vec(&self) -> Vec<u8> { 395 let mut content = Vec::new(); 396 for (n, i) in self.inner.iter().enumerate() { 397 if n != 0 { 398 content.extend_from_slice(b", "); 399 } 400 content.extend_from_slice(i.as_slice()); 401 } 402 content 403 } 404 405 /// Returns an iterator over the `HeaderValue`. 406 /// 407 /// # Examples 408 /// 409 /// ``` 410 /// use ylong_http::headers::HeaderValue; 411 /// 412 /// let mut value = HeaderValue::from_bytes(b"text/html").unwrap(); 413 /// value.append_bytes(b"application/xml").unwrap(); 414 /// 415 /// for sub_value in value.iter() { 416 /// // Operate on each sub-value. 417 /// } 418 /// ``` iter(&self) -> HeaderValueIter<'_>419 pub fn iter(&self) -> HeaderValueIter<'_> { 420 self.inner.iter() 421 } 422 423 /// Returns an iterator that allows modifying each sub-value. 424 /// 425 /// # Examples 426 /// 427 /// ``` 428 /// use ylong_http::headers::HeaderValue; 429 /// 430 /// let mut value = HeaderValue::from_bytes(b"text/html").unwrap(); 431 /// value.append_bytes(b"application/xml").unwrap(); 432 /// 433 /// for sub_value in value.iter_mut() { 434 /// // Operate on each sub-value. 435 /// } 436 /// ``` iter_mut(&mut self) -> HeaderValueIterMut<'_>437 pub fn iter_mut(&mut self) -> HeaderValueIterMut<'_> { 438 self.inner.iter_mut() 439 } 440 441 /// Sets the sensitivity of value. 442 /// 443 /// # Examples 444 /// 445 /// ``` 446 /// use ylong_http::headers::HeaderValue; 447 /// 448 /// let mut value = HeaderValue::from_bytes(b"text/html").unwrap(); 449 /// assert!(!value.is_sensitive()); 450 /// 451 /// value.set_sensitive(true); 452 /// assert!(value.is_sensitive()); 453 /// ``` set_sensitive(&mut self, is_sensitive: bool)454 pub fn set_sensitive(&mut self, is_sensitive: bool) { 455 self.is_sensitive = is_sensitive; 456 } 457 458 /// Returns `true` if the value represents sensitive data. 459 /// 460 /// # Examples 461 /// 462 /// ``` 463 /// use ylong_http::headers::HeaderValue; 464 /// 465 /// let value = HeaderValue::from_bytes(b"text/html").unwrap(); 466 /// assert!(!value.is_sensitive()); 467 /// ``` is_sensitive(&self) -> bool468 pub fn is_sensitive(&self) -> bool { 469 self.is_sensitive 470 } 471 472 /// Returns `true` if the character matches the rules of `HeaderValue`. is_valid(b: u8) -> bool473 fn is_valid(b: u8) -> bool { 474 b >= 32 && b != 127 || b == b'\t' 475 } 476 } 477 478 impl TryFrom<&str> for HeaderValue { 479 type Error = HttpError; 480 try_from(value: &str) -> Result<Self, Self::Error>481 fn try_from(value: &str) -> Result<Self, Self::Error> { 482 Self::from_bytes(value.as_bytes()) 483 } 484 } 485 486 // `HeaderValue` can use `%x80-FF` u8 in [`RFC9110`]. 487 // [`RFC9110`]: https://www.rfc-editor.org/rfc/rfc9110.html#name-field-values 488 // 489 // |======================================================================== 490 // | field-value = *field-content | 491 // | field-content = field-vchar | 492 // | [ 1*( SP / HTAB / field-vchar ) field-vchar ] | 493 // | field-vchar = VCHAR / obs-text | 494 // | obs-text = %x80-FF | 495 // |======================================================================== 496 impl TryFrom<&[u8]> for HeaderValue { 497 type Error = HttpError; 498 try_from(value: &[u8]) -> Result<Self, Self::Error>499 fn try_from(value: &[u8]) -> Result<Self, Self::Error> { 500 Self::from_bytes(value) 501 } 502 } 503 504 /// Immutable `HeaderValue` iterator. 505 /// 506 /// This struct is created by [`HeaderValue::iter`]. 507 /// 508 /// [`HeaderValue::iter`]: HeaderValue::iter 509 /// 510 /// # Examples 511 /// 512 /// ``` 513 /// use ylong_http::headers::HeaderValue; 514 /// 515 /// let mut value = HeaderValue::from_bytes(b"text/html").unwrap(); 516 /// value.append_bytes(b"application/xml").unwrap(); 517 /// 518 /// for sub_value in value.iter() { 519 /// // Operate on each sub-value. 520 /// } 521 /// ``` 522 pub type HeaderValueIter<'a> = slice::Iter<'a, Vec<u8>>; 523 524 /// Mutable `HeaderValue` iterator. 525 /// 526 /// This struct is created by [`HeaderValue::iter_mut`]. 527 /// 528 /// [`HeaderValue::iter_mut`]: HeaderValue::iter_mut 529 /// 530 /// # Examples 531 /// 532 /// ``` 533 /// use ylong_http::headers::HeaderValue; 534 /// 535 /// let mut value = HeaderValue::from_bytes(b"text/html").unwrap(); 536 /// value.append_bytes(b"application/xml").unwrap(); 537 /// 538 /// for sub_value in value.iter_mut() { 539 /// // Operate on each sub-value. 540 /// } 541 /// ``` 542 pub type HeaderValueIterMut<'a> = slice::IterMut<'a, Vec<u8>>; 543 544 /// HTTP `Headers`, which is called [`Fields`] in RFC9110. 545 /// 546 /// Fields are sent and received within the header and trailer sections of 547 /// messages. 548 /// 549 /// [`Fields`]: https://httpwg.org/specs/rfc9110.html#fields 550 /// 551 /// # Examples 552 /// 553 /// ``` 554 /// use ylong_http::headers::Headers; 555 /// 556 /// let mut headers = Headers::new(); 557 /// headers.insert("Accept", "text/html").unwrap(); 558 /// headers.insert("Content-Length", "3495").unwrap(); 559 /// headers.append("Accept", "text/plain").unwrap(); 560 /// 561 /// assert_eq!( 562 /// headers.get("accept").unwrap().to_str().unwrap(), 563 /// "text/html, text/plain" 564 /// ); 565 /// assert_eq!( 566 /// headers.get("content-length").unwrap().to_str().unwrap(), 567 /// "3495" 568 /// ); 569 /// ``` 570 #[derive(Clone, Debug, Default, Eq, PartialEq)] 571 pub struct Headers { 572 map: HashMap<HeaderName, HeaderValue>, 573 } 574 575 impl fmt::Display for Headers { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result576 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 577 for (k, v) in self.iter() { 578 writeln!( 579 f, 580 "{}: {}", 581 k.to_string(), 582 v.to_str() 583 .unwrap_or_else(|_| "<non-visible header value>".to_string()) 584 )?; 585 } 586 Ok(()) 587 } 588 } 589 590 impl Headers { 591 /// Creates a new, empty `Headers`. 592 /// 593 /// # Examples 594 /// 595 /// ``` 596 /// use ylong_http::headers::Headers; 597 /// 598 /// let headers = Headers::new(); 599 /// assert!(headers.is_empty()); 600 /// ``` new() -> Self601 pub fn new() -> Self { 602 Headers { 603 map: HashMap::new(), 604 } 605 } 606 607 /// Returns the number of header in the `Headers`. 608 /// 609 /// # Examples 610 /// 611 /// ``` 612 /// use ylong_http::headers::Headers; 613 /// 614 /// let mut headers = Headers::new(); 615 /// assert_eq!(headers.len(), 0); 616 /// 617 /// headers.insert("accept", "text/html").unwrap(); 618 /// assert_eq!(headers.len(), 1); 619 /// ``` len(&self) -> usize620 pub fn len(&self) -> usize { 621 self.map.len() 622 } 623 624 /// Returns `true` if the `Headers` contains no headers. 625 /// 626 /// # Examples 627 /// 628 /// ``` 629 /// use ylong_http::headers::Headers; 630 /// 631 /// let mut headers = Headers::new(); 632 /// assert!(headers.is_empty()); 633 /// 634 /// headers.insert("accept", "text/html").unwrap(); 635 /// assert!(!headers.is_empty()); 636 /// ``` is_empty(&self) -> bool637 pub fn is_empty(&self) -> bool { 638 self.map.is_empty() 639 } 640 641 /// Returns an immutable reference to the `HeaderValue` corresponding to 642 /// the `HeaderName`. 643 /// 644 /// This method returns `None` if the input argument could not be 645 /// successfully converted to a `HeaderName` or the `HeaderName` is not in 646 /// `Headers`. 647 /// 648 /// # Examples 649 /// 650 /// ``` 651 /// use ylong_http::headers::Headers; 652 /// 653 /// let mut headers = Headers::new(); 654 /// headers.append("accept", "text/html").unwrap(); 655 /// 656 /// let value = headers.get("accept"); 657 /// assert_eq!(value.unwrap().to_str().unwrap(), "text/html"); 658 /// ``` get<T>(&self, name: T) -> Option<&HeaderValue> where HeaderName: TryFrom<T>,659 pub fn get<T>(&self, name: T) -> Option<&HeaderValue> 660 where 661 HeaderName: TryFrom<T>, 662 { 663 HeaderName::try_from(name) 664 .ok() 665 .and_then(|name| self.map.get(&name)) 666 } 667 668 /// Returns a mutable reference to the `HeaderValue` corresponding to 669 /// the `HeaderName`. 670 /// 671 /// This method returns `None` if the input argument could not be 672 /// successfully converted to a `HeaderName` or the `HeaderName` is not in 673 /// `Headers`. 674 /// 675 /// # Examples 676 /// 677 /// ``` 678 /// use ylong_http::headers::Headers; 679 /// 680 /// let mut headers = Headers::new(); 681 /// headers.append("accept", "text/html").unwrap(); 682 /// 683 /// let value = headers.get_mut("accept"); 684 /// assert_eq!(value.unwrap().to_str().unwrap(), "text/html"); 685 /// ``` get_mut<T>(&mut self, name: T) -> Option<&mut HeaderValue> where HeaderName: TryFrom<T>,686 pub fn get_mut<T>(&mut self, name: T) -> Option<&mut HeaderValue> 687 where 688 HeaderName: TryFrom<T>, 689 { 690 HeaderName::try_from(name) 691 .ok() 692 .and_then(move |name| self.map.get_mut(&name)) 693 } 694 695 /// Inserts a `Header` into the `Headers`. 696 /// 697 /// If the input argument could not be successfully converted to a `Header`, 698 /// `Err` is returned. 699 /// 700 /// If the `Headers` did not have this `HeaderName` present, `None` is 701 /// returned. 702 /// 703 /// If the `Headers` did have this `HeaderName` present, the new 704 /// `HeaderValue` is updated, and the old `HeaderValue` is returned. 705 /// 706 /// # Examples 707 /// 708 /// ``` 709 /// use ylong_http::headers::Headers; 710 /// 711 /// let mut headers = Headers::new(); 712 /// assert!(headers.insert("\0", "illegal header").is_err()); 713 /// 714 /// assert_eq!(headers.insert("accept", "text/html"), Ok(None)); 715 /// 716 /// let old_value = headers.insert("accept", "text/plain").unwrap(); 717 /// assert_eq!(old_value.unwrap().to_str().unwrap(), "text/html"); 718 /// ``` insert<N, V>(&mut self, name: N, value: V) -> Result<Option<HeaderValue>, HttpError> where HeaderName: TryFrom<N>, <HeaderName as TryFrom<N>>::Error: Into<HttpError>, HeaderValue: TryFrom<V>, <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,719 pub fn insert<N, V>(&mut self, name: N, value: V) -> Result<Option<HeaderValue>, HttpError> 720 where 721 HeaderName: TryFrom<N>, 722 <HeaderName as TryFrom<N>>::Error: Into<HttpError>, 723 HeaderValue: TryFrom<V>, 724 <HeaderValue as TryFrom<V>>::Error: Into<HttpError>, 725 { 726 let name = HeaderName::try_from(name).map_err(Into::into)?; 727 let value = HeaderValue::try_from(value).map_err(Into::into)?; 728 Ok(self.map.insert(name, value)) 729 } 730 731 /// Appends a `Header` to the `Headers`. 732 /// 733 /// If the input argument could not be successfully converted to a `Header`, 734 /// `Err` is returned. 735 /// 736 /// If the `Headers` did not have this `HeaderName` present, this `Header` 737 /// is inserted into the `Headers`. 738 /// 739 /// If the `Headers` did have this `HeaderName` present, the new 740 /// `HeaderValue` is appended to the old `HeaderValue`. 741 /// 742 /// # Examples 743 /// 744 /// ``` 745 /// use ylong_http::headers::Headers; 746 /// 747 /// let mut headers = Headers::new(); 748 /// assert!(headers.append("\0", "illegal header").is_err()); 749 /// 750 /// headers.append("accept", "text/html").unwrap(); 751 /// headers.append("accept", "text/plain").unwrap(); 752 /// 753 /// let value = headers.get("accept"); 754 /// assert_eq!(value.unwrap().to_str().unwrap(), "text/html, text/plain"); 755 /// ``` append<N, V>(&mut self, name: N, value: V) -> Result<(), HttpError> where HeaderName: TryFrom<N>, <HeaderName as TryFrom<N>>::Error: Into<HttpError>, HeaderValue: TryFrom<V>, <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,756 pub fn append<N, V>(&mut self, name: N, value: V) -> Result<(), HttpError> 757 where 758 HeaderName: TryFrom<N>, 759 <HeaderName as TryFrom<N>>::Error: Into<HttpError>, 760 HeaderValue: TryFrom<V>, 761 <HeaderValue as TryFrom<V>>::Error: Into<HttpError>, 762 { 763 let name = HeaderName::try_from(name).map_err(Into::into)?; 764 let value = HeaderValue::try_from(value).map_err(Into::into)?; 765 766 match self.map.entry(name) { 767 Entry::Occupied(o) => { 768 o.into_mut().append(value); 769 } 770 Entry::Vacant(v) => { 771 let _ = v.insert(value); 772 } 773 }; 774 Ok(()) 775 } 776 777 /// Removes `Header` from `Headers` by `HeaderName`, returning the 778 /// `HeaderValue` at the `HeaderName` if the `HeaderName` was previously 779 /// in the `Headers`. 780 /// 781 /// If the input argument could not be successfully converted to a `Header`, 782 /// `None` is returned. 783 /// 784 /// # Examples 785 /// 786 /// ``` 787 /// use ylong_http::headers::Headers; 788 /// 789 /// let mut headers = Headers::new(); 790 /// headers.append("accept", "text/html").unwrap(); 791 /// 792 /// let value = headers.remove("accept"); 793 /// assert_eq!(value.unwrap().to_str().unwrap(), "text/html"); 794 /// ``` remove<T>(&mut self, name: T) -> Option<HeaderValue> where HeaderName: TryFrom<T>,795 pub fn remove<T>(&mut self, name: T) -> Option<HeaderValue> 796 where 797 HeaderName: TryFrom<T>, 798 { 799 HeaderName::try_from(name) 800 .ok() 801 .and_then(|name| self.map.remove(&name)) 802 } 803 804 /// Returns an iterator over the `Headers`. The iterator element type is 805 /// `(&'a HeaderName, &'a HeaderValue)`. 806 /// 807 /// # Examples 808 /// 809 /// ``` 810 /// use ylong_http::headers::Headers; 811 /// 812 /// let mut headers = Headers::new(); 813 /// headers.append("accept", "text/html").unwrap(); 814 /// 815 /// for (_name, _value) in headers.iter() { 816 /// // Operate on each `HeaderName` and `HeaderValue` pair. 817 /// } 818 /// ``` iter(&self) -> HeadersIter<'_>819 pub fn iter(&self) -> HeadersIter<'_> { 820 self.map.iter() 821 } 822 823 /// Returns an iterator over the `Headers`. The iterator element type is 824 /// `(&'a HeaderName, &'a mut HeaderValue)`. 825 /// 826 /// # Examples 827 /// 828 /// ``` 829 /// use ylong_http::headers::Headers; 830 /// 831 /// let mut headers = Headers::new(); 832 /// headers.append("accept", "text/html").unwrap(); 833 /// 834 /// for (_name, _value) in headers.iter_mut() { 835 /// // Operate on each `HeaderName` and `HeaderValue` pair. 836 /// } 837 /// ``` iter_mut(&mut self) -> HeadersIterMut<'_>838 pub fn iter_mut(&mut self) -> HeadersIterMut<'_> { 839 self.map.iter_mut() 840 } 841 } 842 843 impl IntoIterator for Headers { 844 type Item = (HeaderName, HeaderValue); 845 type IntoIter = HeadersIntoIter; 846 847 /// Creates a consuming iterator, that is, one that moves each `HeaderName` 848 /// and `HeaderValue` pair out of the `Headers` in arbitrary order. The 849 /// `Headers` cannot be used after calling this. 850 /// 851 /// # Examples 852 /// 853 /// ``` 854 /// use ylong_http::headers::Headers; 855 /// 856 /// let mut headers = Headers::new(); 857 /// headers.append("accept", "text/html").unwrap(); 858 /// 859 /// for (_name, _value) in headers.into_iter() { 860 /// // Operate on each `HeaderName` and `HeaderValue` pair. 861 /// } 862 /// ``` into_iter(self) -> Self::IntoIter863 fn into_iter(self) -> Self::IntoIter { 864 self.map.into_iter() 865 } 866 } 867 868 impl<'a> IntoIterator for &'a Headers { 869 type Item = (&'a HeaderName, &'a HeaderValue); 870 type IntoIter = HeadersIter<'a>; 871 into_iter(self) -> Self::IntoIter872 fn into_iter(self) -> Self::IntoIter { 873 self.iter() 874 } 875 } 876 877 impl<'a> IntoIterator for &'a mut Headers { 878 type Item = (&'a HeaderName, &'a mut HeaderValue); 879 type IntoIter = HeadersIterMut<'a>; 880 into_iter(self) -> Self::IntoIter881 fn into_iter(self) -> Self::IntoIter { 882 self.iter_mut() 883 } 884 } 885 886 /// Immutable `Headers` iterator. 887 /// 888 /// This struct is created by [`Headers::iter`]. 889 /// 890 /// [`Headers::iter`]: Headers::iter 891 /// 892 /// # Examples 893 /// 894 /// ``` 895 /// use ylong_http::headers::Headers; 896 /// 897 /// let mut headers = Headers::new(); 898 /// headers.append("accept", "text/html").unwrap(); 899 /// 900 /// for (_name, _value) in headers.iter() { 901 /// // Operate on each `HeaderName` and `HeaderValue` pair. 902 /// } 903 /// ``` 904 pub type HeadersIter<'a> = hash_map::Iter<'a, HeaderName, HeaderValue>; 905 906 /// Mutable `Headers` iterator. 907 /// 908 /// This struct is created by [`Headers::iter_mut`]. 909 /// 910 /// [`Headers::iter_mut`]: Headers::iter_mut 911 /// 912 /// # Examples 913 /// 914 /// ``` 915 /// use ylong_http::headers::Headers; 916 /// 917 /// let mut headers = Headers::new(); 918 /// headers.append("accept", "text/html").unwrap(); 919 /// 920 /// for (_name, _value) in headers.iter_mut() { 921 /// // Operate on each `HeaderName` and `HeaderValue` pair. 922 /// } 923 /// ``` 924 pub type HeadersIterMut<'a> = hash_map::IterMut<'a, HeaderName, HeaderValue>; 925 926 /// An owning iterator over the entries of a `Headers`. 927 /// 928 /// This struct is created by [`Headers::into_iter`]. 929 /// 930 /// [`Headers::into_iter`]: crate::headers::Headers::into_iter 931 /// 932 /// # Examples 933 /// 934 /// ``` 935 /// use ylong_http::headers::Headers; 936 /// 937 /// let mut headers = Headers::new(); 938 /// headers.append("accept", "text/html").unwrap(); 939 /// 940 /// for (_name, _value) in headers.into_iter() { 941 /// // Operate on each `HeaderName` and `HeaderValue` pair. 942 /// } 943 /// ``` 944 pub type HeadersIntoIter = hash_map::IntoIter<HeaderName, HeaderValue>; 945 946 // HEADER_CHARS is used to check whether char is correct and transfer to 947 // lowercase. 948 #[rustfmt::skip] 949 const HEADER_CHARS: [u8; 256] = [ 950 // 0 1 2 3 4 5 6 7 8 9 951 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x 952 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x 953 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x 954 0, 0, b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'', // 3x 955 0, 0, b'*', b'+', b',', b'-', b'.', b'/', b'0', b'1', // 4x 956 b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', 0, 0, // 5x 957 0, 0, 0, 0, 0, b'a', b'b', b'c', b'd', b'e', // 6x 958 b'f', b'g', b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o', // 7x 959 b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', b'x', b'y', // 8x 960 b'z', 0, 0, 0, b'^', b'_', b'`', b'a', b'b', b'c', // 9x 961 b'd', b'e', b'f', b'g', b'h', b'i', b'j', b'k', b'l', b'm', // 10x 962 b'n', b'o', b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', // 11x 963 b'x', b'y', b'z', 0, b'|', 0, b'~', 0, 0, 0, // 12x 964 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 13x 965 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 14x 966 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 15x 967 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16x 968 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 17x 969 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 18x 970 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 19x 971 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20x 972 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 21x 973 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 22x 974 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 23x 975 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 24x 976 0, 0, 0, 0, 0, 0, // 25x 977 ]; 978 979 #[cfg(test)] 980 mod ut_headers { 981 use std::collections::HashMap; 982 983 use crate::headers::{Header, HeaderName, HeaderValue, Headers}; 984 985 /// UT test cases for `HeaderName::from_bytes`. 986 /// 987 /// # Brief 988 /// 1. Creates a `HeaderName` by calling `HeaderName::from_bytes`. 989 /// 2. Checks if the test results are correct. 990 #[test] ut_header_name_from_bytes()991 fn ut_header_name_from_bytes() { 992 let name = String::from("accept"); 993 assert_eq!( 994 HeaderName::from_bytes(b"ACCEPT"), 995 Ok(HeaderName { name: name.clone() }) 996 ); 997 assert_eq!(HeaderName::from_bytes(b"accept"), Ok(HeaderName { name })); 998 } 999 1000 /// UT test cases for `HeaderName::as_bytes`. 1001 /// 1002 /// # Brief 1003 /// 1. Creates a `HeaderName`. 1004 /// 2. Fetches content from `HeaderName` by calling `HeaderName::as_bytes`. 1005 /// 3. Checks if the test results are correct. 1006 #[test] ut_header_name_as_bytes()1007 fn ut_header_name_as_bytes() { 1008 let name = HeaderName { 1009 name: "accept".to_string(), 1010 }; 1011 assert_eq!(name.as_bytes(), b"accept"); 1012 } 1013 1014 /// UT test cases for `HeaderValue::from_bytes`. 1015 /// 1016 /// # Brief 1017 /// 1. Creates a `HeaderValue` by calling `HeaderValue::from_bytes`. 1018 /// 2. Checks if the test results are correct. 1019 #[test] ut_header_value_from_bytes()1020 fn ut_header_value_from_bytes() { 1021 let value = HeaderValue::from_bytes(b"teXt/hTml, APPLICATION/xhtml+xml, application/xml"); 1022 let result = Ok(HeaderValue { 1023 inner: vec![b"teXt/hTml, APPLICATION/xhtml+xml, application/xml".to_vec()], 1024 is_sensitive: false, 1025 }); 1026 assert_eq!(value, result); 1027 } 1028 1029 /// UT test cases for `Header::from_raw_parts, name, value, into_parts`. 1030 /// 1031 /// # Brief 1032 /// 1. Creates a `Header`. 1033 /// 2. Calls Header::from_raw_parts, name, value and into_parts 1034 /// respectively. 1035 /// 3. Checks if the test results are corrent. 1036 #[test] ut_header_methods()1037 fn ut_header_methods() { 1038 // from_raw_parts 1039 let name = HeaderName::from_bytes(b"John-Doe").unwrap(); 1040 let value = HeaderValue::from_bytes(b"Foo").unwrap(); 1041 let header = Header::from_raw_parts(name, value); 1042 assert_eq!(header.name().as_bytes(), b"john-doe"); 1043 assert_eq!(header.value().to_str().unwrap(), "Foo"); 1044 assert_ne!(header.name().as_bytes(), b"John-Doe"); 1045 assert_ne!(header.value().to_str().unwrap(), "foo"); 1046 1047 // name 1048 let name = header.name(); 1049 assert_eq!(name.as_bytes(), b"john-doe"); 1050 assert_ne!(name.as_bytes(), b"John-Doe"); 1051 assert_ne!(name.as_bytes(), b"jane-doe"); 1052 1053 // value 1054 let value = header.value(); 1055 assert_eq!(value.to_str().unwrap(), "Foo"); 1056 assert_ne!(value.to_str().unwrap(), "foo"); 1057 assert_ne!(value.to_str().unwrap(), "oof"); 1058 1059 // into_parts 1060 let (name, value) = header.into_parts(); 1061 assert_eq!(name.as_bytes(), b"john-doe"); 1062 assert_eq!(value.to_str().unwrap(), "Foo"); 1063 assert_ne!(name.as_bytes(), b"John-Doe"); 1064 assert_ne!(value.to_str().unwrap(), "foo"); 1065 } 1066 1067 /// UT test cases for `HeaderValue::iter`. 1068 /// 1069 /// # Brief 1070 /// 1. Creates a `HeaderValue`. 1071 /// 2. Loops through the values by calling `HeaderValue::iter`. 1072 /// 3. Checks if the test results are correct. 1073 #[test] ut_header_value_iter()1074 fn ut_header_value_iter() { 1075 let mut value = HeaderValue::from_bytes(b"text/html").unwrap(); 1076 value.append_bytes(b"application/xml").unwrap(); 1077 let value_to_compare = vec!["text/html", "application/xml"]; 1078 1079 for (index, sub_value) in value.iter().enumerate() { 1080 assert_eq!(sub_value, value_to_compare[index].as_bytes()); 1081 } 1082 1083 for (index, sub_value) in value.iter_mut().enumerate() { 1084 assert_eq!(sub_value, value_to_compare[index].as_bytes()); 1085 } 1086 } 1087 1088 /// UT test cases for `HeaderValue::is_sensitive`. 1089 /// 1090 /// # Brief 1091 /// 1. Creates a `HeaderValue`. 1092 /// 2. Calls `HeaderValue::is_sensitive` to check if the test results are 1093 /// correct. 1094 #[test] ut_header_value_is_sensitive()1095 fn ut_header_value_is_sensitive() { 1096 let mut value = HeaderValue { 1097 inner: vec![b"text/html, application/xhtml+xml".to_vec()], 1098 is_sensitive: true, 1099 }; 1100 assert!(value.is_sensitive()); 1101 value.is_sensitive = false; 1102 assert!(!value.is_sensitive()); 1103 } 1104 1105 /// UT test cases for `Headers::get_mut`. 1106 /// 1107 /// # Brief 1108 /// 1. Creates a `Headers`. 1109 /// 2. Gets the mutable `HeaderValue` by calling 1110 /// `HeaderValue::append_bytes`. 1111 /// 3. Modifies `HeaderValue`. 1112 /// 3. Checks if the test results are correct. 1113 #[test] ut_headers_get_mut()1114 fn ut_headers_get_mut() { 1115 let mut headers = Headers::new(); 1116 headers.append("accept", "text/css").unwrap(); 1117 let value = headers.get_mut("accept").unwrap(); 1118 assert!(!value.is_sensitive()); 1119 value.is_sensitive = true; 1120 assert!(value.is_sensitive()); 1121 } 1122 1123 /// UT test cases for `HeaderValue::append_bytes`. 1124 /// 1125 /// # Brief 1126 /// 1. Creates a `HeaderValue`. 1127 /// 2. Adds new value content into `HeaderValue` by calling 1128 /// `HeaderValue::append_bytes`. 1129 /// 3. Checks if the test results are correct. 1130 #[test] ut_header_value_append_bytes()1131 fn ut_header_value_append_bytes() { 1132 let mut value = HeaderValue { 1133 inner: vec![b"text/html, application/xhtml+xml".to_vec()], 1134 is_sensitive: false, 1135 }; 1136 assert!(value.append_bytes(b"teXt/plain, teXt/css").is_ok()); 1137 assert!(value.append_bytes(b"application/xml").is_ok()); 1138 1139 let res = HeaderValue { 1140 inner: vec![ 1141 b"text/html, application/xhtml+xml".to_vec(), 1142 b"teXt/plain, teXt/css".to_vec(), 1143 b"application/xml".to_vec(), 1144 ], 1145 is_sensitive: false, 1146 }; 1147 assert_eq!(value, res); 1148 } 1149 1150 /// UT test cases for `HeaderValue::to_string`. 1151 /// 1152 /// # Brief 1153 /// 1. Creates a `HeaderValue`. 1154 /// 2. Gets content of `HeaderValue` by calling `HeaderName::to_string`. 1155 /// 3. Checks if the test results are correct. 1156 #[test] ut_header_value_to_string()1157 fn ut_header_value_to_string() { 1158 let value = HeaderValue { 1159 inner: vec![ 1160 b"text/html, application/xhtml+xml".to_vec(), 1161 b"text/plain, text/css".to_vec(), 1162 b"application/xml".to_vec(), 1163 ], 1164 is_sensitive: false, 1165 }; 1166 1167 let result = 1168 "text/html, application/xhtml+xml, text/plain, text/css, application/xml".to_string(); 1169 assert_eq!(value.to_str(), Ok(result)); 1170 } 1171 1172 /// UT test cases for `HeaderValue::set_sensitive`. 1173 /// 1174 /// # Brief 1175 /// 1. Creates a `HeaderValue`. 1176 /// 2. Sets content of `HeaderValue` by calling `HeaderName::set_sensitive`. 1177 /// 3. Checks if the test results are correct. 1178 #[test] ut_header_value_set_sensitive()1179 fn ut_header_value_set_sensitive() { 1180 let mut value = HeaderValue { 1181 inner: vec![], 1182 is_sensitive: false, 1183 }; 1184 1185 value.set_sensitive(true); 1186 assert!(value.is_sensitive); 1187 } 1188 1189 /// UT test cases for `Headers::new`. 1190 /// 1191 /// # Brief 1192 /// 1. Creates `Headers` by calling `Headers::new`. 1193 /// 2. Checks if the test results are correct. 1194 #[test] ut_headers_new()1195 fn ut_headers_new() { 1196 assert_eq!( 1197 Headers::new(), 1198 Headers { 1199 map: HashMap::new() 1200 } 1201 ); 1202 } 1203 1204 /// UT test cases for `ut_change_headers_info`. 1205 /// 1206 /// # Brief 1207 /// 1. Creates Headers 1208 /// 2. Adds content type `(&str, &str)` by calling append(). 1209 /// 3. Uses new content to replace old content by calling insert(). 1210 /// 4. Uses `HeaderName` to fetch `HeaderValue` by calling get(). 1211 /// 5. Uses `HeaderNam`e to remove `HeaderValu`e by calling remove(). 1212 /// 6. Checks if the test result is correct by assert_eq!(). 1213 #[test] ut_change_headers_info()1214 fn ut_change_headers_info() { 1215 let mut new_headers = Headers::new(); 1216 if new_headers.is_empty() { 1217 let _ = new_headers.append("ACCEPT", "text/html"); 1218 } 1219 let map_len = new_headers.len(); 1220 assert_eq!(map_len, 1); 1221 1222 let mut verify_map = HashMap::new(); 1223 verify_map.insert( 1224 HeaderName { 1225 name: "accept".to_string(), 1226 }, 1227 HeaderValue { 1228 inner: [b"text/html".to_vec()].to_vec(), 1229 is_sensitive: false, 1230 }, 1231 ); 1232 let headers_map = &new_headers.map; 1233 assert_eq!(headers_map, &verify_map); 1234 1235 let mut value_vec = Vec::new(); 1236 let inner_vec = b"text/html, application/xhtml+xml, application/xml".to_vec(); 1237 value_vec.push(inner_vec); 1238 let _ = new_headers.insert( 1239 "accept", 1240 "text/html, application/xhtml+xml, application/xml", 1241 ); 1242 1243 let header_value = new_headers.get("accept").unwrap(); 1244 let verify_value = HeaderValue { 1245 inner: value_vec, 1246 is_sensitive: false, 1247 }; 1248 assert_eq!(header_value, &verify_value); 1249 1250 let remove_value = new_headers.remove("accept").unwrap(); 1251 assert_eq!( 1252 remove_value, 1253 HeaderValue { 1254 inner: [b"text/html, application/xhtml+xml, application/xml".to_vec()].to_vec(), 1255 is_sensitive: false 1256 } 1257 ); 1258 } 1259 1260 /// UT test cases for `Headers::iter`. 1261 /// 1262 /// # Brief 1263 /// 1. Creates a `Headers`. 1264 /// 2. Creates an iterator by calling `Headers::iter`. 1265 /// 3. Fetches `HeaderValue` content by calling `HeadersIter::next`. 1266 /// 4. Checks if the test results are correct. 1267 #[test] ut_headers_iter()1268 fn ut_headers_iter() { 1269 let mut headers = Headers::new(); 1270 assert!(headers.append("ACCEPT", "text/html").is_ok()); 1271 1272 let mut iter = headers.iter(); 1273 assert_eq!( 1274 iter.next(), 1275 Some(( 1276 &HeaderName { 1277 name: "accept".to_string() 1278 }, 1279 &HeaderValue { 1280 inner: [b"text/html".to_vec()].to_vec(), 1281 is_sensitive: false 1282 } 1283 )) 1284 ); 1285 assert_eq!(iter.next(), None); 1286 } 1287 } 1288