()
| 763 | |
| 764 | #[tokio::test] |
| 765 | async fn callback_server_handles_cors_preflight() { |
| 766 | let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); |
| 767 | let addr = listener.local_addr().unwrap(); |
| 768 | let (tx, rx) = oneshot::channel(); |
| 769 | |
| 770 | tokio::spawn(run_callback_server( |
| 771 | listener, |
| 772 | tx, |
| 773 | "ABC-1234".to_string(), |
| 774 | TEST_GATEWAY.to_string(), |
| 775 | )); |
| 776 | |
| 777 | // Send OPTIONS preflight with correct origin. |
| 778 | let mut stream = tokio::net::TcpStream::connect(addr).await.unwrap(); |
| 779 | let preflight = format!( |
| 780 | "OPTIONS /callback HTTP/1.1\r\n\ |
| 781 | Host: 127.0.0.1\r\n\ |
| 782 | Origin: {TEST_GATEWAY}\r\n\r\n" |
| 783 | ); |
| 784 | stream.write_all(preflight.as_bytes()).await.unwrap(); |
| 785 | |
| 786 | let mut buf = vec![0u8; 4096]; |
| 787 | let n = stream.read(&mut buf).await.unwrap(); |
| 788 | let response = String::from_utf8_lossy(&buf[..n]); |
| 789 | let expected_header = format!("access-control-allow-origin: {TEST_GATEWAY}"); |
| 790 | assert!( |
| 791 | response.contains("204 No Content"), |
| 792 | "preflight should return 204:\n{response}" |
| 793 | ); |
| 794 | assert!( |
| 795 | response |
| 796 | .lines() |
| 797 | .any(|line| line.eq_ignore_ascii_case(&expected_header)), |
| 798 | "preflight should reflect gateway origin:\n{response}" |
| 799 | ); |
| 800 | |
| 801 | // Now send the actual POST — the server should still be listening. |
| 802 | let mut stream = tokio::net::TcpStream::connect(addr).await.unwrap(); |
| 803 | let body = r#"{"token":"jwt-after-preflight","code":"ABC-1234"}"#; |
| 804 | let request = format!( |
| 805 | "POST /callback HTTP/1.1\r\n\ |
| 806 | Host: 127.0.0.1\r\n\ |
| 807 | Origin: {TEST_GATEWAY}\r\n\ |
| 808 | Content-Type: application/json\r\n\ |
| 809 | Content-Length: {}\r\n\r\n\ |
| 810 | {}", |
| 811 | body.len(), |
| 812 | body, |
| 813 | ); |
| 814 | stream.write_all(request.as_bytes()).await.unwrap(); |
| 815 | |
| 816 | let token = rx.await.unwrap(); |
| 817 | assert_eq!(token, "jwt-after-preflight"); |
| 818 | } |
| 819 | |
| 820 | #[tokio::test] |
| 821 | async fn callback_server_handles_fragmented_post_body() { |
nothing calls this directly
no test coverage detected