logginghandler/vendor/github.com/sonatard/noctx
Marvin Preuss d095180eb4
All checks were successful
continuous-integration/drone/push Build is passing
build: uses go modules for tool handling
2022-01-14 13:51:56 +01:00
..
ngfunc build: uses go modules for tool handling 2022-01-14 13:51:56 +01:00
reqwithoutctx build: uses go modules for tool handling 2022-01-14 13:51:56 +01:00
.gitignore build: uses go modules for tool handling 2022-01-14 13:51:56 +01:00
.golangci.yml build: uses go modules for tool handling 2022-01-14 13:51:56 +01:00
go.mod build: uses go modules for tool handling 2022-01-14 13:51:56 +01:00
go.sum build: uses go modules for tool handling 2022-01-14 13:51:56 +01:00
LICENSE build: uses go modules for tool handling 2022-01-14 13:51:56 +01:00
Makefile build: uses go modules for tool handling 2022-01-14 13:51:56 +01:00
noctx.go build: uses go modules for tool handling 2022-01-14 13:51:56 +01:00
README.md build: uses go modules for tool handling 2022-01-14 13:51:56 +01:00

noctx

noctx finds sending http request without context.Context.

You should use noctx if sending http request in your library. Passing context.Context enables library user to cancel http request, getting trace information and so on.

Install

$ go get -u github.com/sonatard/noctx/cmd/noctx

Usage

$ go vet -vettool=`which noctx` main.go
./main.go:6:11: net/http.Get must not be called

Detection rules

  • Executing following functions
    • net/http.Get
    • net/http.Head
    • net/http.Post
    • net/http.PostForm
    • (*net/http.Client).Get
    • (*net/http.Client).Head
    • (*net/http.Client).Post
    • (*net/http.Client).PostForm
  • http.Request returned by http.NewRequest function and passes it to other function.

How to fix

  • Send http request using (*http.Client).Do(*http.Request) method.
  • In Go 1.13 and later, use http.NewRequestWithContext function instead of using http.NewRequest function.
  • In Go 1.12 and earlier, call (http.Request).WithContext(ctx) after http.NewRequest.

(http.Request).WithContext(ctx) has a disadvantage of performance because it returns a copy of http.Request. Use http.NewRequestWithContext function if you only support Go1.13 or later.

Sample Code

package main

import (
	"context"
	"net/http"
)

func main() {
	const url = "http://example.com"
	http.Get(url) // want `net/http\.Get must not be called`
	http.Head(url)          // want `net/http\.Head must not be called`
	http.Post(url, "", nil) // want `net/http\.Post must not be called`
	http.PostForm(url, nil) // want `net/http\.PostForm must not be called`

	cli := &http.Client{}
	cli.Get(url) // want `\(\*net/http\.Client\)\.Get must not be called`
	cli.Head(url)          // want `\(\*net/http\.Client\)\.Head must not be called`
	cli.Post(url, "", nil) // want `\(\*net/http\.Client\)\.Post must not be called`
	cli.PostForm(url, nil) // want `\(\*net/http\.Client\)\.PostForm must not be called`

	req, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext`
	cli.Do(req)

	ctx := context.Background()
	req2, _ := http.NewRequestWithContext(ctx, http.MethodPost, url, nil) // OK
	cli.Do(req2)

	req3, _ := http.NewRequest(http.MethodPost, url, nil) // OK
	req3 = req3.WithContext(ctx)
	cli.Do(req3)

	f2 := func(req *http.Request, ctx context.Context) *http.Request {
		return req
	}
	req4, _ := http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext`
	req4 = f2(req4, ctx)
	cli.Do(req4)

	req5, _ := func() (*http.Request, error) {
		return http.NewRequest(http.MethodPost, url, nil) // want `should rewrite http.NewRequestWithContext or add \(\*Request\).WithContext`
	}()
	cli.Do(req5)

}

Reference