@marcel91200 / caddy Mirror · read-only / commits / 220cd1c2
Fork 0

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