Skip to content

net/http/httptest: wrong ContentLength for request with http.NoBody #68476

Closed
@jfrancisco0

Description

@jfrancisco0

Go version

go version go1.22.5 darwin/arm64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/jfrancisco/Library/Caches/go-build'
GOENV='/Users/jfrancisco/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/jfrancisco/go/pkg/mod'
GONOPROXY='github.com/<redacted>/*'
GONOSUMDB='github.com/<redacted>/*'
GOOS='darwin'
GOPATH='/Users/jfrancisco/go'
GOPRIVATE='github.com/<redacted>/*'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.22.5/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.22.5/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.22.5'
GCCGO='gccgo'
AR='ar'
CC='cc'
CXX='c++'
CGO_ENABLED='1'
GOMOD='/Users/jfrancisco/golang/src/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/x9/7wxj63rn0f573d7zdjy3m63w0000gn/T/go-build2393148245=/tmp/go-build -gno-record-gcc-switches -fno-common'

What did you do?

The gocritic linter suggests I should use http.NoBody instead of nil for empty body requests. However, httptest.NewRequest() shows different behaviour when http.NoBody is sent vs when nil is sent. Note that this is only the case for the httptest package, as http.NewRequest() - from the http package - works as expected.

See the example from https://go.dev/play/p/n9UxgUsAfM8

What did you see happen?

Creating a request with a http.NoBody body results in a ContentLength value of -1 instead of the expected 0 you would get with a nil body.

httptest.NewRequest("GET", "/", nil)
http.NewRequest("GET", "/", http.NoBody)

set ContentLength as 0, but

httptest.NewRequest("GET", "/", http.NoBody)

sets ContentLength as -1.

This makes my tests fail, as the server returns an error. According to the documentation, ContentLength: -1 means unknown, which should not be the case for http.NoBody, as that's and empty body (length 0). This happens because http.NoBody is a io.ReadCloser, which doesn't match any of the types in the switch.

What did you expect to see?

The request with a http.NoBody body should have ContentLength: 0.

The http package never sets a negative ContentLength for backwards compatibility (source).

I suggest that either the same logic is ported over to the httptest package, or that http.NoBody is accounted for as an exception, like it was in the http package before the reversal in this commit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    FixPendingIssues that have a fix which has not yet been reviewed or submitted.NeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions