Skip to content

Commit e2a4abb

Browse files
authored
refactor: drop space-to-underscore replacement in header names (#2441)
## Summary - Drop `" " -> "_"` from `headerNameReplacer`: Go's net/http rejects header names containing spaces with `400 Bad Request: invalid header name` before requests reach the handler, so the branch is unreachable. - Drop unused explicit type parameters on `otter.Must`. - Add `TestHeaderWithSpaceIsRejectedByNetHTTP` proving the rejection happens at the net/http layer.
1 parent 95216b1 commit e2a4abb

2 files changed

Lines changed: 29 additions & 2 deletions

File tree

internal/phpheaders/phpheaders.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ var CommonRequestHeaders = map[string]string{
120120
// Cache up to 256 uncommon headers
121121
// This is ~2.5x faster than converting the header each time
122122
var (
123-
headerKeyCache = otter.Must[string, string](&otter.Options[string, string]{MaximumSize: 256})
124-
headerNameReplacer = strings.NewReplacer(" ", "_", "-", "_")
123+
headerKeyCache = otter.Must(&otter.Options[string, string]{MaximumSize: 256})
124+
headerNameReplacer = strings.NewReplacer("-", "_")
125125
loader = otter.LoaderFunc[string, string](func(_ context.Context, key string) (string, error) {
126126
return "HTTP_" + headerNameReplacer.Replace(strings.ToUpper(key)) + "\x00", nil
127127
})

internal/phpheaders/phpheaders_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
package phpheaders
22

33
import (
4+
"io"
5+
"net"
6+
"net/http"
47
"net/http/httptest"
8+
"strings"
59
"testing"
610

711
"github.com/stretchr/testify/assert"
12+
"github.com/stretchr/testify/require"
813
)
914

1015
func TestAllCommonHeadersAreCorrect(t *testing.T) {
@@ -20,3 +25,25 @@ func TestAllCommonHeadersAreCorrect(t *testing.T) {
2025
assert.Contains(t, fakeRequest.Header, header, "header is not correctly capitalized: "+header)
2126
}
2227
}
28+
29+
// Go's net/http server rejects header names containing spaces with a 400 response
30+
// before the request reaches the handler, so headerNameReplacer does not need to
31+
// translate spaces to underscores.
32+
func TestHeaderWithSpaceIsRejectedByNetHTTP(t *testing.T) {
33+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
34+
t.Errorf("handler should not be reached, got headers: %v", r.Header)
35+
}))
36+
t.Cleanup(ts.Close)
37+
38+
conn, err := net.Dial("tcp", strings.TrimPrefix(ts.URL, "http://"))
39+
require.NoError(t, err)
40+
t.Cleanup(func() { require.NoError(t, conn.Close()) })
41+
42+
_, err = conn.Write([]byte("GET / HTTP/1.1\r\nHost: localhost\r\nBad Header: x\r\nConnection: close\r\n\r\n"))
43+
require.NoError(t, err)
44+
45+
resp, err := io.ReadAll(conn)
46+
require.NoError(t, err)
47+
assert.Contains(t, string(resp), "400 Bad Request")
48+
assert.Contains(t, string(resp), "invalid header name")
49+
}

0 commit comments

Comments
 (0)