@@ -885,68 +885,56 @@ func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser {
885
885
}
886
886
887
887
type maxBytesReader struct {
888
- w ResponseWriter
889
- r io.ReadCloser // underlying reader
890
- n int64 // max bytes remaining
891
- stopped bool
892
- sawEOF bool
888
+ w ResponseWriter
889
+ r io.ReadCloser // underlying reader
890
+ n int64 // max bytes remaining
891
+ err error // sticky error
893
892
}
894
893
895
894
func (l * maxBytesReader ) tooLarge () (n int , err error ) {
896
- if ! l .stopped {
897
- l .stopped = true
898
-
899
- // The server code and client code both use
900
- // maxBytesReader. This "requestTooLarge" check is
901
- // only used by the server code. To prevent binaries
902
- // which only using the HTTP Client code (such as
903
- // cmd/go) from also linking in the HTTP server, don't
904
- // use a static type assertion to the server
905
- // "*response" type. Check this interface instead:
906
- type requestTooLarger interface {
907
- requestTooLarge ()
908
- }
909
- if res , ok := l .w .(requestTooLarger ); ok {
910
- res .requestTooLarge ()
911
- }
912
- }
913
- return 0 , errors .New ("http: request body too large" )
895
+ l .err = errors .New ("http: request body too large" )
896
+ return 0 , l .err
914
897
}
915
898
916
899
func (l * maxBytesReader ) Read (p []byte ) (n int , err error ) {
917
- toRead := l .n
918
- if l .n == 0 {
919
- if l .sawEOF {
920
- return l .tooLarge ()
921
- }
922
- // The underlying io.Reader may not return (0, io.EOF)
923
- // at EOF if the requested size is 0, so read 1 byte
924
- // instead. The io.Reader docs are a bit ambiguous
925
- // about the return value of Read when 0 bytes are
926
- // requested, and {bytes,strings}.Reader gets it wrong
927
- // too (it returns (0, nil) even at EOF).
928
- toRead = 1
900
+ if l .err != nil {
901
+ return 0 , l .err
902
+ }
903
+ if len (p ) == 0 {
904
+ return 0 , nil
929
905
}
930
- if int64 (len (p )) > toRead {
931
- p = p [:toRead ]
906
+ // If they asked for a 32KB byte read but only 5 bytes are
907
+ // remaining, no need to read 32KB. 6 bytes will answer the
908
+ // question of the whether we hit the limit or go past it.
909
+ if int64 (len (p )) > l .n + 1 {
910
+ p = p [:l .n + 1 ]
932
911
}
933
912
n , err = l .r .Read (p )
934
- if err == io .EOF {
935
- l .sawEOF = true
936
- }
937
- if l .n == 0 {
938
- // If we had zero bytes to read remaining (but hadn't seen EOF)
939
- // and we get a byte here, that means we went over our limit.
940
- if n > 0 {
941
- return l .tooLarge ()
942
- }
943
- return 0 , err
913
+
914
+ if int64 (n ) <= l .n {
915
+ l .n -= int64 (n )
916
+ l .err = err
917
+ return n , err
944
918
}
945
- l .n -= int64 (n )
946
- if l .n < 0 {
947
- l .n = 0
919
+
920
+ n = int (l .n )
921
+ l .n = 0
922
+
923
+ // The server code and client code both use
924
+ // maxBytesReader. This "requestTooLarge" check is
925
+ // only used by the server code. To prevent binaries
926
+ // which only using the HTTP Client code (such as
927
+ // cmd/go) from also linking in the HTTP server, don't
928
+ // use a static type assertion to the server
929
+ // "*response" type. Check this interface instead:
930
+ type requestTooLarger interface {
931
+ requestTooLarge ()
948
932
}
949
- return
933
+ if res , ok := l .w .(requestTooLarger ); ok {
934
+ res .requestTooLarge ()
935
+ }
936
+ l .err = errors .New ("http: request body too large" )
937
+ return n , l .err
950
938
}
951
939
952
940
func (l * maxBytesReader ) Close () error {
0 commit comments