fix: pre-read bodies with unknown length
This commit is contained in:
+1
-1
@@ -13,7 +13,7 @@ import (
|
|||||||
|
|
||||||
// readRequestBody 在转发前完整读取请求体,确保读取失败时不会向上游发送损坏请求。
|
// readRequestBody 在转发前完整读取请求体,确保读取失败时不会向上游发送损坏请求。
|
||||||
func readRequestBody(r *http.Request, max int64) (captured []byte, truncated bool, err error) {
|
func readRequestBody(r *http.Request, max int64) (captured []byte, truncated bool, err error) {
|
||||||
if r.Body == nil || r.ContentLength == 0 {
|
if r.Body == nil || r.Body == http.NoBody {
|
||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
}
|
}
|
||||||
body, err := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
|
|||||||
@@ -100,6 +100,30 @@ func TestRequestBodyReadFailureReturnsFixed400WithoutUpstream(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRequestBodyReadFailureWithZeroContentLengthDoesNotReachUpstream(t *testing.T) {
|
||||||
|
var upstreamCalls atomic.Int32
|
||||||
|
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
upstreamCalls.Add(1)
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
}))
|
||||||
|
defer upstream.Close()
|
||||||
|
u, _ := url.Parse(upstream.URL)
|
||||||
|
h := newTestHandler(t, u, &captureSubmitter{}, proxy.Options{})
|
||||||
|
|
||||||
|
req := httptest.NewRequest(http.MethodPost, "http://proxy.test/v1/chat", nil)
|
||||||
|
req.Body = failingBody{err: errors.New("secret read failure")}
|
||||||
|
req.ContentLength = 0
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
h.ServeHTTP(rec, req)
|
||||||
|
|
||||||
|
if rec.Code != http.StatusBadRequest || rec.Body.String() != "bad request\n" {
|
||||||
|
t.Fatalf("response=(%d, %q), want fixed 400 bad request", rec.Code, rec.Body.String())
|
||||||
|
}
|
||||||
|
if upstreamCalls.Load() != 0 {
|
||||||
|
t.Fatalf("upstream called %d times", upstreamCalls.Load())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRequestBodyReadFailureAfterCaptureLimitDoesNotReachUpstream(t *testing.T) {
|
func TestRequestBodyReadFailureAfterCaptureLimitDoesNotReachUpstream(t *testing.T) {
|
||||||
var upstreamCalls atomic.Int32
|
var upstreamCalls atomic.Int32
|
||||||
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
Reference in New Issue
Block a user