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/1.1 request encoder implementation. 15 //! 16 //! The encoder is used to serialize the request into the specified buf in 17 //! a certain format. 18 //! 19 //! # Examples 20 //! 21 //! ``` 22 //! use ylong_http::h1::RequestEncoder; 23 //! use ylong_http::request::Request; 24 //! 25 //! let request = Request::builder() 26 //! .method("GET") 27 //! .url("www.example.com") 28 //! .version("HTTP/1.1") 29 //! .header("ACCEPT", "text/html") 30 //! .body(()) 31 //! .unwrap(); 32 //! 33 //! // Gets `RequestPart`. 34 //! let (part, _) = request.into_parts(); 35 //! let mut encoder = RequestEncoder::new(part); 36 //! encoder.absolute_uri(true); 37 //! 38 //! // We use `message` to store all the body data. 39 //! let mut message = Vec::new(); 40 //! // We use `buf` to store save temporary data. 41 //! let mut buf = [0u8; 20]; 42 //! 43 //! // First encoding, buf is filled. 44 //! let size = encoder.encode(&mut buf).unwrap(); 45 //! assert_eq!(&buf[..size], "GET www.example.com ".as_bytes()); 46 //! message.extend_from_slice(&buf[..size]); 47 //! 48 //! // Second encoding, buf is filled. 49 //! let size = encoder.encode(&mut buf).unwrap(); 50 //! assert_eq!(&buf[..size], "HTTP/1.1\r\naccept:tex".as_bytes()); 51 //! message.extend_from_slice(&buf[..size]); 52 //! 53 //! // Third encoding, part of buf is filled, this indicates that encoding has ended. 54 //! let size = encoder.encode(&mut buf).unwrap(); 55 //! assert_eq!(&buf[..size], "t/html\r\n\r\n".as_bytes()); 56 //! message.extend_from_slice(&buf[..size]); 57 //! 58 //! // We can assemble temporary data into a complete data. 59 //! let result = "GET www.example.com HTTP/1.1\r\naccept:text/html\r\n\r\n"; 60 //! assert_eq!(message.as_slice(), result.as_bytes()); 61 //! ``` 62 63 use std::io::Read; 64 65 use crate::error::{ErrorKind, HttpError}; 66 use crate::headers::{HeaderName, Headers, HeadersIntoIter}; 67 use crate::request::method::Method; 68 use crate::request::uri::Uri; 69 use crate::request::RequestPart; 70 use crate::version::Version; 71 72 /// A encoder that is used to encode request message in `HTTP/1.1` format. 73 /// 74 /// This encoder supports you to use the encode method multiple times to output 75 /// the result in multiple bytes slices. 76 /// 77 /// # Examples 78 /// 79 /// ``` 80 /// use ylong_http::h1::RequestEncoder; 81 /// use ylong_http::request::Request; 82 /// 83 /// let request = Request::builder() 84 /// .method("GET") 85 /// .url("www.example.com") 86 /// .version("HTTP/1.1") 87 /// .header("ACCEPT", "text/html") 88 /// .body(()) 89 /// .unwrap(); 90 /// 91 /// // Gets `RequestPart`. 92 /// let (part, _) = request.into_parts(); 93 /// let mut encoder = RequestEncoder::new(part); 94 /// encoder.absolute_uri(true); 95 /// 96 /// // We use `message` to store all the body data. 97 /// let mut message = Vec::new(); 98 /// // We use `buf` to store save temporary data. 99 /// let mut buf = [0u8; 20]; 100 /// 101 /// // First encoding, buf is filled. 102 /// let size = encoder.encode(&mut buf).unwrap(); 103 /// assert_eq!(&buf[..size], "GET www.example.com ".as_bytes()); 104 /// message.extend_from_slice(&buf[..size]); 105 /// 106 /// // Second encoding, buf is filled. 107 /// let size = encoder.encode(&mut buf).unwrap(); 108 /// assert_eq!(&buf[..size], "HTTP/1.1\r\naccept:tex".as_bytes()); 109 /// message.extend_from_slice(&buf[..size]); 110 /// 111 /// // Third encoding, part of buf is filled, this indicates that encoding has ended. 112 /// let size = encoder.encode(&mut buf).unwrap(); 113 /// assert_eq!(&buf[..size], "t/html\r\n\r\n".as_bytes()); 114 /// message.extend_from_slice(&buf[..size]); 115 /// 116 /// // We can assemble temporary data into a complete data. 117 /// let result = "GET www.example.com HTTP/1.1\r\naccept:text/html\r\n\r\n"; 118 /// assert_eq!(message.as_slice(), result.as_bytes()); 119 /// ``` 120 pub struct RequestEncoder { 121 encode_status: EncodeState, 122 method_part: EncodeMethod, 123 method_sp_part: EncodeSp, 124 uri_part: EncodeUri, 125 uri_sp_part: EncodeSp, 126 version_part: EncodeVersion, 127 version_crlf_part: EncodeCrlf, 128 headers_part: EncodeHeader, 129 headers_crlf_part: EncodeCrlf, 130 is_absolute_uri: bool, 131 } 132 133 enum EncodeState { 134 // "Method" phase of encoding request-message. 135 Method, 136 // "MethodSp" phase of encoding whitespace after method. 137 MethodSp, 138 // "Uri" phase of encoding request-message. 139 Uri, 140 // "UriSp" phase of encoding whitespace after uri. 141 UriSp, 142 // "Version" phase of encoding request-message. 143 Version, 144 // "VersionCrlf" phase of encoding whitespace after version. 145 VersionCrlf, 146 // "Header" phase of encoding request-message. 147 Header, 148 // "HeaderCrlf" phase of encoding /r/n after header. 149 HeaderCrlf, 150 // "EncodeFinished" phase of finishing the encoding. 151 EncodeFinished, 152 } 153 154 // Component encoding status. 155 enum TokenStatus<T, E> { 156 // The current component is completely encoded. 157 Complete(T), 158 // The current component is partially encoded. 159 Partial(E), 160 } 161 162 type TokenResult<T> = Result<TokenStatus<usize, T>, HttpError>; 163 164 impl RequestEncoder { 165 /// Creates a new `RequestEncoder` from a `RequestPart`. 166 /// 167 /// # Examples 168 /// 169 /// ``` 170 /// use ylong_http::h1::RequestEncoder; 171 /// use ylong_http::request::Request; 172 /// 173 /// let request = Request::builder() 174 /// .method("GET") 175 /// .url("www.example.com") 176 /// .version("HTTP/1.1") 177 /// .header("ACCEPT", "text/html") 178 /// .body(()) 179 /// .unwrap(); 180 /// 181 /// let (part, _) = request.into_parts(); 182 /// let encoder = RequestEncoder::new(part); 183 /// ``` new(part: RequestPart) -> Self184 pub fn new(part: RequestPart) -> Self { 185 Self { 186 encode_status: EncodeState::Method, 187 method_part: EncodeMethod::new(part.method), 188 method_sp_part: EncodeSp::new(), 189 uri_part: EncodeUri::new(part.uri, false), 190 uri_sp_part: EncodeSp::new(), 191 version_part: EncodeVersion::new(part.version), 192 version_crlf_part: EncodeCrlf::new(), 193 headers_part: EncodeHeader::new(part.headers), 194 headers_crlf_part: EncodeCrlf::new(), 195 is_absolute_uri: false, 196 } 197 } 198 199 /// Encodes `RequestPart` into target buf and returns the number of 200 /// bytes written. 201 /// 202 /// If the length of buf is not enough to write all the output results, 203 /// the state will be saved until the next call to this method. 204 /// 205 /// # Return Value 206 /// 207 /// This method may return the following results: 208 /// 209 /// - `Ok(size) && size == buf.len()`: it means that buf has been completely 210 /// filled, but the result may not be fully output. You **must** call this 211 /// method again to obtain the rest part of the result. Otherwise you may 212 /// lose some parts of the result. 213 /// 214 /// - `Ok(size) && size < buf.len()`: it indicates that the result has been 215 /// fully output. 216 /// 217 /// - `Err(e)`: it indicates that an error has occurred during encoding. 218 /// 219 /// # Examples 220 /// 221 /// ``` 222 /// use ylong_http::h1::RequestEncoder; 223 /// use ylong_http::request::Request; 224 /// 225 /// let request = Request::builder() 226 /// .method("GET") 227 /// .url("www.example.com") 228 /// .version("HTTP/1.1") 229 /// .header("ACCEPT", "text/html") 230 /// .body(()) 231 /// .unwrap(); 232 /// 233 /// let (part, _) = request.into_parts(); 234 /// let mut encoder = RequestEncoder::new(part); 235 /// encoder.absolute_uri(true); 236 /// 237 /// let mut buf = [0_u8; 10]; 238 /// let mut message = Vec::new(); 239 /// let mut idx = 0; 240 /// loop { 241 /// let size = encoder.encode(&mut buf).unwrap(); 242 /// message.extend_from_slice(&buf[..size]); 243 /// if size < buf.len() { 244 /// break; 245 /// } 246 /// } 247 /// 248 /// let result = "GET www.example.com HTTP/1.1\r\naccept:text/html\r\n\r\n"; 249 /// assert_eq!(message.as_slice(), result.as_bytes()); 250 /// ``` encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>251 pub fn encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> { 252 if dst.is_empty() { 253 return Err(ErrorKind::InvalidInput.into()); 254 } 255 let mut count = 0; 256 while count != dst.len() { 257 count += match self.encode_status { 258 EncodeState::Method => self.method_encode(&mut dst[count..]), 259 EncodeState::MethodSp => self.method_sp_encode(&mut dst[count..]), 260 EncodeState::Uri => self.uri_encode(&mut dst[count..]), 261 EncodeState::UriSp => self.uri_sp_encode(&mut dst[count..]), 262 EncodeState::Version => self.version_encode(&mut dst[count..]), 263 EncodeState::VersionCrlf => self.version_crlf_encode(&mut dst[count..]), 264 EncodeState::Header => self.header_encode(&mut dst[count..]), 265 EncodeState::HeaderCrlf => self.header_crlf_encode(&mut dst[count..]), 266 EncodeState::EncodeFinished => return Ok(count), 267 }?; 268 } 269 Ok(dst.len()) 270 } 271 272 /// Sets the `is_absolute_uri` flag. 273 /// 274 /// If you enable the flag, the uri part will be encoded as absolute form 275 /// in the headline. Otherwise the uri part will be encoded as origin form. 276 /// 277 /// You should use this method before the uri part being encoded. 278 /// 279 /// # Examples 280 /// 281 /// ``` 282 /// use ylong_http::h1::RequestEncoder; 283 /// use ylong_http::request::Request; 284 /// 285 /// let request = Request::builder() 286 /// .method("GET") 287 /// .url("www.example.com") 288 /// .version("HTTP/1.1") 289 /// .header("ACCEPT", "text/html") 290 /// .body(()) 291 /// .unwrap(); 292 /// 293 /// let (part, _) = request.into_parts(); 294 /// let mut encoder = RequestEncoder::new(part); 295 /// // After you create the request encoder, users can choose to set the uri form. 296 /// encoder.absolute_uri(false); 297 /// 298 /// let mut buf = [0u8; 1024]; 299 /// let size = encoder.encode(&mut buf).unwrap(); 300 /// // If you disable the `is_absolute_uri` flag, the uri will be encoded as a origin form. 301 /// assert_eq!( 302 /// &buf[..size], 303 /// b"GET / HTTP/1.1\r\naccept:text/html\r\n\r\n".as_slice() 304 /// ); 305 /// ``` absolute_uri(&mut self, is_absolute: bool)306 pub fn absolute_uri(&mut self, is_absolute: bool) { 307 self.is_absolute_uri = is_absolute; 308 } 309 method_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>310 fn method_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> { 311 match self.method_part.encode(dst)? { 312 TokenStatus::Complete(output_size) => { 313 self.encode_status = EncodeState::MethodSp; 314 Ok(output_size) 315 } 316 TokenStatus::Partial(output_size) => { 317 self.encode_status = EncodeState::Method; 318 Ok(output_size) 319 } 320 } 321 } 322 method_sp_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>323 fn method_sp_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> { 324 match self.method_sp_part.encode(dst)? { 325 TokenStatus::Complete(output_size) => { 326 self.uri_part.is_absolute = self.is_absolute_uri; 327 self.encode_status = EncodeState::Uri; 328 Ok(output_size) 329 } 330 TokenStatus::Partial(output_size) => { 331 self.encode_status = EncodeState::MethodSp; 332 Ok(output_size) 333 } 334 } 335 } 336 uri_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>337 fn uri_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> { 338 match self.uri_part.encode(dst)? { 339 TokenStatus::Complete(output_size) => { 340 self.encode_status = EncodeState::UriSp; 341 Ok(output_size) 342 } 343 TokenStatus::Partial(output_size) => { 344 self.encode_status = EncodeState::Uri; 345 Ok(output_size) 346 } 347 } 348 } 349 uri_sp_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>350 fn uri_sp_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> { 351 match self.uri_sp_part.encode(dst)? { 352 TokenStatus::Complete(output_size) => { 353 self.encode_status = EncodeState::Version; 354 Ok(output_size) 355 } 356 TokenStatus::Partial(output_size) => { 357 self.encode_status = EncodeState::UriSp; 358 Ok(output_size) 359 } 360 } 361 } 362 version_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>363 fn version_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> { 364 match self.version_part.encode(dst)? { 365 TokenStatus::Complete(output_size) => { 366 self.encode_status = EncodeState::VersionCrlf; 367 Ok(output_size) 368 } 369 TokenStatus::Partial(output_size) => { 370 self.encode_status = EncodeState::Version; 371 Ok(output_size) 372 } 373 } 374 } 375 version_crlf_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>376 fn version_crlf_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> { 377 match self.version_crlf_part.encode(dst)? { 378 TokenStatus::Complete(output_size) => { 379 self.encode_status = EncodeState::Header; 380 Ok(output_size) 381 } 382 TokenStatus::Partial(output_size) => { 383 self.encode_status = EncodeState::VersionCrlf; 384 Ok(output_size) 385 } 386 } 387 } 388 header_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>389 fn header_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> { 390 match self.headers_part.encode(dst)? { 391 TokenStatus::Complete(output_size) => { 392 self.encode_status = EncodeState::HeaderCrlf; 393 Ok(output_size) 394 } 395 TokenStatus::Partial(output_size) => { 396 self.encode_status = EncodeState::Header; 397 Ok(output_size) 398 } 399 } 400 } 401 header_crlf_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>402 fn header_crlf_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> { 403 match self.headers_crlf_part.encode(dst)? { 404 TokenStatus::Complete(output_size) => { 405 self.encode_status = EncodeState::EncodeFinished; 406 Ok(output_size) 407 } 408 TokenStatus::Partial(output_size) => { 409 self.encode_status = EncodeState::HeaderCrlf; 410 Ok(output_size) 411 } 412 } 413 } 414 } 415 416 struct EncodeMethod { 417 inner: Method, 418 src_idx: usize, 419 } 420 421 impl EncodeMethod { new(method: Method) -> Self422 fn new(method: Method) -> Self { 423 Self { 424 inner: method, 425 src_idx: 0, 426 } 427 } 428 encode(&mut self, buf: &mut [u8]) -> TokenResult<usize>429 fn encode(&mut self, buf: &mut [u8]) -> TokenResult<usize> { 430 let method = self.inner.as_str().as_bytes(); 431 WriteData::new(method, &mut self.src_idx, buf).write() 432 } 433 } 434 435 struct EncodeUri { 436 absolute: Vec<u8>, 437 origin: Vec<u8>, 438 src_idx: usize, 439 is_absolute: bool, 440 } 441 442 impl EncodeUri { new(uri: Uri, is_absolute: bool) -> Self443 fn new(uri: Uri, is_absolute: bool) -> Self { 444 let mut origin_form = vec![]; 445 let path = uri.path_and_query(); 446 if let Some(p) = path { 447 origin_form = p.as_bytes().to_vec(); 448 } else { 449 origin_form.extend_from_slice(b"/"); 450 } 451 let init_uri = uri.to_string().into_bytes(); 452 Self { 453 absolute: init_uri, 454 origin: origin_form, 455 src_idx: 0, 456 is_absolute, 457 } 458 } 459 encode(&mut self, buf: &mut [u8]) -> TokenResult<usize>460 fn encode(&mut self, buf: &mut [u8]) -> TokenResult<usize> { 461 let mut uri = self.origin.as_slice(); 462 if self.is_absolute { 463 uri = self.absolute.as_slice(); 464 } 465 WriteData::new(uri, &mut self.src_idx, buf).write() 466 } 467 } 468 469 struct EncodeVersion { 470 inner: Version, 471 src_idx: usize, 472 } 473 474 impl EncodeVersion { new(version: Version) -> Self475 fn new(version: Version) -> Self { 476 Self { 477 inner: version, 478 src_idx: 0, 479 } 480 } 481 encode(&mut self, buf: &mut [u8]) -> TokenResult<usize>482 fn encode(&mut self, buf: &mut [u8]) -> TokenResult<usize> { 483 let version = self.inner.as_str().as_bytes(); 484 let mut task = WriteData::new(version, &mut self.src_idx, buf); 485 task.write() 486 } 487 } 488 489 struct EncodeHeader { 490 inner: HeadersIntoIter, 491 status: Option<HeaderStatus>, 492 name: HeaderName, 493 value: Vec<u8>, 494 name_idx: usize, 495 colon_idx: usize, 496 value_idx: usize, 497 } 498 499 enum HeaderStatus { 500 Name, 501 Colon, 502 Value, 503 Crlf(EncodeCrlf), 504 EmptyHeader, 505 } 506 507 impl EncodeHeader { new(header: Headers) -> Self508 fn new(header: Headers) -> Self { 509 let mut header_iter = header.into_iter(); 510 if let Some((header_name, header_value)) = header_iter.next() { 511 Self { 512 inner: header_iter, 513 status: Some(HeaderStatus::Name), 514 name: header_name, 515 value: header_value.to_str().unwrap().into_bytes(), 516 name_idx: 0, 517 colon_idx: 0, 518 value_idx: 0, 519 } 520 } else { 521 Self { 522 inner: header_iter, 523 status: Some(HeaderStatus::EmptyHeader), 524 name: HeaderName::from_bytes(" ".as_bytes()).unwrap(), 525 value: vec![], 526 name_idx: 0, 527 colon_idx: 0, 528 value_idx: 0, 529 } 530 } 531 } 532 encode(&mut self, buf: &mut [u8]) -> TokenResult<usize>533 fn encode(&mut self, buf: &mut [u8]) -> TokenResult<usize> { 534 match self.status.take().unwrap() { 535 HeaderStatus::Name => { 536 let name = self.name.as_bytes(); 537 let mut task = WriteData::new(name, &mut self.name_idx, buf); 538 match task.write()? { 539 TokenStatus::Complete(size) => { 540 self.status = Some(HeaderStatus::Colon); 541 Ok(TokenStatus::Partial(size)) 542 } 543 TokenStatus::Partial(size) => { 544 self.status = Some(HeaderStatus::Name); 545 Ok(TokenStatus::Partial(size)) 546 } 547 } 548 } 549 HeaderStatus::Colon => { 550 let colon = ":".as_bytes(); 551 let mut task = WriteData::new(colon, &mut self.colon_idx, buf); 552 match task.write()? { 553 TokenStatus::Complete(size) => { 554 self.status = Some(HeaderStatus::Value); 555 Ok(TokenStatus::Partial(size)) 556 } 557 TokenStatus::Partial(size) => { 558 self.status = Some(HeaderStatus::Colon); 559 Ok(TokenStatus::Partial(size)) 560 } 561 } 562 } 563 HeaderStatus::Value => { 564 let value = self.value.as_slice(); 565 let mut task = WriteData::new(value, &mut self.value_idx, buf); 566 match task.write()? { 567 TokenStatus::Complete(size) => { 568 let crlf = EncodeCrlf::new(); 569 self.status = Some(HeaderStatus::Crlf(crlf)); 570 Ok(TokenStatus::Partial(size)) 571 } 572 TokenStatus::Partial(size) => { 573 self.status = Some(HeaderStatus::Value); 574 Ok(TokenStatus::Partial(size)) 575 } 576 } 577 } 578 HeaderStatus::Crlf(mut crlf) => match crlf.encode(buf)? { 579 TokenStatus::Complete(size) => { 580 if let Some(iter) = self.inner.next() { 581 let (header_name, header_value) = iter; 582 self.status = Some(HeaderStatus::Name); 583 self.name = header_name; 584 self.value = header_value.to_str().unwrap().into_bytes(); 585 self.name_idx = 0; 586 self.colon_idx = 0; 587 self.value_idx = 0; 588 Ok(TokenStatus::Partial(size)) 589 } else { 590 Ok(TokenStatus::Complete(size)) 591 } 592 } 593 TokenStatus::Partial(size) => { 594 self.status = Some(HeaderStatus::Crlf(crlf)); 595 Ok(TokenStatus::Partial(size)) 596 } 597 }, 598 HeaderStatus::EmptyHeader => Ok(TokenStatus::Complete(0)), 599 } 600 } 601 } 602 603 struct EncodeSp { 604 src_idx: usize, 605 } 606 607 impl EncodeSp { new() -> Self608 fn new() -> Self { 609 Self { src_idx: 0 } 610 } 611 encode(&mut self, buf: &mut [u8]) -> TokenResult<usize>612 fn encode(&mut self, buf: &mut [u8]) -> TokenResult<usize> { 613 let sp = " ".as_bytes(); 614 let mut task = WriteData::new(sp, &mut self.src_idx, buf); 615 task.write() 616 } 617 } 618 619 struct EncodeCrlf { 620 src_idx: usize, 621 } 622 623 impl EncodeCrlf { new() -> Self624 fn new() -> Self { 625 Self { src_idx: 0 } 626 } 627 encode(&mut self, buf: &mut [u8]) -> TokenResult<usize>628 fn encode(&mut self, buf: &mut [u8]) -> TokenResult<usize> { 629 let crlf = "\r\n".as_bytes(); 630 let mut task = WriteData::new(crlf, &mut self.src_idx, buf); 631 task.write() 632 } 633 } 634 635 struct WriteData<'a> { 636 src: &'a [u8], 637 src_idx: &'a mut usize, 638 dst: &'a mut [u8], 639 } 640 641 impl<'a> WriteData<'a> { new(src: &'a [u8], src_idx: &'a mut usize, dst: &'a mut [u8]) -> Self642 fn new(src: &'a [u8], src_idx: &'a mut usize, dst: &'a mut [u8]) -> Self { 643 WriteData { src, src_idx, dst } 644 } 645 write(&mut self) -> TokenResult<usize>646 fn write(&mut self) -> TokenResult<usize> { 647 let src_idx = *self.src_idx; 648 let input_len = self.src.len() - src_idx; 649 let output_len = self.dst.len(); 650 let num = (&self.src[src_idx..]).read(self.dst).unwrap(); 651 if output_len >= input_len { 652 return Ok(TokenStatus::Complete(num)); 653 } 654 *self.src_idx += num; 655 Ok(TokenStatus::Partial(num)) 656 } 657 } 658 impl Default for RequestEncoder { default() -> Self659 fn default() -> Self { 660 RequestEncoder::new(RequestPart::default()) 661 } 662 } 663 664 #[cfg(test)] 665 mod ut_request_encoder { 666 use super::RequestEncoder; 667 use crate::request::{Request, RequestBuilder}; 668 669 /// UT test cases for `RequestEncoder::new`. 670 /// 671 /// # Brief 672 /// 1. Calls `RequestEncoder::new` to create a `RequestEncoder`. 673 #[test] ut_request_encoder_new()674 fn ut_request_encoder_new() { 675 let request = Request::new(()); 676 let (part, _) = request.into_parts(); 677 let _encoder = RequestEncoder::new(part); 678 // Success if no panic. 679 } 680 681 /// UT test cases for `RequestEncoder::encode`. 682 /// 683 /// # Brief 684 /// 1. Creates a `Request` by calling methods of `Request::builder`. 685 /// 2. Gets a request part by calling `Request::into_parts`. 686 /// 3. Creates a `RequestEncoder` by calling `RequestBuilder::new`. 687 /// 4. Calls `RequestEncoder::encode` method in a loop and collects the 688 /// results. 689 /// 5. Checks if the test result is correct. 690 #[test] ut_request_encoder_encode_1()691 fn ut_request_encoder_encode_1() { 692 macro_rules! encoder_test_case { 693 ( 694 Method: $method:expr, 695 Uri: $uri:expr, 696 Version: $version:expr, 697 $(Header: $name:expr, $value:expr,)* 698 RequestLine: $request_line:expr, 699 ) => {{ 700 let request = Request::builder() 701 .method($method) 702 .url($uri) 703 .version($version) 704 $(.header($name, $value))* 705 .body(()) 706 .unwrap(); 707 708 let (part, _) = request.into_parts(); 709 let mut encoder = RequestEncoder::new(part); 710 encoder.absolute_uri(true); 711 let mut buf = [0u8; 5]; 712 let mut res = Vec::new(); 713 loop { 714 let size = encoder.encode(&mut buf).unwrap(); 715 res.extend_from_slice(&buf[..size]); 716 if size < buf.len() { 717 break; 718 } 719 } 720 721 let str = std::str::from_utf8(res.as_slice()) 722 .expect("Cannot convert res to &str"); 723 724 assert!(str.find($request_line).is_some()); 725 726 $( 727 let target_header = format!( 728 "{}:{}\r\n", 729 ($name).to_lowercase(), 730 ($value).to_lowercase(), 731 ); 732 assert!(str.find(target_header.as_str()).is_some()); 733 )* 734 }}; 735 } 736 737 // No header-lines. 738 encoder_test_case! { 739 Method: "GET", 740 Uri: "www.example.com", 741 Version: "HTTP/1.1", 742 RequestLine: "GET www.example.com HTTP/1.1\r\n", 743 } 744 745 // 1 header-line. 746 encoder_test_case! { 747 Method: "GET", 748 Uri: "www.example.com", 749 Version: "HTTP/1.1", 750 Header: "ACCEPT", "text/html", 751 RequestLine: "GET www.example.com HTTP/1.1\r\n", 752 } 753 754 // More than 1 header-lines. 755 encoder_test_case! { 756 Method: "GET", 757 Uri: "www.example.com", 758 Version: "HTTP/1.1", 759 Header: "ACCEPT", "text/html", 760 Header: "HOST", "127.0.0.1", 761 RequestLine: "GET www.example.com HTTP/1.1\r\n", 762 } 763 } 764 765 /// UT test cases for `RequestEncoder::absolute_uri`. 766 /// 767 /// # Brief 768 /// 1. Creates a `Request` by calling `RequestBuilder::build`. 769 /// 2. Calls absolute_uri. 770 /// 3. Checks if the test result is correct. 771 #[test] ut_request_encoder_set_proxy()772 fn ut_request_encoder_set_proxy() { 773 let request = RequestBuilder::new() 774 .method("GET") 775 .url("www.example.com") 776 .version("HTTP/1.1") 777 .body(()) 778 .unwrap(); 779 let (part, _) = request.into_parts(); 780 let mut encoder = RequestEncoder::new(part); 781 assert!(!encoder.is_absolute_uri); 782 783 encoder.absolute_uri(true); 784 assert!(encoder.is_absolute_uri); 785 encoder.absolute_uri(false); 786 787 let mut buf = [0u8; 100]; 788 let size = encoder.encode(&mut buf).unwrap(); 789 let res = std::str::from_utf8(&buf[..size]).unwrap(); 790 assert_eq!(res, "GET / HTTP/1.1\r\n\r\n"); 791 } 792 } 793