timakin/bodyclose

Returning *http.Response to another function is not handled correctly

mkfsn opened this issue · 3 comments

mkfsn commented

Here is the sample code to reproduce:

package main

import (
	"net/http"
)

func getResponse(url string) *http.Response {
	res, _ := http.Get(url)
	return res
}

func main() {
	resp := getResponse("https://example.com")
	resp.Body.Close()
}

And the result of go vet:

go vet -vettool=$(which bodyclose) ./main.go
# command-line-arguments
./closer.go:8:20: response body must be closed
./closer.go:13:21: response body must be closed

This also occurs when using a RequestRecorder and calling .Result() on them.

Also occurs if you ever have a function that harmlessly passes through an HTTP response,
like this:

func addHeader(resp *http.Response) *http.Response {
    resp.Header.Set("foo", "bar")
    return resp
}

(clearly you don't even need to return the pointer, really, but that's beside the point, this is an actual example I've seen in the wild)

This also occurs when returning a function that takes response as an argument, as in the following.

func modifyResponse() func(*http.Response) error {
	return func(resp *http.Response) error {
		return nil
	}
}
response body must be closed (bodyclose)
proxy.go:38:40:   proxy.ModifyResponse = modifyResponse()