1use std::fmt;
191use std::io::Write;
192use std::marker::PhantomData;
193
194use amended::AmendedResponse;
195use http::{Method, Response, StatusCode, Version};
196
197use crate::body::{BodyReader, BodyWriter};
198use crate::ext::{MethodExt, StatusCodeExt};
199use crate::util::Writer;
200use crate::{ArrayVec, CloseReason};
201
202mod amended;
203
204#[cfg(test)]
205mod test;
206
207pub const MAX_REQUEST_HEADERS: usize = 128;
213
214pub struct Reply<State> {
226 inner: Inner,
227 _ph: PhantomData<State>,
228}
229
230#[derive(Debug)]
232pub(crate) struct Inner {
233 pub phase: ResponsePhase,
234 pub state: BodyState,
235 pub response: Option<AmendedResponse>,
236 pub close_reason: ArrayVec<CloseReason, 4>,
237 pub force_recv_body: bool,
238 pub force_send_body: bool,
239 pub method: Option<Method>,
240 pub expect_100: bool,
241 pub expect_100_reject: bool,
242}
243
244#[derive(Clone, Copy, PartialEq, Eq)]
245pub(crate) enum ResponsePhase {
246 Status,
247 Headers(usize),
248 Body,
249}
250
251impl ResponsePhase {
252 fn is_prelude(&self) -> bool {
253 matches!(self, ResponsePhase::Status | ResponsePhase::Headers(_))
254 }
255
256 fn is_body(&self) -> bool {
257 matches!(self, ResponsePhase::Body)
258 }
259}
260
261#[derive(Debug, Default)]
262pub(crate) struct BodyState {
263 reader: Option<BodyReader>,
264 writer: Option<BodyWriter>,
265 stop_on_chunk_boundary: bool,
266}
267
268#[doc(hidden)]
269pub mod state {
270 pub(crate) trait Named {
271 fn name() -> &'static str;
272 }
273
274 macro_rules! reply_state {
275 ($n:tt) => {
276 #[doc(hidden)]
277 pub struct $n(());
278 impl Named for $n {
279 fn name() -> &'static str {
280 stringify!($n)
281 }
282 }
283 };
284 }
285
286 reply_state!(RecvRequest);
287 reply_state!(Send100);
288 reply_state!(RecvBody);
289 reply_state!(ProvideResponse);
290 reply_state!(SendResponse);
291 reply_state!(SendBody);
292 reply_state!(Cleanup);
293}
294use self::state::*;
295
296impl<S> Reply<S> {
297 fn wrap(inner: Inner) -> Reply<S>
298 where
299 S: Named,
300 {
301 let wrapped = Reply {
302 inner,
303 _ph: PhantomData,
304 };
305
306 debug!("{:?}", wrapped);
307
308 wrapped
309 }
310
311 #[cfg(test)]
312 pub(crate) fn inner(&self) -> &Inner {
313 &self.inner
314 }
315}
316
317mod recvreq;
320
321pub enum RecvRequestResult {
325 Send100(Reply<Send100>),
327 RecvBody(Reply<RecvBody>),
329 ProvideResponse(Reply<ProvideResponse>),
331}
332
333mod send100;
336
337fn append_request(inner: Inner, response: Response<()>) -> Inner {
342 let method_allows_body = inner.method.as_ref().unwrap().allow_request_body();
344 let status_allows_body = response.status().body_allowed();
345
346 let default_body_mode = if method_allows_body && status_allows_body {
347 BodyWriter::new_chunked()
348 } else {
349 BodyWriter::new_none()
350 };
351
352 Inner {
353 phase: inner.phase,
354 state: BodyState {
355 writer: Some(default_body_mode),
356 ..inner.state
357 },
358 response: Some(AmendedResponse::new(response)),
359 force_recv_body: inner.force_recv_body,
360 force_send_body: inner.force_send_body,
361 close_reason: inner.close_reason,
362 method: inner.method,
363 expect_100: inner.expect_100,
364 expect_100_reject: inner.expect_100_reject,
365 }
366}
367
368fn do_write_send_line(line: (Version, StatusCode), w: &mut Writer, end_head: bool) -> bool {
372 w.try_write(|w| {
373 write!(
374 w,
375 "{:?} {} {}\r\n{}",
376 line.0,
377 line.1.as_str(),
378 line.1.canonical_reason().unwrap_or("Unknown"),
379 if end_head { "\r\n" } else { "" }
380 )
381 })
382}
383
384mod provres;
387
388mod recvbody;
391
392mod sendres;
395
396pub enum SendResponseResult {
404 SendBody(Reply<SendBody>),
406 Cleanup(Reply<Cleanup>),
408}
409
410mod sendbody;
413
414impl Reply<Cleanup> {
417 pub fn must_close_connection(&self) -> bool {
419 self.close_reason().is_some()
420 }
421
422 pub fn close_reason(&self) -> Option<&'static str> {
424 self.inner.close_reason.first().map(|s| s.explain())
425 }
426}
427
428impl<State: Named> fmt::Debug for Reply<State> {
431 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
432 write!(f, "Reply<{}>", State::name())
433 }
434}
435
436impl fmt::Debug for ResponsePhase {
437 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
438 match self {
439 ResponsePhase::Status => write!(f, "SendStatus"),
440 ResponsePhase::Headers(_) => write!(f, "SendHeaders"),
441 ResponsePhase::Body => write!(f, "SendBody"),
442 }
443 }
444}
445
446#[cfg(test)]
447mod tests {
448 use super::*;
449 use http::{Response, StatusCode};
450 use std::str;
451
452 #[test]
453 fn get_simple() {
454 let mut reply = Reply::new().unwrap();
456
457 let input = b"GET /page HTTP/1.1\r\n\
459 host: test.local\r\n\
460 \r\n";
461 let (input_used, request) = reply.try_request(input).unwrap();
462 let request = request.unwrap();
463
464 assert_eq!(input_used, 40);
465 assert_eq!(request.method(), "GET");
466 assert_eq!(request.uri().path(), "/page");
467
468 let reply = reply.proceed().unwrap();
470 let RecvRequestResult::ProvideResponse(reply) = reply else {
471 panic!("Expected ProvideResponse state");
472 };
473
474 let response = Response::builder()
476 .status(StatusCode::OK)
477 .header("content-type", "text/plain")
478 .body(())
479 .unwrap();
480
481 let mut reply = reply.provide(response).unwrap();
482
483 let mut output = vec![0_u8; 1024];
485 let n = reply.write(&mut output).unwrap();
486
487 let s = str::from_utf8(&output[..n]).unwrap();
488 assert_eq!(
489 s,
490 "HTTP/1.1 200 OK\r\n\
491 transfer-encoding: chunked\r\n\
492 content-type: text/plain\r\n\
493 \r\n"
494 );
495 }
496
497 #[test]
498 fn post_with_100_continue() {
499 let mut reply = Reply::new().unwrap();
501
502 let input = b"POST /upload HTTP/1.1\r\n\
504 host: test.local\r\n\
505 expect: 100-continue\r\n\
506 transfer-encoding: chunked\r\n\
507 \r\n";
508 let (input_used, request) = reply.try_request(input).unwrap();
509 let request = request.unwrap();
510
511 assert_eq!(input_used, 93); assert_eq!(request.method(), "POST");
513 assert_eq!(request.uri().path(), "/upload");
514 assert_eq!(request.headers().get("expect").unwrap(), "100-continue");
515
516 let reply = reply.proceed().unwrap();
518 let reply = match reply {
519 RecvRequestResult::Send100(r) => r,
520 _ => panic!("Expected Send100 state"),
521 };
522
523 let mut output = vec![0_u8; 1024];
526 let (n, reply) = reply.accept(&mut output).unwrap();
527
528 assert_eq!(&output[..n], b"HTTP/1.1 100 Continue\r\n\r\n");
529
530 let mut reply = reply;
532 let mut body_buf = vec![0_u8; 1024];
533
534 let input = b"5\r\nhello\r\n";
536 let (input_used, output_used) = reply.read(input, &mut body_buf).unwrap();
537 assert_eq!(input_used, 10);
538 assert_eq!(&body_buf[..output_used], b"hello");
539
540 let input = b"0\r\n\r\n";
542 let (input_used, output_used) = reply.read(input, &mut body_buf[5..]).unwrap();
543 assert_eq!(input_used, 5);
544 assert_eq!(output_used, 0);
545
546 assert!(reply.is_ended());
547 }
548
549 #[test]
550 fn post_with_content_length() {
551 let mut reply = Reply::new().unwrap();
552
553 let input = b"POST /data HTTP/1.1\r\n\
555 host: test.local\r\n\
556 content-length: 11\r\n\
557 \r\n";
558 let (input_used, request) = reply.try_request(input).unwrap();
559 let request = request.unwrap();
560
561 assert_eq!(input_used, 61); assert_eq!(request.method(), "POST");
563 assert_eq!(request.uri().path(), "/data");
564
565 let reply = reply.proceed().unwrap();
567 let mut reply = match reply {
568 RecvRequestResult::RecvBody(r) => r,
569 _ => panic!("Expected RecvBody state"),
570 };
571
572 let mut body_buf = vec![0_u8; 1024];
574 let input = b"Hello World";
575 let (input_used, output_used) = reply.read(input, &mut body_buf).unwrap();
576
577 assert_eq!(input_used, 11);
578 assert_eq!(&body_buf[..output_used], b"Hello World");
579 assert!(reply.is_ended());
580 }
581
582 #[test]
583 fn head_response_with_body_fails() {
584 let mut reply = Reply::new().unwrap();
585
586 let input = b"HEAD /status HTTP/1.1\r\n\
588 host: test.local\r\n\
589 \r\n";
590 let (input_used, request) = reply.try_request(input).unwrap();
591 let request = request.unwrap();
592
593 assert_eq!(input_used, 43); assert_eq!(request.method(), "HEAD");
595 assert_eq!(request.uri().path(), "/status");
596
597 let reply = reply.proceed().unwrap();
599 let RecvRequestResult::ProvideResponse(reply) = reply else {
600 panic!("Expected ProvideResponse state");
601 };
602
603 let response = Response::builder()
605 .status(StatusCode::OK)
606 .header("content-length", "1000") .body(())
608 .unwrap();
609
610 reply
611 .provide(response)
612 .expect_err("no body allowed on HEAD response");
613 }
614
615 #[test]
616 fn head_response_with_body_and_footgun() {
617 let mut reply = Reply::new().unwrap();
618
619 let input = b"HEAD /status HTTP/1.1\r\n\
621 host: test.local\r\n\
622 \r\n";
623 let (input_used, request) = reply.try_request(input).unwrap();
624 let request = request.unwrap();
625
626 assert_eq!(input_used, 43); assert_eq!(request.method(), "HEAD");
628 assert_eq!(request.uri().path(), "/status");
629
630 let reply = reply.proceed().unwrap();
632 let RecvRequestResult::ProvideResponse(mut reply) = reply else {
633 panic!("Expected ProvideResponse state");
634 };
635
636 let response = Response::builder()
638 .status(StatusCode::OK)
639 .header("content-length", "1000") .body(())
641 .unwrap();
642
643 reply.force_send_body();
644 let mut reply = reply.provide(response).unwrap();
645
646 let mut output = vec![0_u8; 1024];
648 let n = reply.write(&mut output).unwrap();
649
650 let s = str::from_utf8(&output[..n]).unwrap();
652 assert!(s.contains("content-length: 1000"));
653 assert!(!s.contains("transfer-encoding"));
654 }
655
656 #[test]
657 fn post_streaming() {
658 let mut reply = Reply::new().unwrap();
659
660 let input = b"POST /upload HTTP/1.1\r\n\
662 host: test.local\r\n\
663 transfer-encoding: chunked\r\n\
664 \r\n";
665 let (input_used, request) = reply.try_request(input).unwrap();
666 let request = request.unwrap();
667
668 assert_eq!(input_used, 71);
669 assert_eq!(request.method(), "POST");
670 assert_eq!(request.uri().path(), "/upload");
671
672 let reply = reply.proceed().unwrap();
674 let mut reply = match reply {
675 RecvRequestResult::RecvBody(r) => r,
676 _ => panic!("Expected RecvBody state"),
677 };
678
679 let mut body_buf = vec![0_u8; 1024];
681 let input = b"5\r\nhello\r\n";
682 let (input_used, output_used) = reply.read(input, &mut body_buf).unwrap();
683 assert_eq!(input_used, 10);
684 assert_eq!(output_used, 5);
685 assert_eq!(&body_buf[..output_used], b"hello");
686
687 let input = b"0\r\n\r\n";
689 let (input_used, output_used) = reply.read(input, &mut body_buf[5..]).unwrap();
690 assert_eq!(input_used, 5);
691 assert_eq!(output_used, 0);
692 assert!(reply.is_ended());
693 }
694
695 #[test]
696 fn post_small_input() {
697 let mut reply = Reply::new().unwrap();
698
699 let input1 = b"POST /upload";
701 let (used1, req1) = reply.try_request(input1).unwrap();
702 assert_eq!(used1, 0);
703 assert!(req1.is_none());
704
705 let input2 = b"POST /upload HTTP/1.1\r\n";
706 let (used2, req2) = reply.try_request(input2).unwrap();
707 assert_eq!(used2, 0);
708 assert!(req2.is_none());
709
710 let input3 = b"POST /upload HTTP/1.1\r\n\
711 host: test.local\r\n";
712 let (used3, req3) = reply.try_request(input3).unwrap();
713 assert_eq!(used3, 0);
714 assert!(req3.is_none());
715
716 let input4 = b"POST /upload HTTP/1.1\r\n\
717 host: test.local\r\n\
718 \r\n";
719 let (used4, req4) = reply.try_request(input4).unwrap();
720 assert_eq!(used4, 43);
721 let request = req4.unwrap();
722 assert_eq!(request.method(), "POST");
723 assert_eq!(request.uri().path(), "/upload");
724 }
725
726 #[test]
727 fn post_with_short_content_length() {
728 let mut reply = Reply::new().unwrap();
729
730 let input = b"POST /upload HTTP/1.1\r\n\
732 host: test.local\r\n\
733 content-length: 2\r\n\
734 \r\n";
735 let (input_used, request) = reply.try_request(input).unwrap();
736 let request = request.unwrap();
737
738 assert_eq!(input_used, 62);
739 assert_eq!(request.method(), "POST");
740
741 let reply = reply.proceed().unwrap();
743 let mut reply = match reply {
744 RecvRequestResult::RecvBody(r) => r,
745 _ => panic!("Expected RecvBody state"),
746 };
747
748 let mut body_buf = vec![0_u8; 1024];
750 let input = b"hello";
751 let (i1, o1) = reply.read(input, &mut body_buf).unwrap();
752 assert_eq!(i1, 2);
753 assert_eq!(o1, 2);
754
755 assert!(reply.is_ended());
756 }
757
758 #[test]
759 fn post_streaming_too_much() {
760 let mut reply = Reply::new().unwrap();
761
762 let input = b"POST /upload HTTP/1.1\r\n\
764 host: test.local\r\n\
765 content-length: 5\r\n\
766 \r\n";
767 let (input_used, request) = reply.try_request(input).unwrap();
768 let request = request.unwrap();
769
770 assert_eq!(input_used, 62);
771 assert_eq!(request.method(), "POST");
772
773 let reply = reply.proceed().unwrap();
775 let mut reply = match reply {
776 RecvRequestResult::RecvBody(r) => r,
777 _ => panic!("Expected RecvBody state"),
778 };
779
780 let mut body_buf = vec![0_u8; 1024];
782 let input = b"hello world"; let (input_used, output_used) = reply.read(input, &mut body_buf).unwrap();
784 assert_eq!(input_used, 5);
785 assert_eq!(output_used, 5);
786 }
787
788 #[test]
789 fn post_streaming_after_end() {
790 let mut reply = Reply::new().unwrap();
791
792 let input = b"POST /upload HTTP/1.1\r\n\
794 host: test.local\r\n\
795 transfer-encoding: chunked\r\n\
796 \r\n";
797 let (input_used, request) = reply.try_request(input).unwrap();
798 let request = request.unwrap();
799
800 assert_eq!(input_used, 71);
801 assert_eq!(request.method(), "POST");
802
803 let reply = reply.proceed().unwrap();
805 let mut reply = match reply {
806 RecvRequestResult::RecvBody(r) => r,
807 _ => panic!("Expected RecvBody state"),
808 };
809
810 let mut body_buf = vec![0_u8; 1024];
812
813 let input = b"5\r\nhello\r\n";
815 let (input_used, output_used) = reply.read(input, &mut body_buf).unwrap();
816 assert_eq!(input_used, 10);
817 assert_eq!(output_used, 5);
818
819 let input = b"0\r\n\r\n";
821 let (input_used, output_used) = reply.read(input, &mut body_buf[5..]).unwrap();
822 assert_eq!(input_used, 5);
823 assert_eq!(output_used, 0);
824 assert!(reply.is_ended());
825
826 let input = b"more data";
828 let (i1, o1) = reply.read(input, &mut body_buf).unwrap();
829 assert_eq!(i1, 0);
830 assert_eq!(o1, 0);
831 }
832
833 #[test]
834 fn post_with_short_body_input() {
835 let mut reply = Reply::new().unwrap();
836
837 let input = b"POST /upload HTTP/1.1\r\n\
839 host: test.local\r\n\
840 content-length: 11\r\n\
841 \r\n";
842 let (input_used, request) = reply.try_request(input).unwrap();
843 let request = request.unwrap();
844
845 assert_eq!(input_used, 63);
846 assert_eq!(request.method(), "POST");
847
848 let reply = reply.proceed().unwrap();
850 let mut reply = match reply {
851 RecvRequestResult::RecvBody(r) => r,
852 _ => panic!("Expected RecvBody state"),
853 };
854
855 let mut body_buf = vec![0_u8; 1024];
857
858 let input = b"He";
860 let (input_used, output_used) = reply.read(input, &mut body_buf).unwrap();
861 assert_eq!(input_used, 2);
862 assert_eq!(output_used, 2);
863 assert_eq!(&body_buf[..output_used], b"He");
864
865 let input = b"llo ";
867 let (input_used, output_used) = reply.read(input, &mut body_buf[2..]).unwrap();
868 assert_eq!(input_used, 4);
869 assert_eq!(output_used, 4);
870 assert_eq!(&body_buf[..6], b"Hello ");
871
872 let input = b"World";
874 let (input_used, output_used) = reply.read(input, &mut body_buf[6..]).unwrap();
875 assert_eq!(input_used, 5);
876 assert_eq!(output_used, 5);
877 assert_eq!(&body_buf[..11], b"Hello World");
878 assert!(reply.is_ended());
879 }
880
881 #[test]
882 fn non_standard_method_is_ok() {
883 let mut reply = Reply::new().unwrap();
884
885 let input = b"FNORD /page HTTP/1.1\r\n\
887 host: test.local\r\n\
888 \r\n";
889
890 let result = reply.try_request(input);
891 assert!(result.is_ok());
892 }
893
894 #[test]
895 fn ensure_reasonable_stack_sizes() {
896 macro_rules! ensure {
897 ($type:ty, $size:tt) => {
898 let sz = std::mem::size_of::<$type>();
899 assert!(
900 sz <= $size,
901 "Stack size of {} is too big {} > {}",
902 stringify!($type),
903 sz,
904 $size
905 );
906 };
907 }
908
909 ensure!(http::Response<()>, 300); ensure!(AmendedResponse, 400); ensure!(Inner, 600); ensure!(Reply<RecvRequest>, 600); }
914
915 #[test]
916 fn connect() {
917 let mut reply = Reply::new().unwrap();
918
919 let input = b"CONNECT example.com HTTP/1.1\r\nhost: example.com\r\n\r\n";
920
921 let (input_used, request) = reply.try_request(input).unwrap();
922 let request = request.unwrap();
923
924 assert_eq!(input_used, 51);
925 assert_eq!(request.method(), "CONNECT");
926 assert_eq!(request.uri().path(), "");
927
928 let RecvRequestResult::ProvideResponse(reply) = reply.proceed().unwrap() else {
930 panic!("Expected ProvideResponse state");
931 };
932
933 let response = Response::builder().status(StatusCode::OK).body(()).unwrap();
934
935 let mut reply = reply.provide(response).unwrap();
936
937 let mut output = vec![0_u8; 1024];
938 let n = reply.write(&mut output).unwrap();
939
940 let s = str::from_utf8(&output[..n]).unwrap();
942 assert_eq!(s, "HTTP/1.1 200 OK\r\n\r\n");
943
944 let SendResponseResult::Cleanup(_reply) = reply.proceed() else {
946 panic!("Expected Cleanup state")
947 };
948 }
949
950 #[test]
951 fn connect_read_body() {
952 let mut reply = Reply::new().unwrap();
953 reply.force_recv_body();
954
955 let input =
956 b"CONNECT example.com HTTP/1.1\r\nhost: example.com\r\ncontent-length: 1024\r\n\r\n";
957
958 let (input_used, request) = reply.try_request(input).unwrap();
959 let request = request.unwrap();
960
961 assert_eq!(input_used, 73);
962 assert_eq!(request.method(), "CONNECT");
963 assert_eq!(request.uri().path(), "");
964
965 let RecvRequestResult::RecvBody(_reply) = reply.proceed().unwrap() else {
967 panic!("Expected RecvBody state");
968 };
969 }
970
971 #[test]
972 fn connect_send_body_fails() {
973 let mut reply = Reply::new().unwrap();
974
975 let input =
976 b"CONNECT example.com HTTP/1.1\r\nhost: example.com\r\ncontent-length: 1024\r\n\r\n";
977
978 let (input_used, request) = reply.try_request(input).unwrap();
979 let request = request.unwrap();
980
981 assert_eq!(input_used, 73);
982 assert_eq!(request.method(), "CONNECT");
983 assert_eq!(request.uri().path(), "");
984
985 let RecvRequestResult::ProvideResponse(reply) = reply.proceed().unwrap() else {
987 panic!("Expected ProvideResponse state");
988 };
989
990 let response = Response::builder()
991 .status(StatusCode::OK)
992 .header("content-length", 1024)
993 .body(())
994 .unwrap();
995
996 reply
997 .provide(response)
998 .expect_err("no body allowed on CONNECT response");
999 }
1000
1001 #[test]
1002 fn connect_send_body_with_footgun() {
1003 let mut reply = Reply::new().unwrap();
1004
1005 let input =
1006 b"CONNECT example.com HTTP/1.1\r\nhost: example.com\r\ncontent-length: 1024\r\n\r\n";
1007
1008 let (input_used, request) = reply.try_request(input).unwrap();
1009 let request = request.unwrap();
1010
1011 assert_eq!(input_used, 73);
1012 assert_eq!(request.method(), "CONNECT");
1013 assert_eq!(request.uri().path(), "");
1014
1015 let RecvRequestResult::ProvideResponse(mut reply) = reply.proceed().unwrap() else {
1017 panic!("Expected ProvideResponse state");
1018 };
1019
1020 let response = Response::builder()
1021 .status(StatusCode::OK)
1022 .header("content-length", 1024)
1023 .body(())
1024 .unwrap();
1025
1026 reply.force_send_body();
1027 let mut reply = reply.provide(response).unwrap();
1028
1029 let mut output = vec![0_u8; 1024];
1030 let n = reply.write(&mut output).unwrap();
1031
1032 let s = str::from_utf8(&output[..n]).unwrap();
1033 assert_eq!(s, "HTTP/1.1 200 OK\r\ncontent-length: 1024\r\n\r\n");
1034
1035 let SendResponseResult::SendBody(_reply) = reply.proceed() else {
1036 panic!("Expected SendBody state")
1037 };
1038 }
1039}