@@ -416,3 +416,102 @@ func TestDialViaProxy(t *testing.T) {
416416 assertEcho (t , ctx , c )
417417 assertClose (t , c )
418418}
419+
420+ // Additional tests for error response body capture behavior.
421+ // A tracking body to verify Close is called when capture is disabled.
422+ type trackingBodyDialTest struct {
423+ io.ReadCloser
424+ closed * bool
425+ }
426+
427+ func (tb trackingBodyDialTest ) Close () error {
428+ * tb .closed = true
429+ return tb .ReadCloser .Close ()
430+ }
431+
432+ func TestDial_ErrorResponseBodyCapture_DefaultAndCustom (t * testing.T ) {
433+ t .Parallel ()
434+
435+ longBody := strings .Repeat ("x" , 4096 )
436+
437+ s := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
438+ w .WriteHeader (http .StatusTeapot )
439+ io .WriteString (w , longBody )
440+ }))
441+ defer s .Close ()
442+
443+ ctx , cancel := context .WithTimeout (context .Background (), time .Second * 5 )
444+ defer cancel ()
445+
446+ // Default behavior (zero value options): capture up to 1024 bytes
447+ _ , resp , err := websocket .Dial (ctx , s .URL , nil )
448+ assert .Error (t , err )
449+ if resp == nil {
450+ t .Fatal ("expected non-nil resp" )
451+ }
452+ assert .Equal (t , "StatusCode" , http .StatusTeapot , resp .StatusCode )
453+
454+ b , rerr := io .ReadAll (resp .Body )
455+ assert .Success (t , rerr )
456+ if len (b ) > 1024 {
457+ t .Fatalf ("expected captured body length <= 1024, got %d" , len (b ))
458+ }
459+ if exp := longBody [:len (b )]; string (b ) != exp {
460+ t .Fatalf ("unexpected body prefix: expected %d bytes prefix match" , len (b ))
461+ }
462+
463+ // Custom limit (>0)
464+ limit := 200
465+ _ , resp , err = websocket .Dial (ctx , s .URL , & websocket.DialOptions {MaxErrorResponseBodyBytes : limit })
466+ assert .Error (t , err )
467+ if resp == nil {
468+ t .Fatal ("expected non-nil resp" )
469+ }
470+ assert .Equal (t , "StatusCode" , http .StatusTeapot , resp .StatusCode )
471+
472+ b , rerr = io .ReadAll (resp .Body )
473+ assert .Success (t , rerr )
474+ if len (b ) > limit {
475+ t .Fatalf ("expected captured body length <= %d, got %d" , limit , len (b ))
476+ }
477+ if exp := longBody [:len (b )]; string (b ) != exp {
478+ t .Fatalf ("unexpected body prefix: expected %d bytes prefix match" , len (b ))
479+ }
480+ }
481+
482+ func TestDial_ErrorResponseBodyCapture_Disabled_NoBodyWithClose (t * testing.T ) {
483+ t .Parallel ()
484+
485+ closed := false
486+ rt := func (r * http.Request ) (* http.Response , error ) {
487+ // Return a long body and a non-101 status to trigger error path.
488+ return & http.Response {
489+ StatusCode : http .StatusForbidden ,
490+ Body : trackingBodyDialTest {io .NopCloser (strings .NewReader (strings .Repeat ("y" , 4096 ))), & closed },
491+ }, nil
492+ }
493+
494+ ctx , cancel := context .WithTimeout (context .Background (), time .Second * 5 )
495+ defer cancel ()
496+
497+ _ , resp , err := websocket .Dial (ctx , "ws://example.com" , & websocket.DialOptions {
498+ HTTPClient : mockHTTPClient (rt ),
499+ MaxErrorResponseBodyBytes : - 1 ,
500+ })
501+ assert .Error (t , err )
502+ if resp == nil {
503+ t .Fatal ("expected non-nil resp" )
504+ }
505+ assert .Equal (t , "StatusCode" , http .StatusForbidden , resp .StatusCode )
506+ if resp .Body != nil {
507+ // If any body is present, ensure it's empty.
508+ b , rerr := io .ReadAll (resp .Body )
509+ assert .Success (t , rerr )
510+ if len (b ) != 0 {
511+ t .Fatalf ("expected no body bytes when capture disabled, got %d" , len (b ))
512+ }
513+ }
514+ if ! closed {
515+ t .Fatal ("expected original body to be closed" )
516+ }
517+ }
0 commit comments