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 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` 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_string().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 => self.encode_name(buf), 536 HeaderStatus::Colon => self.encode_colon(buf), 537 HeaderStatus::Value => self.encode_value(buf), 538 HeaderStatus::Crlf(crlf) => self.encode_crlf(buf, crlf), 539 HeaderStatus::EmptyHeader => Ok(TokenStatus::Complete(0)), 540 } 541 } 542 encode_name(&mut self, buf: &mut [u8]) -> TokenResult<usize>543 fn encode_name(&mut self, buf: &mut [u8]) -> TokenResult<usize> { 544 let name = self.name.as_bytes(); 545 let mut task = WriteData::new(name, &mut self.name_idx, buf); 546 match task.write()? { 547 TokenStatus::Complete(size) => { 548 self.status = Some(HeaderStatus::Colon); 549 Ok(TokenStatus::Partial(size)) 550 } 551 TokenStatus::Partial(size) => { 552 self.status = Some(HeaderStatus::Name); 553 Ok(TokenStatus::Partial(size)) 554 } 555 } 556 } 557 encode_colon(&mut self, buf: &mut [u8]) -> TokenResult<usize>558 fn encode_colon(&mut self, buf: &mut [u8]) -> TokenResult<usize> { 559 let colon = ":".as_bytes(); 560 let mut task = WriteData::new(colon, &mut self.colon_idx, buf); 561 match task.write()? { 562 TokenStatus::Complete(size) => { 563 self.status = Some(HeaderStatus::Value); 564 Ok(TokenStatus::Partial(size)) 565 } 566 TokenStatus::Partial(size) => { 567 self.status = Some(HeaderStatus::Colon); 568 Ok(TokenStatus::Partial(size)) 569 } 570 } 571 } 572 encode_value(&mut self, buf: &mut [u8]) -> TokenResult<usize>573 fn encode_value(&mut self, buf: &mut [u8]) -> TokenResult<usize> { 574 let value = self.value.as_slice(); 575 let mut task = WriteData::new(value, &mut self.value_idx, buf); 576 match task.write()? { 577 TokenStatus::Complete(size) => { 578 let crlf = EncodeCrlf::new(); 579 self.status = Some(HeaderStatus::Crlf(crlf)); 580 Ok(TokenStatus::Partial(size)) 581 } 582 TokenStatus::Partial(size) => { 583 self.status = Some(HeaderStatus::Value); 584 Ok(TokenStatus::Partial(size)) 585 } 586 } 587 } 588 encode_crlf(&mut self, buf: &mut [u8], mut crlf: EncodeCrlf) -> TokenResult<usize>589 fn encode_crlf(&mut self, buf: &mut [u8], mut crlf: EncodeCrlf) -> TokenResult<usize> { 590 match crlf.encode(buf)? { 591 TokenStatus::Complete(size) => { 592 if let Some(iter) = self.inner.next() { 593 let (header_name, header_value) = iter; 594 self.status = Some(HeaderStatus::Name); 595 self.name = header_name; 596 self.value = header_value.to_string().unwrap().into_bytes(); 597 self.name_idx = 0; 598 self.colon_idx = 0; 599 self.value_idx = 0; 600 Ok(TokenStatus::Partial(size)) 601 } else { 602 Ok(TokenStatus::Complete(size)) 603 } 604 } 605 TokenStatus::Partial(size) => { 606 self.status = Some(HeaderStatus::Crlf(crlf)); 607 Ok(TokenStatus::Partial(size)) 608 } 609 } 610 } 611 } 612 613 struct EncodeSp { 614 src_idx: usize, 615 } 616 617 impl EncodeSp { new() -> Self618 fn new() -> Self { 619 Self { src_idx: 0 } 620 } 621 encode(&mut self, buf: &mut [u8]) -> TokenResult<usize>622 fn encode(&mut self, buf: &mut [u8]) -> TokenResult<usize> { 623 let sp = " ".as_bytes(); 624 let mut task = WriteData::new(sp, &mut self.src_idx, buf); 625 task.write() 626 } 627 } 628 629 struct EncodeCrlf { 630 src_idx: usize, 631 } 632 633 impl EncodeCrlf { new() -> Self634 fn new() -> Self { 635 Self { src_idx: 0 } 636 } 637 encode(&mut self, buf: &mut [u8]) -> TokenResult<usize>638 fn encode(&mut self, buf: &mut [u8]) -> TokenResult<usize> { 639 let crlf = "\r\n".as_bytes(); 640 let mut task = WriteData::new(crlf, &mut self.src_idx, buf); 641 task.write() 642 } 643 } 644 645 struct WriteData<'a> { 646 src: &'a [u8], 647 src_idx: &'a mut usize, 648 dst: &'a mut [u8], 649 } 650 651 impl<'a> WriteData<'a> { new(src: &'a [u8], src_idx: &'a mut usize, dst: &'a mut [u8]) -> Self652 fn new(src: &'a [u8], src_idx: &'a mut usize, dst: &'a mut [u8]) -> Self { 653 WriteData { src, src_idx, dst } 654 } 655 write(&mut self) -> TokenResult<usize>656 fn write(&mut self) -> TokenResult<usize> { 657 let src_idx = *self.src_idx; 658 let input_len = self.src.len() - src_idx; 659 let output_len = self.dst.len(); 660 let num = (&self.src[src_idx..]).read(self.dst).unwrap(); 661 if output_len >= input_len { 662 return Ok(TokenStatus::Complete(num)); 663 } 664 *self.src_idx += num; 665 Ok(TokenStatus::Partial(num)) 666 } 667 } 668 impl Default for RequestEncoder { default() -> Self669 fn default() -> Self { 670 RequestEncoder::new(RequestPart::default()) 671 } 672 } 673 674 #[cfg(test)] 675 mod ut_request_encoder { 676 use super::RequestEncoder; 677 use crate::request::{Request, RequestBuilder}; 678 679 /// UT test cases for `RequestEncoder::new`. 680 /// 681 /// # Brief 682 /// 1. Calls `RequestEncoder::new` to create a `RequestEncoder`. 683 #[test] ut_request_encoder_new()684 fn ut_request_encoder_new() { 685 let request = Request::new(()); 686 let (part, _) = request.into_parts(); 687 let _encoder = RequestEncoder::new(part); 688 // Success if no panic. 689 } 690 691 /// UT test cases for `RequestEncoder::encode`. 692 /// 693 /// # Brief 694 /// 1. Creates a `Request` by calling methods of `Request::builder`. 695 /// 2. Gets a request part by calling `Request::into_parts`. 696 /// 3. Creates a `RequestEncoder` by calling `RequestBuilder::new`. 697 /// 4. Calls `RequestEncoder::encode` method in a loop and collects the 698 /// results. 699 /// 5. Checks if the test result is correct. 700 #[test] ut_request_encoder_encode_1()701 fn ut_request_encoder_encode_1() { 702 macro_rules! encoder_test_case { 703 ( 704 Method: $method:expr, 705 Uri: $uri:expr, 706 Version: $version:expr, 707 $(Header: $name:expr, $value:expr,)* 708 RequestLine: $request_line:expr, 709 ) => {{ 710 let request = Request::builder() 711 .method($method) 712 .url($uri) 713 .version($version) 714 $(.header($name, $value))* 715 .body(()) 716 .unwrap(); 717 718 let (part, _) = request.into_parts(); 719 let mut encoder = RequestEncoder::new(part); 720 encoder.absolute_uri(true); 721 let mut buf = [0u8; 5]; 722 let mut res = Vec::new(); 723 loop { 724 let size = encoder.encode(&mut buf).unwrap(); 725 res.extend_from_slice(&buf[..size]); 726 if size < buf.len() { 727 break; 728 } 729 } 730 731 let str = std::str::from_utf8(res.as_slice()) 732 .expect("Cannot convert res to &str"); 733 734 assert!(str.find($request_line).is_some()); 735 736 $( 737 let target_header = format!( 738 "{}:{}\r\n", 739 ($name).to_lowercase(), 740 ($value).to_lowercase(), 741 ); 742 assert!(str.find(target_header.as_str()).is_some()); 743 )* 744 }}; 745 } 746 747 // No header-lines. 748 encoder_test_case! { 749 Method: "GET", 750 Uri: "www.example.com", 751 Version: "HTTP/1.1", 752 RequestLine: "GET www.example.com HTTP/1.1\r\n", 753 } 754 755 // 1 header-line. 756 encoder_test_case! { 757 Method: "GET", 758 Uri: "www.example.com", 759 Version: "HTTP/1.1", 760 Header: "ACCEPT", "text/html", 761 RequestLine: "GET www.example.com HTTP/1.1\r\n", 762 } 763 764 // More than 1 header-lines. 765 encoder_test_case! { 766 Method: "GET", 767 Uri: "www.example.com", 768 Version: "HTTP/1.1", 769 Header: "ACCEPT", "text/html", 770 Header: "HOST", "127.0.0.1", 771 RequestLine: "GET www.example.com HTTP/1.1\r\n", 772 } 773 } 774 775 /// UT test cases for `RequestEncoder::absolute_uri`. 776 /// 777 /// # Brief 778 /// 1. Creates a `Request` by calling `RequestBuilder::build`. 779 /// 2. Calls absolute_uri. 780 /// 3. Checks if the test result is correct. 781 #[test] ut_request_encoder_set_proxy()782 fn ut_request_encoder_set_proxy() { 783 let request = RequestBuilder::new() 784 .method("GET") 785 .url("www.example.com") 786 .version("HTTP/1.1") 787 .body(()) 788 .unwrap(); 789 let (part, _) = request.into_parts(); 790 let mut encoder = RequestEncoder::new(part); 791 assert!(!encoder.is_absolute_uri); 792 793 encoder.absolute_uri(true); 794 assert!(encoder.is_absolute_uri); 795 encoder.absolute_uri(false); 796 797 let mut buf = [0u8; 100]; 798 let size = encoder.encode(&mut buf).unwrap(); 799 let res = std::str::from_utf8(&buf[..size]).unwrap(); 800 assert_eq!(res, "GET / HTTP/1.1\r\n\r\n"); 801 } 802 } 803