From dffc7ada5eef8a8b3df7da8928536ce57135a119 Mon Sep 17 00:00:00 2001 From: FunLay123 <137938315+FunLay123@users.noreply.github.com> Date: Thu, 27 Aug 2026 03:41:43 +0700 Subject: [PATCH] XHTTP client: Define Request.GetBody() for packet-up so h2 can replay after GOAWAY (#6632) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/XTLS/Xray-core/pull/6632#issuecomment-5430735467 --------- Co-authored-by: 风扇滑翔翼 --- transport/internet/splithttp/config.go | 15 ++++++--- transport/internet/splithttp/config_test.go | 36 +++++++++++++++++++++ 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/transport/internet/splithttp/config.go b/transport/internet/splithttp/config.go index c2441386c..e06281b1b 100644 --- a/transport/internet/splithttp/config.go +++ b/transport/internet/splithttp/config.go @@ -1,6 +1,7 @@ package splithttp import ( + "bytes" "encoding/base64" "fmt" "io" @@ -330,14 +331,18 @@ func (c *Config) FillStreamRequest(request *http.Request, sessionId string, seqS func (c *Config) FillPacketRequest(request *http.Request, sessionId string, seqStr string, payload buf.MultiBuffer) error { dataPlacement := c.GetNormalizedUplinkDataPlacement() + data := make([]byte, payload.Len()) + payload.Copy(data) + buf.ReleaseMulti(payload) + if dataPlacement == PlacementBody || dataPlacement == PlacementAuto { request.Header = c.GetRequestHeader() - request.Body = io.NopCloser(&buf.MultiBufferContainer{MultiBuffer: payload}) - request.ContentLength = int64(payload.Len()) + request.Body = io.NopCloser(bytes.NewReader(data)) + request.ContentLength = int64(len(data)) + request.GetBody = func() (io.ReadCloser, error) { + return io.NopCloser(bytes.NewReader(data)), nil + } } else { - data := make([]byte, payload.Len()) - payload.Copy(data) - buf.ReleaseMulti(payload) switch dataPlacement { case PlacementHeader: request.Header = c.GetRequestHeaderWithPayload(data) diff --git a/transport/internet/splithttp/config_test.go b/transport/internet/splithttp/config_test.go index 2cb1e5e9d..2ee7470aa 100644 --- a/transport/internet/splithttp/config_test.go +++ b/transport/internet/splithttp/config_test.go @@ -1,9 +1,13 @@ package splithttp_test import ( + "io" + "net/http" "testing" "github.com/stretchr/testify/assert" + "github.com/xtls/xray-core/common" + "github.com/xtls/xray-core/common/buf" . "github.com/xtls/xray-core/transport/internet/splithttp" ) @@ -77,3 +81,35 @@ func Test_GetNormalizedPath(t *testing.T) { }) } } + +func Test_FillPacketRequest_GetBody(t *testing.T) { + data := []byte("hello xray") + payload := buf.MergeBytes(nil, data) + + req, err := http.NewRequest("POST", "https://example.com/", nil) + common.Must(err) + + config := &Config{} + config.FillPacketRequest(req, "sess", "0", payload) + + if req.GetBody == nil { + t.Fatalf("Expected GetBody to be set") + } + + first, err := io.ReadAll(req.Body) + common.Must(err) + + if string(data) != string(first) { + t.Fatalf("Body mismatch. Format %q and %q are not equal", data, first) + } + + body2, err := req.GetBody() + common.Must(err) + + second, err := io.ReadAll(body2) + common.Must(err) + + if string(data) != string(second) { + t.Fatalf("Replayed body mismatch. Format %q and %q are not equal", data, second) + } +}