Repository: zeromicro/go-zero
Pull request #2520 (2022-10-16 01:56:41)

chore: fix lint errors


Patch:
diff --git a/.gitignore b/.gitignore
index e756a6be..77ba06dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,6 +22,7 @@ go.work.sum
 
 # gitlab ci
 .cache
+.golangci.yml
 
 # vim auto backup file
 *~
diff --git a/.golangci.yml b/.golangci.yml
deleted file mode 100644
index 011c8610..00000000
--- a/.golangci.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-linters-settings:
-  errcheck:
-    check-type-assertions: true
-  goconst:
-    min-len: 2
-    min-occurrences: 3
-  gocritic:
-    enabled-tags:
-      - diagnostic
-      - experimental
-      - opinionated
-      - performance
-      - style
-  govet:
-    check-shadowing: true
-    enable:
-      - fieldalignment
-  nolintlint:
-    require-explanation: true
-    require-specific: true
-  staticcheck:
-    checks:
-      - all
-      - '-SA5008'
-
-linters:
-  disable-all: true
-  enable:
-    - bodyclose
-    - depguard
-    - dogsled
-    - dupl
-    - errcheck
-    - exportloopref
-    - exhaustive
-    - goconst
-    - gocritic
-    - gofmt
-    - goimports
-    - gomnd
-    - gocyclo
-    - gosec
-    - gosimple
-    - govet
-    - ineffassign
-    - misspell
-    - nolintlint
-    - nakedret
-    - prealloc
-    - predeclared
-    - revive
-    - staticcheck
-    - stylecheck
-    - thelper
-    - tparallel
-    - typecheck
-    - unconvert
-    - unparam
-    - unused
-    - whitespace
-    - wsl
-
-run:
-  issues-exit-code: 1
diff --git a/gateway/internal/requestparser.go b/gateway/internal/requestparser.go
index 344931d7..3f27dec0 100644
--- a/gateway/internal/requestparser.go
+++ b/gateway/internal/requestparser.go
@@ -3,6 +3,7 @@ package internal
 import (
 	"bytes"
 	"encoding/json"
+	"io"
 	"net/http"
 
 	"github.com/fullstorydev/grpcurl"
@@ -22,16 +23,18 @@ func NewRequestParser(r *http.Request, resolver jsonpb.AnyResolver) (grpcurl.Req
 	for k, v := range vars {
 		params[k] = v
 	}
-	if len(params) == 0 {
-		return grpcurl.NewJSONRequestParser(r.Body, resolver), nil
-	}
 
-	if r.ContentLength == 0 {
+	body, ok := getBody(r)
+	if !ok {
 		return buildJsonRequestParser(params, resolver)
 	}
 
+	if len(params) == 0 {
+		return grpcurl.NewJSONRequestParser(body, resolver), nil
+	}
+
 	m := make(map[string]interface{})
-	if err := json.NewDecoder(r.Body).Decode(&m); err != nil {
+	if err := json.NewDecoder(body).Decode(&m); err != nil {
 		return nil, err
 	}
 
@@ -51,3 +54,28 @@ func buildJsonRequestParser(m map[string]interface{}, resolver jsonpb.AnyResolve
 
 	return grpcurl.NewJSONRequestParser(&buf, resolver), nil
 }
+
+func getBody(r *http.Request) (io.Reader, bool) {
+	if r.Body == nil {
+		return nil, false
+	}
+
+	if r.ContentLength == 0 {
+		return nil, false
+	}
+
+	if r.ContentLength > 0 {
+		return r.Body, true
+	}
+
+	var buf bytes.Buffer
+	if _, err := io.Copy(&buf, r.Body); err != nil {
+		return nil, false
+	}
+
+	if buf.Len() > 0 {
+		return &buf, true
+	}
+
+	return nil, false
+}
diff --git a/zrpc/resolver/internal/directbuilder.go b/zrpc/resolver/internal/directbuilder.go
index 81840df2..bbe70d4b 100644
--- a/zrpc/resolver/internal/directbuilder.go
+++ b/zrpc/resolver/internal/directbuilder.go
@@ -11,12 +11,13 @@ type directBuilder struct{}
 
 func (d *directBuilder) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (
 	resolver.Resolver, error) {
-	var addrs []resolver.Address
 	endpoints := strings.FieldsFunc(targets.GetEndpoints(target), func(r rune) bool {
 		return r == EndpointSepChar
 	})
+	endpoints = subset(endpoints, subsetSize)
+	addrs := make([]resolver.Address, 0, len(endpoints))
 
-	for _, val := range subset(endpoints, subsetSize) {
+	for _, val := range endpoints {
 		addrs = append(addrs, resolver.Address{
 			Addr: val,
 		})
diff --git a/zrpc/resolver/internal/kube/eventhandler.go b/zrpc/resolver/internal/kube/eventhandler.go
index d3b218a0..e247ce0b 100644
--- a/zrpc/resolver/internal/kube/eventhandler.go
+++ b/zrpc/resolver/internal/kube/eventhandler.go
@@ -115,7 +115,7 @@ func (h *EventHandler) Update(endpoints *v1.Endpoints) {
 }
 
 func (h *EventHandler) notify() {
-	var targets []string
+	targets := make([]string, 0, len(h.endpoints))
 
 	for k := range h.endpoints {
 		targets = append(targets, k)


Test patch:
diff --git a/gateway/internal/headerprocessor_test.go b/gateway/internal/headerprocessor_test.go
index c22f59f6..cba6a2c2 100644
--- a/gateway/internal/headerprocessor_test.go
+++ b/gateway/internal/headerprocessor_test.go
@@ -1,6 +1,7 @@
 package internal
 
 import (
+	"net/http"
 	"net/http/httptest"
 	"testing"
 
@@ -8,13 +9,13 @@ import (
 )
 
 func TestBuildHeadersNoValue(t *testing.T) {
-	req := httptest.NewRequest("GET", "/", nil)
+	req := httptest.NewRequest("GET", "/", http.NoBody)
 	req.Header.Add("a", "b")
 	assert.Nil(t, ProcessHeaders(req.Header))
 }
 
 func TestBuildHeadersWithValues(t *testing.T) {
-	req := httptest.NewRequest("GET", "/", nil)
+	req := httptest.NewRequest("GET", "/", http.NoBody)
 	req.Header.Add("grpc-metadata-a", "b")
 	req.Header.Add("grpc-metadata-b", "b")
 	assert.ElementsMatch(t, []string{"gateway-A:b", "gateway-B:b"}, ProcessHeaders(req.Header))
diff --git a/gateway/internal/requestparser_test.go b/gateway/internal/requestparser_test.go
index c910d02a..4a02aac5 100644
--- a/gateway/internal/requestparser_test.go
+++ b/gateway/internal/requestparser_test.go
@@ -1,6 +1,7 @@
 package internal
 
 import (
+	"net/http"
 	"net/http/httptest"
 	"strings"
 	"testing"
@@ -10,14 +11,14 @@ import (
 )
 
 func TestNewRequestParserNoVar(t *testing.T) {
-	req := httptest.NewRequest("GET", "/", nil)
+	req := httptest.NewRequest("GET", "/", http.NoBody)
 	parser, err := NewRequestParser(req, nil)
 	assert.Nil(t, err)
 	assert.NotNil(t, parser)
 }
 
 func TestNewRequestParserWithVars(t *testing.T) {
-	req := httptest.NewRequest("GET", "/", nil)
+	req := httptest.NewRequest("GET", "/", http.NoBody)
 	req = pathvar.WithVars(req, map[string]string{"a": "b"})
 	parser, err := NewRequestParser(req, nil)
 	assert.Nil(t, err)
@@ -48,14 +49,14 @@ func TestNewRequestParserWithVarsWithWrongBody(t *testing.T) {
 }
 
 func TestNewRequestParserWithForm(t *testing.T) {
-	req := httptest.NewRequest("GET", "/val?a=b", nil)
+	req := httptest.NewRequest("GET", "/val?a=b", http.NoBody)
 	parser, err := NewRequestParser(req, nil)
 	assert.Nil(t, err)
 	assert.NotNil(t, parser)
 }
 
 func TestNewRequestParserWithBadForm(t *testing.T) {
-	req := httptest.NewRequest("GET", "/val?a%1=b", nil)
+	req := httptest.NewRequest("GET", "/val?a%1=b", http.NoBody)
 	parser, err := NewRequestParser(req, nil)
 	assert.NotNil(t, err)
 	assert.Nil(t, parser)
diff --git a/gateway/internal/timeout_test.go b/gateway/internal/timeout_test.go
index bf681e9d..ff59052d 100644
--- a/gateway/internal/timeout_test.go
+++ b/gateway/internal/timeout_test.go
@@ -1,6 +1,7 @@
 package internal
 
 import (
+	"net/http"
 	"net/http/httptest"
 	"testing"
 	"time"
@@ -9,14 +10,14 @@ import (
 )
 
 func TestGetTimeout(t *testing.T) {
-	req := httptest.NewRequest("GET", "/", nil)
+	req := httptest.NewRequest("GET", "/", http.NoBody)
 	req.Header.Set(grpcTimeoutHeader, "1s")
 	timeout := GetTimeout(req.Header, time.Second*5)
 	assert.Equal(t, time.Second, timeout)
 }
 
 func TestGetTimeoutDefault(t *testing.T) {
-	req := httptest.NewRequest("GET", "/", nil)
+	req := httptest.NewRequest("GET", "/", http.NoBody)
 	timeout := GetTimeout(req.Header, time.Second*5)
 	assert.Equal(t, time.Second*5, timeout)
 }
diff --git a/rest/engine_test.go b/rest/engine_test.go
index 2aeef9a9..ef7ab474 100644
--- a/rest/engine_test.go
+++ b/rest/engine_test.go
@@ -237,7 +237,7 @@ func TestEngine_notFoundHandler(t *testing.T) {
 	defer ts.Close()
 
 	client := ts.Client()
-	err := func(ctx context.Context) error {
+	err := func(_ context.Context) error {
 		req, err := http.NewRequest("GET", ts.URL+"/bad", http.NoBody)
 		assert.Nil(t, err)
 		res, err := client.Do(req)
@@ -260,7 +260,7 @@ func TestEngine_notFoundHandlerNotNil(t *testing.T) {
 	defer ts.Close()
 
 	client := ts.Client()
-	err := func(ctx context.Context) error {
+	err := func(_ context.Context) error {
 		req, err := http.NewRequest("GET", ts.URL+"/bad", http.NoBody)
 		assert.Nil(t, err)
 		res, err := client.Do(req)
diff --git a/rest/handler/authhandler_test.go b/rest/handler/authhandler_test.go
index e9496e10..ad56557c 100644
--- a/rest/handler/authhandler_test.go
+++ b/rest/handler/authhandler_test.go
@@ -13,7 +13,7 @@ import (
 )
 
 func TestAuthHandlerFailed(t *testing.T) {
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	handler := Authorize("B63F477D-BBA3-4E52-96D3-C0034C27694A", WithUnauthorizedCallback(
 		func(w http.ResponseWriter, r *http.Request, err error) {
 			assert.NotNil(t, err)
@@ -33,7 +33,7 @@ func TestAuthHandlerFailed(t *testing.T) {
 
 func TestAuthHandler(t *testing.T) {
 	const key = "B63F477D-BBA3-4E52-96D3-C0034C27694A"
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	token, err := buildToken(key, map[string]interface{}{
 		"key": "value",
 	}, 3600)
@@ -62,7 +62,7 @@ func TestAuthHandlerWithPrevSecret(t *testing.T) {
 		key     = "14F17379-EB8F-411B-8F12-6929002DCA76"
 		prevKey = "B63F477D-BBA3-4E52-96D3-C0034C27694A"
 	)
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	token, err := buildToken(key, map[string]interface{}{
 		"key": "value",
 	}, 3600)
@@ -83,7 +83,7 @@ func TestAuthHandlerWithPrevSecret(t *testing.T) {
 }
 
 func TestAuthHandler_NilError(t *testing.T) {
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	assert.NotPanics(t, func() {
 		unauthorized(resp, req, nil, nil)
diff --git a/rest/handler/breakerhandler_test.go b/rest/handler/breakerhandler_test.go
index baf54d50..bda8fef1 100644
--- a/rest/handler/breakerhandler_test.go
+++ b/rest/handler/breakerhandler_test.go
@@ -25,7 +25,7 @@ func TestBreakerHandlerAccept(t *testing.T) {
 		assert.Nil(t, err)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	req.Header.Set("X-Test", "test")
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
@@ -41,7 +41,7 @@ func TestBreakerHandlerFail(t *testing.T) {
 		w.WriteHeader(http.StatusBadGateway)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusBadGateway, resp.Code)
@@ -55,7 +55,7 @@ func TestBreakerHandler_4XX(t *testing.T) {
 	}))
 
 	for i := 0; i < 1000; i++ {
-		req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+		req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 		resp := httptest.NewRecorder()
 		handler.ServeHTTP(resp, req)
 	}
@@ -63,7 +63,7 @@ func TestBreakerHandler_4XX(t *testing.T) {
 	const tries = 100
 	var pass int
 	for i := 0; i < tries; i++ {
-		req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+		req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 		resp := httptest.NewRecorder()
 		handler.ServeHTTP(resp, req)
 		if resp.Code == http.StatusBadRequest {
@@ -82,14 +82,14 @@ func TestBreakerHandlerReject(t *testing.T) {
 	}))
 
 	for i := 0; i < 1000; i++ {
-		req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+		req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 		resp := httptest.NewRecorder()
 		handler.ServeHTTP(resp, req)
 	}
 
 	var drops int
 	for i := 0; i < 100; i++ {
-		req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+		req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 		resp := httptest.NewRecorder()
 		handler.ServeHTTP(resp, req)
 		if resp.Code == http.StatusServiceUnavailable {
diff --git a/rest/handler/cryptionhandler_test.go b/rest/handler/cryptionhandler_test.go
index aa698292..d3fcfe09 100644
--- a/rest/handler/cryptionhandler_test.go
+++ b/rest/handler/cryptionhandler_test.go
@@ -26,7 +26,7 @@ func init() {
 }
 
 func TestCryptionHandlerGet(t *testing.T) {
-	req := httptest.NewRequest(http.MethodGet, "/any", nil)
+	req := httptest.NewRequest(http.MethodGet, "/any", http.NoBody)
 	handler := CryptionHandler(aesKey)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		_, err := w.Write([]byte(respText))
 		w.Header().Set("X-Test", "test")
@@ -80,7 +80,7 @@ func TestCryptionHandlerPostBadEncryption(t *testing.T) {
 }
 
 func TestCryptionHandlerWriteHeader(t *testing.T) {
-	req := httptest.NewRequest(http.MethodGet, "/any", nil)
+	req := httptest.NewRequest(http.MethodGet, "/any", http.NoBody)
 	handler := CryptionHandler(aesKey)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(http.StatusServiceUnavailable)
 	}))
@@ -90,7 +90,7 @@ func TestCryptionHandlerWriteHeader(t *testing.T) {
 }
 
 func TestCryptionHandlerFlush(t *testing.T) {
-	req := httptest.NewRequest(http.MethodGet, "/any", nil)
+	req := httptest.NewRequest(http.MethodGet, "/any", http.NoBody)
 	handler := CryptionHandler(aesKey)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.Write([]byte(respText))
 		flusher, ok := w.(http.Flusher)
diff --git a/rest/handler/loghandler_test.go b/rest/handler/loghandler_test.go
index 5de9adcf..a84b43d0 100644
--- a/rest/handler/loghandler_test.go
+++ b/rest/handler/loghandler_test.go
@@ -24,7 +24,7 @@ func TestLogHandler(t *testing.T) {
 	}
 
 	for _, logHandler := range handlers {
-		req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+		req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 		handler := logHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 			r.Context().Value(internal.LogContext).(*internal.LogCollector).Append("anything")
 			w.Header().Set("X-Test", "test")
@@ -79,7 +79,7 @@ func TestLogHandlerSlow(t *testing.T) {
 	}
 
 	for _, logHandler := range handlers {
-		req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+		req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 		handler := logHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 			time.Sleep(defaultSlowThreshold + time.Millisecond*50)
 		}))
@@ -159,7 +159,7 @@ func TestWrapStatusCodeWithColor(t *testing.T) {
 func BenchmarkLogHandler(b *testing.B) {
 	b.ReportAllocs()
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	handler := LogHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(http.StatusOK)
 	}))
diff --git a/rest/handler/maxconnshandler_test.go b/rest/handler/maxconnshandler_test.go
index 1286f720..7f857c0c 100644
--- a/rest/handler/maxconnshandler_test.go
+++ b/rest/handler/maxconnshandler_test.go
@@ -32,13 +32,13 @@ func TestMaxConnsHandler(t *testing.T) {
 
 	for i := 0; i < conns; i++ {
 		go func() {
-			req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+			req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 			handler.ServeHTTP(httptest.NewRecorder(), req)
 		}()
 	}
 
 	waitGroup.Wait()
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusServiceUnavailable, resp.Code)
@@ -65,14 +65,14 @@ func TestWithoutMaxConnsHandler(t *testing.T) {
 
 	for i := 0; i < conns; i++ {
 		go func() {
-			req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+			req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 			req.Header.Set(key, value)
 			handler.ServeHTTP(httptest.NewRecorder(), req)
 		}()
 	}
 
 	waitGroup.Wait()
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusOK, resp.Code)
diff --git a/rest/handler/metrichandler_test.go b/rest/handler/metrichandler_test.go
index 6eb3bf58..1382cb7a 100644
--- a/rest/handler/metrichandler_test.go
+++ b/rest/handler/metrichandler_test.go
@@ -16,7 +16,7 @@ func TestMetricHandler(t *testing.T) {
 		w.WriteHeader(http.StatusOK)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusOK, resp.Code)
diff --git a/rest/handler/prometheushandler_test.go b/rest/handler/prometheushandler_test.go
index abb802e6..ce7551e8 100644
--- a/rest/handler/prometheushandler_test.go
+++ b/rest/handler/prometheushandler_test.go
@@ -15,7 +15,7 @@ func TestPromMetricHandler_Disabled(t *testing.T) {
 		w.WriteHeader(http.StatusOK)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusOK, resp.Code)
@@ -31,7 +31,7 @@ func TestPromMetricHandler_Enabled(t *testing.T) {
 		w.WriteHeader(http.StatusOK)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusOK, resp.Code)
diff --git a/rest/handler/recoverhandler_test.go b/rest/handler/recoverhandler_test.go
index 538ac6f2..51189b5a 100644
--- a/rest/handler/recoverhandler_test.go
+++ b/rest/handler/recoverhandler_test.go
@@ -19,7 +19,7 @@ func TestWithPanic(t *testing.T) {
 		panic("whatever")
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusInternalServerError, resp.Code)
@@ -29,7 +29,7 @@ func TestWithoutPanic(t *testing.T) {
 	handler := RecoverHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusOK, resp.Code)
diff --git a/rest/handler/sheddinghandler_test.go b/rest/handler/sheddinghandler_test.go
index 6fa513b2..f3dbd209 100644
--- a/rest/handler/sheddinghandler_test.go
+++ b/rest/handler/sheddinghandler_test.go
@@ -28,7 +28,7 @@ func TestSheddingHandlerAccept(t *testing.T) {
 		assert.Nil(t, err)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	req.Header.Set("X-Test", "test")
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
@@ -47,7 +47,7 @@ func TestSheddingHandlerFail(t *testing.T) {
 		w.WriteHeader(http.StatusServiceUnavailable)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusServiceUnavailable, resp.Code)
@@ -63,7 +63,7 @@ func TestSheddingHandlerReject(t *testing.T) {
 		w.WriteHeader(http.StatusOK)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusServiceUnavailable, resp.Code)
@@ -76,7 +76,7 @@ func TestSheddingHandlerNoShedding(t *testing.T) {
 		w.WriteHeader(http.StatusOK)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusOK, resp.Code)
diff --git a/rest/handler/timeouthandler_test.go b/rest/handler/timeouthandler_test.go
index 531785ce..73e75cce 100644
--- a/rest/handler/timeouthandler_test.go
+++ b/rest/handler/timeouthandler_test.go
@@ -22,7 +22,7 @@ func TestTimeout(t *testing.T) {
 		time.Sleep(time.Minute)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusServiceUnavailable, resp.Code)
@@ -34,7 +34,7 @@ func TestWithinTimeout(t *testing.T) {
 		time.Sleep(time.Millisecond)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusOK, resp.Code)
@@ -48,7 +48,7 @@ func TestWithTimeoutTimedout(t *testing.T) {
 		w.WriteHeader(http.StatusOK)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusServiceUnavailable, resp.Code)
@@ -60,7 +60,7 @@ func TestWithoutTimeout(t *testing.T) {
 		time.Sleep(100 * time.Millisecond)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusOK, resp.Code)
@@ -72,7 +72,7 @@ func TestTimeoutPanic(t *testing.T) {
 		panic("foo")
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	assert.Panics(t, func() {
 		handler.ServeHTTP(resp, req)
@@ -85,7 +85,7 @@ func TestTimeoutWebsocket(t *testing.T) {
 		time.Sleep(time.Millisecond * 10)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	req.Header.Set(headerUpgrade, valueWebsocket)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
@@ -100,7 +100,7 @@ func TestTimeoutWroteHeaderTwice(t *testing.T) {
 		w.WriteHeader(http.StatusOK)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	handler.ServeHTTP(resp, req)
 	assert.Equal(t, http.StatusOK, resp.Code)
@@ -112,7 +112,7 @@ func TestTimeoutWriteBadCode(t *testing.T) {
 		w.WriteHeader(1000)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	resp := httptest.NewRecorder()
 	assert.Panics(t, func() {
 		handler.ServeHTTP(resp, req)
@@ -125,7 +125,7 @@ func TestTimeoutClientClosed(t *testing.T) {
 		w.WriteHeader(http.StatusServiceUnavailable)
 	}))
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	ctx, cancel := context.WithCancel(context.Background())
 	req = req.WithContext(ctx)
 	cancel()
diff --git a/rest/httpx/requests_test.go b/rest/httpx/requests_test.go
index e0d1ffee..70c35c1d 100644
--- a/rest/httpx/requests_test.go
+++ b/rest/httpx/requests_test.go
@@ -19,7 +19,7 @@ func TestParseForm(t *testing.T) {
 		Percent float64 `form:"percent,optional"`
 	}
 
-	r, err := http.NewRequest(http.MethodGet, "/a?name=hello&age=18&percent=3.4", nil)
+	r, err := http.NewRequest(http.MethodGet, "/a?name=hello&age=18&percent=3.4", http.NoBody)
 	assert.Nil(t, err)
 	assert.Nil(t, Parse(r, &v))
 	assert.Equal(t, "hello", v.Name)
@@ -33,7 +33,7 @@ func TestParseForm_Error(t *testing.T) {
 		Age  int    `form:"age"`
 	}
 
-	r := httptest.NewRequest(http.MethodGet, "/a?name=hello;", nil)
+	r := httptest.NewRequest(http.MethodGet, "/a?name=hello;", http.NoBody)
 	assert.NotNil(t, ParseForm(r, &v))
 }
 
@@ -82,7 +82,7 @@ func TestParsePath(t *testing.T) {
 		Age  int    `path:"age"`
 	}
 
-	r := httptest.NewRequest(http.MethodGet, "/", nil)
+	r := httptest.NewRequest(http.MethodGet, "/", http.NoBody)
 	r = pathvar.WithVars(r, map[string]string{
 		"name": "foo",
 		"age":  "18",
@@ -99,7 +99,7 @@ func TestParsePath_Error(t *testing.T) {
 		Age  int    `path:"age"`
 	}
 
-	r := httptest.NewRequest(http.MethodGet, "/", nil)
+	r := httptest.NewRequest(http.MethodGet, "/", http.NoBody)
 	r = pathvar.WithVars(r, map[string]string{
 		"name": "foo",
 	})
@@ -138,7 +138,7 @@ func TestParseFormOutOfRange(t *testing.T) {
 	}
 
 	for _, test := range tests {
-		r, err := http.NewRequest(http.MethodGet, test.url, nil)
+		r, err := http.NewRequest(http.MethodGet, test.url, http.NoBody)
 		assert.Nil(t, err)
 
 		err = Parse(r, &v)
@@ -218,7 +218,7 @@ func TestParseJsonBody(t *testing.T) {
 			Age  int    `json:"age,optional"`
 		}
 
-		r := httptest.NewRequest(http.MethodGet, "/", nil)
+		r := httptest.NewRequest(http.MethodGet, "/", http.NoBody)
 		assert.Nil(t, Parse(r, &v))
 		assert.Equal(t, "", v.Name)
 		assert.Equal(t, 0, v.Age)
@@ -231,7 +231,7 @@ func TestParseRequired(t *testing.T) {
 		Percent float64 `form:"percent"`
 	}{}
 
-	r, err := http.NewRequest(http.MethodGet, "/a?name=hello", nil)
+	r, err := http.NewRequest(http.MethodGet, "/a?name=hello", http.NoBody)
 	assert.Nil(t, err)
 	assert.NotNil(t, Parse(r, &v))
 }
@@ -241,7 +241,7 @@ func TestParseOptions(t *testing.T) {
 		Position int8 `form:"pos,options=1|2"`
 	}{}
 
-	r, err := http.NewRequest(http.MethodGet, "/a?pos=4", nil)
+	r, err := http.NewRequest(http.MethodGet, "/a?pos=4", http.NoBody)
 	assert.Nil(t, err)
 	assert.NotNil(t, Parse(r, &v))
 }
@@ -258,7 +258,7 @@ func TestParseHeaders(t *testing.T) {
 		XForwardedFor string   `header:"X-Forwarded-For,optional"`
 		AnonymousStruct
 	}{}
-	request, err := http.NewRequest("POST", "/", nil)
+	request, err := http.NewRequest("POST", "/", http.NoBody)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -287,13 +287,13 @@ func TestParseHeaders_Error(t *testing.T) {
 		Age  int    `header:"age"`
 	}{}
 
-	r := httptest.NewRequest("POST", "/", nil)
+	r := httptest.NewRequest("POST", "/", http.NoBody)
 	r.Header.Set("name", "foo")
 	assert.NotNil(t, Parse(r, &v))
 }
 
 func BenchmarkParseRaw(b *testing.B) {
-	r, err := http.NewRequest(http.MethodGet, "http://hello.com/a?name=hello&age=18&percent=3.4", nil)
+	r, err := http.NewRequest(http.MethodGet, "http://hello.com/a?name=hello&age=18&percent=3.4", http.NoBody)
 	if err != nil {
 		b.Fatal(err)
 	}
@@ -318,7 +318,7 @@ func BenchmarkParseRaw(b *testing.B) {
 }
 
 func BenchmarkParseAuto(b *testing.B) {
-	r, err := http.NewRequest(http.MethodGet, "http://hello.com/a?name=hello&age=18&percent=3.4", nil)
+	r, err := http.NewRequest(http.MethodGet, "http://hello.com/a?name=hello&age=18&percent=3.4", http.NoBody)
 	if err != nil {
 		b.Fatal(err)
 	}
diff --git a/rest/internal/cors/handlers_test.go b/rest/internal/cors/handlers_test.go
index 4a398ba5..2082228a 100644
--- a/rest/internal/cors/handlers_test.go
+++ b/rest/internal/cors/handlers_test.go
@@ -65,7 +65,7 @@ func TestCorsHandlerWithOrigins(t *testing.T) {
 		for _, method := range methods {
 			test := test
 			t.Run(test.name+"-handler", func(t *testing.T) {
-				r := httptest.NewRequest(method, "http://localhost", nil)
+				r := httptest.NewRequest(method, "http://localhost", http.NoBody)
 				r.Header.Set(originHeader, test.reqOrigin)
 				w := httptest.NewRecorder()
 				handler := NotAllowedHandler(nil, test.origins...)
@@ -78,7 +78,7 @@ func TestCorsHandlerWithOrigins(t *testing.T) {
 				assert.Equal(t, test.expect, w.Header().Get(allowOrigin))
 			})
 			t.Run(test.name+"-handler-custom", func(t *testing.T) {
-				r := httptest.NewRequest(method, "http://localhost", nil)
+				r := httptest.NewRequest(method, "http://localhost", http.NoBody)
 				r.Header.Set(originHeader, test.reqOrigin)
 				w := httptest.NewRecorder()
 				handler := NotAllowedHandler(func(w http.ResponseWriter) {
@@ -100,7 +100,7 @@ func TestCorsHandlerWithOrigins(t *testing.T) {
 		for _, method := range methods {
 			test := test
 			t.Run(test.name+"-middleware", func(t *testing.T) {
-				r := httptest.NewRequest(method, "http://localhost", nil)
+				r := httptest.NewRequest(method, "http://localhost", http.NoBody)
 				r.Header.Set(originHeader, test.reqOrigin)
 				w := httptest.NewRecorder()
 				handler := Middleware(nil, test.origins...)(func(w http.ResponseWriter, r *http.Request) {
@@ -115,7 +115,7 @@ func TestCorsHandlerWithOrigins(t *testing.T) {
 				assert.Equal(t, test.expect, w.Header().Get(allowOrigin))
 			})
 			t.Run(test.name+"-middleware-custom", func(t *testing.T) {
-				r := httptest.NewRequest(method, "http://localhost", nil)
+				r := httptest.NewRequest(method, "http://localhost", http.NoBody)
 				r.Header.Set(originHeader, test.reqOrigin)
 				w := httptest.NewRecorder()
 				handler := Middleware(func(header http.Header) {
diff --git a/rest/internal/encoding/parser_test.go b/rest/internal/encoding/parser_test.go
index 2708098c..ef92dcd5 100644
--- a/rest/internal/encoding/parser_test.go
+++ b/rest/internal/encoding/parser_test.go
@@ -14,7 +14,7 @@ func TestParseHeaders(t *testing.T) {
 		Baz int    `header:"baz"`
 		Qux bool   `header:"qux,default=true"`
 	}
-	r := httptest.NewRequest(http.MethodGet, "/any", nil)
+	r := httptest.NewRequest(http.MethodGet, "/any", http.NoBody)
 	r.Header.Set("foo", "bar")
 	r.Header.Set("baz", "1")
 	assert.Nil(t, ParseHeaders(r.Header, &val))
@@ -29,7 +29,7 @@ func TestParseHeadersMulti(t *testing.T) {
 		Baz int      `header:"baz"`
 		Qux bool     `header:"qux,default=true"`
 	}
-	r := httptest.NewRequest(http.MethodGet, "/any", nil)
+	r := httptest.NewRequest(http.MethodGet, "/any", http.NoBody)
 	r.Header.Set("foo", "bar")
 	r.Header.Add("foo", "bar1")
 	r.Header.Set("baz", "1")
@@ -43,7 +43,7 @@ func TestParseHeadersArrayInt(t *testing.T) {
 	var val struct {
 		Foo []int `header:"foo"`
 	}
-	r := httptest.NewRequest(http.MethodGet, "/any", nil)
+	r := httptest.NewRequest(http.MethodGet, "/any", http.NoBody)
 	r.Header.Set("foo", "1")
 	r.Header.Add("foo", "2")
 	assert.Nil(t, ParseHeaders(r.Header, &val))
diff --git a/rest/internal/log_test.go b/rest/internal/log_test.go
index 9344dc51..f4bcc799 100644
--- a/rest/internal/log_test.go
+++ b/rest/internal/log_test.go
@@ -13,7 +13,7 @@ import (
 
 func TestInfo(t *testing.T) {
 	collector := new(LogCollector)
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	req = req.WithContext(context.WithValue(req.Context(), LogContext, collector))
 	Info(req, "first")
 	Infof(req, "second %s", "third")
@@ -35,7 +35,7 @@ func TestError(t *testing.T) {
 		logx.SetWriter(o)
 	}()
 
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	Error(req, "first")
 	Errorf(req, "second %s", "third")
 	val := buf.String()
diff --git a/rest/internal/response/headeronceresponsewriter_test.go b/rest/internal/response/headeronceresponsewriter_test.go
index cbc8fe1d..7e5b1166 100644
--- a/rest/internal/response/headeronceresponsewriter_test.go
+++ b/rest/internal/response/headeronceresponsewriter_test.go
@@ -11,7 +11,7 @@ import (
 )
 
 func TestHeaderOnceResponseWriter_Flush(t *testing.T) {
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		cw := NewHeaderOnceResponseWriter(w)
 		cw.Header().Set("X-Test", "test")
diff --git a/rest/internal/response/withcoderesponsewriter_test.go b/rest/internal/response/withcoderesponsewriter_test.go
index a4fcfae6..c03e84c5 100644
--- a/rest/internal/response/withcoderesponsewriter_test.go
+++ b/rest/internal/response/withcoderesponsewriter_test.go
@@ -9,7 +9,7 @@ import (
 )
 
 func TestWithCodeResponseWriter(t *testing.T) {
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		cw := &WithCodeResponseWriter{Writer: w}
 
diff --git a/rest/server_test.go b/rest/server_test.go
index 26912e2c..ad205552 100644
--- a/rest/server_test.go
+++ b/rest/server_test.go
@@ -255,7 +255,7 @@ func TestWithPrefix(t *testing.T) {
 		},
 	}
 	WithPrefix("/api")(&fr)
-	var vals []string
+	vals := make([]string, 0, len(fr.routes))
 	for _, r := range fr.routes {
 		vals = append(vals, r.Path)
 	}
@@ -510,7 +510,7 @@ func TestServer_WithChain(t *testing.T) {
 	)
 	rt := router.NewRouter()
 	assert.Nil(t, server.ngin.bindRoutes(rt))
-	req, err := http.NewRequest(http.MethodGet, "/", nil)
+	req, err := http.NewRequest(http.MethodGet, "/", http.NoBody)
 	assert.Nil(t, err)
 	rt.ServeHTTP(httptest.NewRecorder(), req)
 	assert.Equal(t, int32(5), atomic.LoadInt32(&called))
@@ -531,7 +531,7 @@ func TestServer_WithCors(t *testing.T) {
 		Router:     r,
 		middleware: cors.Middleware(nil, "*"),
 	}
-	req := httptest.NewRequest(http.MethodOptions, "/", nil)
+	req := httptest.NewRequest(http.MethodOptions, "/", http.NoBody)
 	cr.ServeHTTP(httptest.NewRecorder(), req)
 	assert.Equal(t, int32(0), atomic.LoadInt32(&called))
 }
diff --git a/rest/token/tokenparser_test.go b/rest/token/tokenparser_test.go
index 5d299121..00d0ee61 100644
--- a/rest/token/tokenparser_test.go
+++ b/rest/token/tokenparser_test.go
@@ -31,7 +31,7 @@ func TestTokenParser(t *testing.T) {
 	}
 
 	for _, pair := range keys {
-		req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+		req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 		token, err := buildToken(key, map[string]interface{}{
 			"key": "value",
 		}, 3600)
@@ -50,7 +50,7 @@ func TestTokenParser_Expired(t *testing.T) {
 		key     = "14F17379-EB8F-411B-8F12-6929002DCA76"
 		prevKey = "B63F477D-BBA3-4E52-96D3-C0034C27694A"
 	)
-	req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
+	req := httptest.NewRequest(http.MethodGet, "http://localhost", http.NoBody)
 	token, err := buildToken(key, map[string]interface{}{
 		"key": "value",
 	}, 3600)