From 68f39ad66bf05dd2b23b3c9c201eba95ce0a92bf Mon Sep 17 00:00:00 2001 From: forgejo-backport-action Date: Mon, 26 Jan 2026 20:41:29 +0100 Subject: [PATCH] [v14.0/forgejo] fix NewMockWebServer(): Headers never reached the http client (#11058) **Backport:** https://codeberg.org/forgejo/forgejo/pulls/11007 Found while working on https://codeberg.org/forgejo/forgejo/pulls/10798#issuecomment-10083846: The symptom was that the go-github client never returned a `resp.After`, so I tracked down the root cause, which was that, with the mocked http server ... Mocked headers never reached the calling client, because w.WriteHeader() was called before the headers were set in the response. Fix by moving w.WriteHeader() to the right place just before w.Write(), which writes the body. Test added which fails without the fix and succeeds with it. Co-authored-by: Nils Goroll Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11058 Co-authored-by: forgejo-backport-action Co-committed-by: forgejo-backport-action --- models/unittest/mock_http.go | 10 +++++++--- models/unittest/mock_http_test.go | 24 ++++++++++++++++++++++++ models/unittest/testdata/GET_%2F | 3 +++ 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 models/unittest/mock_http_test.go create mode 100644 models/unittest/testdata/GET_%2F diff --git a/models/unittest/mock_http.go b/models/unittest/mock_http.go index c2c12e55ee..3c4ddd8e27 100644 --- a/models/unittest/mock_http.go +++ b/models/unittest/mock_http.go @@ -91,8 +91,6 @@ func NewMockWebServer(t *testing.T, liveServerBaseURL, testDataDir string, liveM fixture, err := os.ReadFile(fixturePath) require.NoError(t, err, "missing mock HTTP response: "+fixturePath) - w.WriteHeader(http.StatusOK) - // replace any mention of the live HTTP service by the mocked host stringFixture := strings.ReplaceAll(string(fixture), liveServerBaseURL, mockServerBaseURL) if isGh { @@ -104,10 +102,16 @@ func NewMockWebServer(t *testing.T, liveServerBaseURL, testDataDir string, liveM for idx, line := range lines { colonIndex := strings.Index(line, ": ") if colonIndex != -1 { - w.Header().Set(line[0:colonIndex], line[colonIndex+2:]) + // Because we modified the body with ReplaceAll() above, we need to + // remove Content-Length. w.Write() should add it back. + header := line[0:colonIndex] + if !strings.EqualFold(header, "Content-Length") { + w.Header().Set(line[0:colonIndex], line[colonIndex+2:]) + } } else { // we reached the end of the headers (empty line), so what follows is the body responseBody := strings.Join(lines[idx+1:], "\n") + w.WriteHeader(http.StatusOK) _, err := w.Write([]byte(responseBody)) require.NoError(t, err, "writing the body of the HTTP response failed") break diff --git a/models/unittest/mock_http_test.go b/models/unittest/mock_http_test.go new file mode 100644 index 0000000000..9ae4592aab --- /dev/null +++ b/models/unittest/mock_http_test.go @@ -0,0 +1,24 @@ +// Copyright 2026 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package unittest + +import ( + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// NOTE: This is a test of the unittest helper itself +func TestMockWebServer(t *testing.T) { + server := NewMockWebServer(t, "https://example.com", "testdata", false) + defer server.Close() + request, err := http.NewRequest("GET", server.URL+"/", nil) + require.NoError(t, err) + response, err := server.Client().Do(request) + require.NoError(t, err) + assert.Len(t, response.Header["Header"], 1) + assert.Equal(t, "value", response.Header["Header"][0]) +} diff --git a/models/unittest/testdata/GET_%2F b/models/unittest/testdata/GET_%2F new file mode 100644 index 0000000000..8b79a2cd25 --- /dev/null +++ b/models/unittest/testdata/GET_%2F @@ -0,0 +1,3 @@ +Header: value + +bodydata