@@ -422,8 +422,8 @@ func (t *transferWriter) doBodyCopy(dst io.Writer, src io.Reader) (n int64, err
422
422
//
423
423
// This function is only intended for use in writeBody.
424
424
func (t * transferWriter ) unwrapBody () io.Reader {
425
- if reflect . TypeOf (t .Body ) == nopCloserType {
426
- return reflect . ValueOf ( t . Body ). Field ( 0 ). Interface ().(io. Reader )
425
+ if r , ok := unwrapNopCloser (t .Body ); ok {
426
+ return r
427
427
}
428
428
if r , ok := t .Body .(* readTrackingBody ); ok {
429
429
r .didRead = true
@@ -1081,6 +1081,21 @@ func (fr finishAsyncByteRead) Read(p []byte) (n int, err error) {
1081
1081
}
1082
1082
1083
1083
var nopCloserType = reflect .TypeOf (io .NopCloser (nil ))
1084
+ var nopCloserWriterToType = reflect .TypeOf (io .NopCloser (struct {
1085
+ io.Reader
1086
+ io.WriterTo
1087
+ }{}))
1088
+
1089
+ // unwrapNopCloser return the underlying reader and true if r is a NopCloser
1090
+ // else it return false
1091
+ func unwrapNopCloser (r io.Reader ) (underlyingReader io.Reader , isNopCloser bool ) {
1092
+ switch reflect .TypeOf (r ) {
1093
+ case nopCloserType , nopCloserWriterToType :
1094
+ return reflect .ValueOf (r ).Field (0 ).Interface ().(io.Reader ), true
1095
+ default :
1096
+ return nil , false
1097
+ }
1098
+ }
1084
1099
1085
1100
// isKnownInMemoryReader reports whether r is a type known to not
1086
1101
// block on Read. Its caller uses this as an optional optimization to
@@ -1090,8 +1105,8 @@ func isKnownInMemoryReader(r io.Reader) bool {
1090
1105
case * bytes.Reader , * bytes.Buffer , * strings.Reader :
1091
1106
return true
1092
1107
}
1093
- if reflect . TypeOf ( r ) == nopCloserType {
1094
- return isKnownInMemoryReader (reflect . ValueOf ( r ). Field ( 0 ). Interface ().(io. Reader ) )
1108
+ if r , ok := unwrapNopCloser ( r ); ok {
1109
+ return isKnownInMemoryReader (r )
1095
1110
}
1096
1111
if r , ok := r .(* readTrackingBody ); ok {
1097
1112
return isKnownInMemoryReader (r .ReadCloser )
0 commit comments