11using System . Text ;
22using Http11Probe . Client ;
3+ using Http11Probe . Response ;
34
45namespace Http11Probe . TestCases . Suites ;
56
@@ -483,9 +484,11 @@ public static IEnumerable<TestCase> GetTestCases()
483484 RfcReference = "RFC 9112 §6.2" ,
484485 PayloadFactory = ctx => MakeRequest (
485486 $ "POST / HTTP/1.1\r \n Host: { ctx . HostHeader } \r \n Content-Length: 5\r \n \r \n hello") ,
487+ BehavioralAnalyzer = EchoAnalyzer ( "hello" ) ,
486488 Expected = new ExpectedBehavior
487489 {
488- ExpectedStatus = StatusCodeRange . Range2xx
490+ Description = "2xx + echo" ,
491+ CustomValidator = EchoValidator ( "hello" )
489492 }
490493 } ;
491494
@@ -550,9 +553,11 @@ public static IEnumerable<TestCase> GetTestCases()
550553 RfcReference = "RFC 9112 §7.1" ,
551554 PayloadFactory = ctx => MakeRequest (
552555 $ "POST / HTTP/1.1\r \n Host: { ctx . HostHeader } \r \n Transfer-Encoding: chunked\r \n \r \n 5\r \n hello\r \n 0\r \n \r \n ") ,
556+ BehavioralAnalyzer = EchoAnalyzer ( "hello" ) ,
553557 Expected = new ExpectedBehavior
554558 {
555- ExpectedStatus = StatusCodeRange . Range2xx
559+ Description = "2xx + echo" ,
560+ CustomValidator = EchoValidator ( "hello" )
556561 }
557562 } ;
558563
@@ -564,9 +569,11 @@ public static IEnumerable<TestCase> GetTestCases()
564569 RfcReference = "RFC 9112 §7.1" ,
565570 PayloadFactory = ctx => MakeRequest (
566571 $ "POST / HTTP/1.1\r \n Host: { ctx . HostHeader } \r \n Transfer-Encoding: chunked\r \n \r \n 5\r \n hello\r \n 6\r \n world\r \n 0\r \n \r \n ") ,
572+ BehavioralAnalyzer = EchoAnalyzer ( "hello world" ) ,
567573 Expected = new ExpectedBehavior
568574 {
569- ExpectedStatus = StatusCodeRange . Range2xx
575+ Description = "2xx + echo" ,
576+ CustomValidator = EchoValidator ( "hello world" )
570577 }
571578 } ;
572579
@@ -755,17 +762,23 @@ public static IEnumerable<TestCase> GetTestCases()
755762 RfcReference = "RFC 9112 §7.1.1" ,
756763 PayloadFactory = ctx => MakeRequest (
757764 $ "POST / HTTP/1.1\r \n Host: { ctx . HostHeader } \r \n Transfer-Encoding: chunked\r \n \r \n 5;ext=value\r \n hello\r \n 0\r \n \r \n ") ,
765+ BehavioralAnalyzer = EchoAnalyzer ( "hello" ) ,
758766 Expected = new ExpectedBehavior
759767 {
760768 Description = "2xx preferred; 400 warns" ,
761769 CustomValidator = ( response , state ) =>
762770 {
763771 if ( response is null )
764772 return state == ConnectionState . ClosedByServer ? TestVerdict . Warn : TestVerdict . Fail ;
765- if ( response . StatusCode is >= 200 and < 300 )
766- return TestVerdict . Pass ;
767773 if ( response . StatusCode == 400 )
768774 return TestVerdict . Warn ;
775+ if ( response . StatusCode is >= 200 and < 300 )
776+ {
777+ var body = ( response . Body ?? "" ) . TrimEnd ( '\r ' , '\n ' ) ;
778+ if ( body == "hello" ) return TestVerdict . Pass ;
779+ if ( IsStaticResponse ( body ) || body . Length == 0 ) return TestVerdict . Pass ;
780+ return TestVerdict . Warn ;
781+ }
769782 return TestVerdict . Fail ;
770783 }
771784 }
@@ -1028,9 +1041,11 @@ public static IEnumerable<TestCase> GetTestCases()
10281041 RfcReference = "RFC 9112 §7.1.2" ,
10291042 PayloadFactory = ctx => MakeRequest (
10301043 $ "POST / HTTP/1.1\r \n Host: { ctx . HostHeader } \r \n Transfer-Encoding: chunked\r \n \r \n 5\r \n hello\r \n 0\r \n X-Checksum: abc\r \n \r \n ") ,
1044+ BehavioralAnalyzer = EchoAnalyzer ( "hello" ) ,
10311045 Expected = new ExpectedBehavior
10321046 {
1033- ExpectedStatus = StatusCodeRange . Range ( 200 , 299 )
1047+ Description = "2xx + echo" ,
1048+ CustomValidator = EchoValidator ( "hello" )
10341049 }
10351050 } ;
10361051
@@ -1042,9 +1057,11 @@ public static IEnumerable<TestCase> GetTestCases()
10421057 RfcReference = "RFC 9112 §7.1" ,
10431058 PayloadFactory = ctx => MakeRequest (
10441059 $ "POST / HTTP/1.1\r \n Host: { ctx . HostHeader } \r \n Transfer-Encoding: chunked\r \n \r \n A\r \n helloworld\r \n 0\r \n \r \n ") ,
1060+ BehavioralAnalyzer = EchoAnalyzer ( "helloworld" ) ,
10451061 Expected = new ExpectedBehavior
10461062 {
1047- ExpectedStatus = StatusCodeRange . Range ( 200 , 299 )
1063+ Description = "2xx + echo" ,
1064+ CustomValidator = EchoValidator ( "helloworld" )
10481065 }
10491066 } ;
10501067
@@ -1234,5 +1251,38 @@ public static IEnumerable<TestCase> GetTestCases()
12341251 } ;
12351252 }
12361253
1254+ // ── Echo verification helpers ──────────────────────────────
1255+
1256+ private static bool IsStaticResponse ( string body ) => body == "OK" ;
1257+
1258+ private static Func < HttpResponse ? , string ? > EchoAnalyzer ( string expectedBody )
1259+ {
1260+ return response =>
1261+ {
1262+ if ( response is null || response . StatusCode is < 200 or >= 300 ) return null ;
1263+ var body = ( response . Body ?? "" ) . TrimEnd ( '\r ' , '\n ' ) ;
1264+ if ( IsStaticResponse ( body ) ) return "Static response — server does not echo POST body" ;
1265+ if ( body == expectedBody ) return "Echoed correctly" ;
1266+ if ( body . Length == 0 ) return "Empty body" ;
1267+ return $ "Echo mismatch: expected \" { expectedBody } \" , got \" { ( body . Length > 40 ? body [ ..40 ] + "..." : body ) } \" ";
1268+ } ;
1269+ }
1270+
1271+ private static Func < HttpResponse ? , ConnectionState , TestVerdict > EchoValidator ( string expectedBody )
1272+ {
1273+ return ( response , state ) =>
1274+ {
1275+ if ( response is null )
1276+ return TestVerdict . Fail ;
1277+ if ( response . StatusCode is < 200 or >= 300 )
1278+ return TestVerdict . Fail ;
1279+ var body = ( response . Body ?? "" ) . TrimEnd ( '\r ' , '\n ' ) ;
1280+ if ( body == expectedBody ) return TestVerdict . Pass ;
1281+ if ( IsStaticResponse ( body ) ) return TestVerdict . Pass ;
1282+ if ( body . Length == 0 ) return TestVerdict . Pass ;
1283+ return TestVerdict . Warn ;
1284+ } ;
1285+ }
1286+
12371287 private static byte [ ] MakeRequest ( string request ) => Encoding . ASCII . GetBytes ( request ) ;
12381288}
0 commit comments