Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 12, 02:00 UTC
reverseproxy: more comments about buffering and add new tests (#6778)
Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
WeidiDeng committed
Mar 8, 2025 at 02:22 UTC
220cd1c2bcecc07bcf6a0141069538c1b1109907
2 files changed
+88
modules/caddyhttp/reverseproxy/buffering_test.go
new
+84
@@ -0,0 +1,84 @@
1
+package reverseproxy
2
+
3
+import (
4
+ "io"
5
+ "testing"
6
+)
7
+
8
+type zeroReader struct{}
9
+
10
+func (zeroReader) Read(p []byte) (int, error) {
11
+ for i := range p {
12
+ p[i] = 0
13
+ }
14
+ return len(p), nil
15
+}
16
+
17
+func TestBuffering(t *testing.T) {
18
+ var (
19
+ h Handler
20
+ zr zeroReader
21
+ )
22
+ type args struct {
23
+ body io.ReadCloser
24
+ limit int64
25
+ }
26
+ tests := []struct {
27
+ name string
28
+ args args
29
+ resultCheck func(io.ReadCloser, int64, args) bool
30
+ }{
31
+ {
32
+ name: "0 limit, body is returned as is",
33
+ args: args{
34
+ body: io.NopCloser(&zr),
35
+ limit: 0,
36
+ },
37
+ resultCheck: func(res io.ReadCloser, read int64, args args) bool {
38
+ return res == args.body && read == args.limit && read == 0
39
+ },
40
+ },
41
+ {
42
+ name: "negative limit, body is read completely",
43
+ args: args{
44
+ body: io.NopCloser(io.LimitReader(&zr, 100)),
45
+ limit: -1,
46
+ },
47
+ resultCheck: func(res io.ReadCloser, read int64, args args) bool {
48
+ brc, ok := res.(bodyReadCloser)
49
+ return ok && brc.body == nil && brc.buf.Len() == 100 && read == 100
50
+ },
51
+ },
52
+ {
53
+ name: "positive limit, body is read partially",
54
+ args: args{
55
+ body: io.NopCloser(io.LimitReader(&zr, 100)),
56
+ limit: 50,
57
+ },
58
+ resultCheck: func(res io.ReadCloser, read int64, args args) bool {
59
+ brc, ok := res.(bodyReadCloser)
60
+ return ok && brc.body != nil && brc.buf.Len() == 50 && read == 50
61
+ },
62
+ },
63
+ {
64
+ name: "positive limit, body is read completely",
65
+ args: args{
66
+ body: io.NopCloser(io.LimitReader(&zr, 100)),
67
+ limit: 101,
68
+ },
69
+ resultCheck: func(res io.ReadCloser, read int64, args args) bool {
70
+ brc, ok := res.(bodyReadCloser)
71
+ return ok && brc.body == nil && brc.buf.Len() == 100 && read == 100
72
+ },
73
+ },
74
+ }
75
+ for _, tt := range tests {
76
+ t.Run(tt.name, func(t *testing.T) {
77
+ res, read := h.bufferedBody(tt.args.body, tt.args.limit)
78
+ if !tt.resultCheck(res, read, tt.args) {
79
+ t.Error("Handler.bufferedBody() test failed")
80
+ return
81
+ }
82
+ })
83
+ }
84
+}
modules/caddyhttp/reverseproxy/reverseproxy.go
+4
@@ -1234,6 +1234,10 @@ func (h Handler) provisionUpstream(upstream *Upstream) {
1234
// then returns a reader for the buffer along with how many bytes were buffered. Always close
1235
// the return value when done with it, just like if it was the original body! If limit is 0
1236
// (which it shouldn't be), this function returns its input; i.e. is a no-op, for safety.
1237
+// Otherwise, it returns bodyReadCloser, the original body will be closed and body will be nil
1238
+// if it's explicitly configured to buffer all or EOF is reached when reading.
1239
+// TODO: the error during reading is discarded if the limit is negative, should the error be propagated
1240
+// to upstream/downstream?
1241
func (h Handler) bufferedBody(originalBody io.ReadCloser, limit int64) (io.ReadCloser, int64) {
1242
if limit == 0 {
1243
return originalBody, 0