Repository: go-kratos/kratos
Pull request #2726 (2023-03-13 07:35:20)

fix(grpc/balancer): fix the problem that the watch log cannot be closed
<!--
🎉 Thanks for sending a pull request to Kratos! Here are some tips for you:

1. If this is your first time contributing to Kratos, please read our contribution guide: https://go-kratos.dev/en/docs/community/contribution/
2. Ensure you have added or ran the appropriate tests and lint for your PR, please use `make lint` and `make test` before filing your PR, use `make clean` to tidy your go mod.
3. If the PR is unfinished, you may need to mark it as a WIP(Work In Progress) PR or Draft PR
4. Please use a semantic commits format title, such as `<type>[optional scope]: <description>`, see: https://go-kratos.dev/docs/community/contribution#type
5. at the same time, please note that similar work should be submitted in one PR as far as possible to reduce the workload of reviewers. Do not split a work into multiple PR unless it should.
-->

<!--
🎉 感谢您向 Kratos 发送 PR！以下是一些提示：
如果这是你第一次为 Kratos 贡献，请阅读我们的贡献指南：https://go-kratos.dev/en/docs/community/contribution/
2、确保您已经为您的 PR 添加或运行了适当的测试和lint，请在提交PR之前使用“make lint”和“make test”，使用“make clean”整理您的 go.mod。
3、如果 PR 未完成，您可能需要将其标记为 WIP（Work In Progress）PR 或 Draft PR
4、请使用语义提交格式标题，如“<类型>[可选范围]：<说明>`，请参阅：https://go-kratos.dev/docs/community/contribution#type
5. 同时请注意，同类的工作请尽量在一个PR中提交，以减轻 review 者的工作负担，不要把一项工作拆分成很多个PR，除非它应该这样做。
-->


#### Description (what this PR does / why we need it):
<!--
* The description should include the motivation for this PR or contrast this with previous behavior
-->


#### Which issue(s) this PR fixes (resolves / be part of):
<!--
* Automatically closes linked issue when PR is merged.
* If your PR is not fully resolved the issue, please use `part of #<issue number>` instead.

Usage: `fixes/resolves #<issue number>`, or `fixes/resolves (paste link of issue)`.
-->


#### Other special notes for the reviewers:
<!--
* Somethings that need extra attention for the reviewers
* Some additional notes, TODO list, etc.
-->



Patch:
diff --git a/Makefile b/Makefile
index 77ee21a8..79e6cda2 100644
--- a/Makefile
+++ b/Makefile
@@ -89,7 +89,7 @@ test:
 .PHONY: test-coverage
 test-coverage:
 	@${TOOLS_SHELL} test_coverage
-	@echo "go test with coverage finished"	
+	@echo "go test with coverage finished"
 
 .PHONY: lint
 lint: $(LINTER)
diff --git a/SECURITY.md b/SECURITY.md
index d7fb3ffe..6e28dd41 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -5,10 +5,10 @@
 Use this section to tell people about which versions of your project are
 currently being supported with security updates.
 
-| Version | Supported          |
-| ------- | ------------------ |
-| 2.0.rc1   | :white_check_mark: |
-| < 2.0.beta3  | :x:                |
+| Version     | Supported          |
+|-------------|--------------------|
+| 2.0.rc1     | :white_check_mark: |
+| < 2.0.beta3 | :x:                |
 
 ## Reporting a Vulnerability
 
diff --git a/cmd/kratos/internal/proto/server/server.go b/cmd/kratos/internal/proto/server/server.go
index 3b8a8196..e9af0c71 100644
--- a/cmd/kratos/internal/proto/server/server.go
+++ b/cmd/kratos/internal/proto/server/server.go
@@ -17,7 +17,7 @@ import (
 var CmdServer = &cobra.Command{
 	Use:   "server",
 	Short: "Generate the proto Server implementations",
-	Long:  "Generate the proto Server implementations. Example: kratos proto server api/xxx.proto -target-dir=internal/service",
+	Long:  "Generate the proto Server implementations. Example: kratos proto server api/xxx.proto --target-dir=internal/service",
 	Run:   run,
 }
 var targetDir string
diff --git a/selector/node/ewma/node.go b/selector/node/ewma/node.go
index 3b8d2a02..c718f252 100644
--- a/selector/node/ewma/node.go
+++ b/selector/node/ewma/node.go
@@ -10,7 +10,6 @@ import (
 	"time"
 
 	"github.com/go-kratos/kratos/v2/errors"
-
 	"github.com/go-kratos/kratos/v2/selector"
 )
 
diff --git a/transport/grpc/client.go b/transport/grpc/client.go
index b2b5c0c2..9c8dfa68 100644
--- a/transport/grpc/client.go
+++ b/transport/grpc/client.go
@@ -109,19 +109,26 @@ func WithLogger(log log.Logger) ClientOption {
 	return func(o *clientOptions) {}
 }
 
+func WithPrintDiscoveryDebugLog(p bool) ClientOption {
+	return func(o *clientOptions) {
+		o.printDiscoveryDebugLog = p
+	}
+}
+
 // clientOptions is gRPC Client
 type clientOptions struct {
-	endpoint     string
-	subsetSize   int
-	tlsConf      *tls.Config
-	timeout      time.Duration
-	discovery    registry.Discovery
-	middleware   []middleware.Middleware
-	ints         []grpc.UnaryClientInterceptor
-	streamInts   []grpc.StreamClientInterceptor
-	grpcOpts     []grpc.DialOption
-	balancerName string
-	filters      []selector.NodeFilter
+	endpoint               string
+	subsetSize             int
+	tlsConf                *tls.Config
+	timeout                time.Duration
+	discovery              registry.Discovery
+	middleware             []middleware.Middleware
+	ints                   []grpc.UnaryClientInterceptor
+	streamInts             []grpc.StreamClientInterceptor
+	grpcOpts               []grpc.DialOption
+	balancerName           string
+	filters                []selector.NodeFilter
+	printDiscoveryDebugLog bool
 }
 
 // Dial returns a GRPC connection.
@@ -136,9 +143,10 @@ func DialInsecure(ctx context.Context, opts ...ClientOption) (*grpc.ClientConn,
 
 func dial(ctx context.Context, insecure bool, opts ...ClientOption) (*grpc.ClientConn, error) {
 	options := clientOptions{
-		timeout:      2000 * time.Millisecond,
-		balancerName: balancerName,
-		subsetSize:   25,
+		timeout:                2000 * time.Millisecond,
+		balancerName:           balancerName,
+		subsetSize:             25,
+		printDiscoveryDebugLog: true,
 	}
 	for _, o := range opts {
 		o(&options)
@@ -169,6 +177,7 @@ func dial(ctx context.Context, insecure bool, opts ...ClientOption) (*grpc.Clien
 					options.discovery,
 					discovery.WithInsecure(insecure),
 					discovery.WithSubset(options.subsetSize),
+					discovery.PrintDebugLog(options.printDiscoveryDebugLog),
 				)))
 	}
 	if insecure {
diff --git a/transport/grpc/resolver/discovery/builder.go b/transport/grpc/resolver/discovery/builder.go
index 6186cdf1..37a9b560 100644
--- a/transport/grpc/resolver/discovery/builder.go
+++ b/transport/grpc/resolver/discovery/builder.go
@@ -38,29 +38,37 @@ func WithSubset(size int) Option {
 	}
 }
 
+// Deprecated: please use PrintDebugLog
 // DisableDebugLog disables update instances log.
 func DisableDebugLog() Option {
 	return func(b *builder) {
-		b.debugLogDisabled = true
+		b.debugLog = false
+	}
+}
+
+// PrintDebugLog print grpc resolver watch service log
+func PrintDebugLog(p bool) Option {
+	return func(b *builder) {
+		b.debugLog = p
 	}
 }
 
 type builder struct {
-	discoverer       registry.Discovery
-	timeout          time.Duration
-	insecure         bool
-	subsetSize       int
-	debugLogDisabled bool
+	discoverer registry.Discovery
+	timeout    time.Duration
+	insecure   bool
+	subsetSize int
+	debugLog   bool
 }
 
 // NewBuilder creates a builder which is used to factory registry resolvers.
 func NewBuilder(d registry.Discovery, opts ...Option) resolver.Builder {
 	b := &builder{
-		discoverer:       d,
-		timeout:          time.Second * 10,
-		insecure:         false,
-		debugLogDisabled: false,
-		subsetSize:       25,
+		discoverer: d,
+		timeout:    time.Second * 10,
+		insecure:   false,
+		debugLog:   true,
+		subsetSize: 25,
 	}
 	for _, o := range opts {
 		o(b)
@@ -96,14 +104,14 @@ func (b *builder) Build(target resolver.Target, cc resolver.ClientConn, opts res
 	}
 
 	r := &discoveryResolver{
-		w:                watchRes.w,
-		cc:               cc,
-		ctx:              ctx,
-		cancel:           cancel,
-		insecure:         b.insecure,
-		debugLogDisabled: b.debugLogDisabled,
-		subsetSize:       b.subsetSize,
-		selecterKey:      uuid.New().String(),
+		w:           watchRes.w,
+		cc:          cc,
+		ctx:         ctx,
+		cancel:      cancel,
+		insecure:    b.insecure,
+		debugLog:    b.debugLog,
+		subsetSize:  b.subsetSize,
+		selecterKey: uuid.New().String(),
 	}
 	go r.watch()
 	return r, nil
diff --git a/transport/grpc/resolver/discovery/resolver.go b/transport/grpc/resolver/discovery/resolver.go
index a66a9b4e..a4bd05d5 100644
--- a/transport/grpc/resolver/discovery/resolver.go
+++ b/transport/grpc/resolver/discovery/resolver.go
@@ -22,10 +22,10 @@ type discoveryResolver struct {
 	ctx    context.Context
 	cancel context.CancelFunc
 
-	insecure         bool
-	debugLogDisabled bool
-	selecterKey      string
-	subsetSize       int
+	insecure    bool
+	debugLog    bool
+	selecterKey string
+	subsetSize  int
 }
 
 func (r *discoveryResolver) watch() {
@@ -90,7 +90,7 @@ func (r *discoveryResolver) update(ins []*registry.ServiceInstance) {
 		log.Errorf("[resolver] failed to update state: %s", err)
 	}
 
-	if !r.debugLogDisabled {
+	if r.debugLog {
 		b, _ := json.Marshal(filtered)
 		log.Infof("[resolver] update instances: %s", b)
 	}


Test patch:
diff --git a/transport/grpc/resolver/discovery/builder_test.go b/transport/grpc/resolver/discovery/builder_test.go
index 664b5d44..21d5585c 100644
--- a/transport/grpc/resolver/discovery/builder_test.go
+++ b/transport/grpc/resolver/discovery/builder_test.go
@@ -33,8 +33,8 @@ func TestWithTimeout(t *testing.T) {
 func TestDisableDebugLog(t *testing.T) {
 	o := &builder{}
 	DisableDebugLog()(o)
-	if !o.debugLogDisabled {
-		t.Errorf("expected debugLogDisabled true, got %v", o.debugLogDisabled)
+	if o.debugLog {
+		t.Errorf("expected debugLog true, got %v", o.debugLog)
 	}
 }
 
diff --git a/transport/http/client_test.go b/transport/http/client_test.go
index 9a0dd782..119c8c0b 100644
--- a/transport/http/client_test.go
+++ b/transport/http/client_test.go
@@ -10,13 +10,12 @@ import (
 	"io"
 	"log"
 	"net/http"
-	nethttp "net/http"
 	"reflect"
 	"strconv"
 	"testing"
 	"time"
 
-	kratosErrors "github.com/go-kratos/kratos/v2/errors"
+	kratoserrors "github.com/go-kratos/kratos/v2/errors"
 	"github.com/go-kratos/kratos/v2/middleware"
 	"github.com/go-kratos/kratos/v2/registry"
 	"github.com/go-kratos/kratos/v2/selector"
@@ -24,7 +23,7 @@ import (
 
 type mockRoundTripper struct{}
 
-func (rt *mockRoundTripper) RoundTrip(req *nethttp.Request) (resp *nethttp.Response, err error) {
+func (rt *mockRoundTripper) RoundTrip(req *http.Request) (resp *http.Response, err error) {
 	return
 }
 
@@ -129,7 +128,7 @@ func TestWithRequestEncoder(t *testing.T) {
 
 func TestWithResponseDecoder(t *testing.T) {
 	o := &clientOptions{}
-	v := func(ctx context.Context, res *nethttp.Response, out interface{}) error { return nil }
+	v := func(ctx context.Context, res *http.Response, out interface{}) error { return nil }
 	WithResponseDecoder(v)(o)
 	if o.decoder == nil {
 		t.Errorf("expected encoder to be not nil")
@@ -138,7 +137,7 @@ func TestWithResponseDecoder(t *testing.T) {
 
 func TestWithErrorDecoder(t *testing.T) {
 	o := &clientOptions{}
-	v := func(ctx context.Context, res *nethttp.Response) error { return nil }
+	v := func(ctx context.Context, res *http.Response) error { return nil }
 	WithErrorDecoder(v)(o)
 	if o.errorDecoder == nil {
 		t.Errorf("expected encoder to be not nil")
@@ -199,27 +198,24 @@ func TestWithNodeFilter(t *testing.T) {
 }
 
 func TestDefaultRequestEncoder(t *testing.T) {
-	req1 := &nethttp.Request{
-		Header: make(nethttp.Header),
-		Body:   io.NopCloser(bytes.NewBufferString("{\"a\":\"1\", \"b\": 2}")),
-	}
-	req1.Header.Set("Content-Type", "application/xml")
+	r, _ := http.NewRequest(http.MethodPost, "", io.NopCloser(bytes.NewBufferString(`{"a":"1", "b": 2}`)))
+	r.Header.Set("Content-Type", "application/xml")
 
 	v1 := &struct {
 		A string `json:"a"`
 		B int64  `json:"b"`
 	}{"a", 1}
-	b, err1 := DefaultRequestEncoder(context.TODO(), "application/json", v1)
-	if err1 != nil {
-		t.Errorf("expected no error, got %v", err1)
+	b, err := DefaultRequestEncoder(context.TODO(), "application/json", v1)
+	if err != nil {
+		t.Fatal(err)
 	}
 	v1b := &struct {
 		A string `json:"a"`
 		B int64  `json:"b"`
 	}{}
-	err1 = json.Unmarshal(b, v1b)
-	if err1 != nil {
-		t.Errorf("expected no error, got %v", err1)
+	err = json.Unmarshal(b, v1b)
+	if err != nil {
+		t.Fatal(err)
 	}
 	if !reflect.DeepEqual(v1b, v1) {
 		t.Errorf("expected %v, got %v", v1, v1b)
@@ -227,8 +223,8 @@ func TestDefaultRequestEncoder(t *testing.T) {
 }
 
 func TestDefaultResponseDecoder(t *testing.T) {
-	resp1 := &nethttp.Response{
-		Header:     make(nethttp.Header),
+	resp1 := &http.Response{
+		Header:     make(http.Header),
 		StatusCode: 200,
 		Body:       io.NopCloser(bytes.NewBufferString("{\"a\":\"1\", \"b\": 2}")),
 	}
@@ -236,19 +232,19 @@ func TestDefaultResponseDecoder(t *testing.T) {
 		A string `json:"a"`
 		B int64  `json:"b"`
 	}{}
-	err1 := DefaultResponseDecoder(context.TODO(), resp1, &v1)
-	if err1 != nil {
-		t.Errorf("expected no error, got %v", err1)
+	err := DefaultResponseDecoder(context.TODO(), resp1, &v1)
+	if err != nil {
+		t.Fatal(err)
 	}
-	if !reflect.DeepEqual("1", v1.A) {
+	if v1.A != "1" {
 		t.Errorf("expected %v, got %v", "1", v1.A)
 	}
-	if !reflect.DeepEqual(int64(2), v1.B) {
+	if v1.B != int64(2) {
 		t.Errorf("expected %v, got %v", 2, v1.B)
 	}
 
-	resp2 := &nethttp.Response{
-		Header:     make(nethttp.Header),
+	resp2 := &http.Response{
+		Header:     make(http.Header),
 		StatusCode: 200,
 		Body:       io.NopCloser(bytes.NewBufferString("{badjson}")),
 	}
@@ -256,22 +252,22 @@ func TestDefaultResponseDecoder(t *testing.T) {
 		A string `json:"a"`
 		B int64  `json:"b"`
 	}{}
-	err2 := DefaultResponseDecoder(context.TODO(), resp2, &v2)
-	terr1 := &json.SyntaxError{}
-	if !errors.As(err2, &terr1) {
-		t.Errorf("expected %v, got %v", terr1, err2)
+	err = DefaultResponseDecoder(context.TODO(), resp2, &v2)
+	syntaxErr := &json.SyntaxError{}
+	if !errors.As(err, &syntaxErr) {
+		t.Errorf("expected %v, got %v", syntaxErr, err)
 	}
 }
 
 func TestDefaultErrorDecoder(t *testing.T) {
 	for i := 200; i < 300; i++ {
-		resp := &nethttp.Response{Header: make(nethttp.Header), StatusCode: i}
+		resp := &http.Response{Header: make(http.Header), StatusCode: i}
 		if DefaultErrorDecoder(context.TODO(), resp) != nil {
 			t.Errorf("expected no error, got %v", DefaultErrorDecoder(context.TODO(), resp))
 		}
 	}
-	resp1 := &nethttp.Response{
-		Header:     make(nethttp.Header),
+	resp1 := &http.Response{
+		Header:     make(http.Header),
 		StatusCode: 300,
 		Body:       io.NopCloser(bytes.NewBufferString("{\"foo\":\"bar\"}")),
 	}
@@ -279,28 +275,28 @@ func TestDefaultErrorDecoder(t *testing.T) {
 		t.Errorf("expected error, got nil")
 	}
 
-	resp2 := &nethttp.Response{
-		Header:     make(nethttp.Header),
+	resp2 := &http.Response{
+		Header:     make(http.Header),
 		StatusCode: 500,
 		Body:       io.NopCloser(bytes.NewBufferString("{\"code\":54321, \"message\": \"hi\", \"reason\": \"FOO\"}")),
 	}
-	err2 := DefaultErrorDecoder(context.TODO(), resp2)
-	if err2 == nil {
+	err := DefaultErrorDecoder(context.TODO(), resp2)
+	if err == nil {
 		t.Errorf("expected error, got nil")
 	}
-	if !reflect.DeepEqual(int32(500), err2.(*kratosErrors.Error).Code) {
-		t.Errorf("expected %v, got %v", 500, err2.(*kratosErrors.Error).Code)
+	if err.(*kratoserrors.Error).Code != int32(500) {
+		t.Errorf("expected %v, got %v", 500, err.(*kratoserrors.Error).Code)
 	}
-	if !reflect.DeepEqual("hi", err2.(*kratosErrors.Error).Message) {
-		t.Errorf("expected %v, got %v", "hi", err2.(*kratosErrors.Error).Message)
+	if err.(*kratoserrors.Error).Message != "hi" {
+		t.Errorf("expected %v, got %v", "hi", err.(*kratoserrors.Error).Message)
 	}
-	if !reflect.DeepEqual("FOO", err2.(*kratosErrors.Error).Reason) {
-		t.Errorf("expected %v, got %v", "FOO", err2.(*kratosErrors.Error).Reason)
+	if err.(*kratoserrors.Error).Reason != "FOO" {
+		t.Errorf("expected %v, got %v", "FOO", err.(*kratoserrors.Error).Reason)
 	}
 }
 
 func TestCodecForResponse(t *testing.T) {
-	resp := &nethttp.Response{Header: make(nethttp.Header)}
+	resp := &http.Response{Header: make(http.Header)}
 	resp.Header.Set("Content-Type", "application/xml")
 	c := CodecForResponse(resp)
 	if !reflect.DeepEqual("xml", c.Name()) {
@@ -346,7 +342,7 @@ func TestNewClient(t *testing.T) {
 		}),
 	)
 	if err != nil {
-		t.Error(err)
+		t.Fatal(err)
 	}
 
 	err = client.Invoke(context.Background(), http.MethodPost, "/go", map[string]string{"name": "kratos"}, nil, EmptyCallOption{}, &mockCallOption{})
diff --git a/transport/http/codec_test.go b/transport/http/codec_test.go
index b701b70f..8efd2332 100644
--- a/transport/http/codec_test.go
+++ b/transport/http/codec_test.go
@@ -3,53 +3,50 @@ package http
 import (
 	"bytes"
 	"io"
-	nethttp "net/http"
-	"reflect"
+	"net/http"
 	"testing"
 
 	"github.com/go-kratos/kratos/v2/errors"
 )
 
 func TestDefaultRequestDecoder(t *testing.T) {
-	bodyString := "{\"a\":\"1\", \"b\": 2}"
-
-	req1 := &nethttp.Request{
-		Header: make(nethttp.Header),
-		Body:   io.NopCloser(bytes.NewBufferString(bodyString)),
-	}
-	req1.Header.Set("Content-Type", "application/json")
+	var (
+		bodyStr = `{"a":"1", "b": 2}`
+		r, _    = http.NewRequest(http.MethodPost, "", io.NopCloser(bytes.NewBufferString(bodyStr)))
+	)
+	r.Header.Set("Content-Type", "application/json")
 
 	v1 := &struct {
 		A string `json:"a"`
 		B int64  `json:"b"`
 	}{}
-	err1 := DefaultRequestDecoder(req1, &v1)
-	if err1 != nil {
-		t.Errorf("expected no error, got %v", err1)
+	err := DefaultRequestDecoder(r, &v1)
+	if err != nil {
+		t.Fatal(err)
 	}
-	if !reflect.DeepEqual("1", v1.A) {
+	if v1.A != "1" {
 		t.Errorf("expected %v, got %v", "1", v1.A)
 	}
-	if !reflect.DeepEqual(int64(2), v1.B) {
+	if v1.B != int64(2) {
 		t.Errorf("expected %v, got %v", 2, v1.B)
 	}
 
-	data, err := io.ReadAll(req1.Body)
+	data, err := io.ReadAll(r.Body)
 	if err != nil {
-		t.Errorf("expected no error, got %v", err1)
+		t.Fatal(err)
 	}
-	if !reflect.DeepEqual([]byte(bodyString), data) {
-		t.Errorf("expected %v, got %v", bodyString, data)
+	if bodyStr != string(data) {
+		t.Errorf("expected %v, got %v", bodyStr, string(data))
 	}
 }
 
 type mockResponseWriter struct {
 	StatusCode int
 	Data       []byte
-	header     nethttp.Header
+	header     http.Header
 }
 
-func (w *mockResponseWriter) Header() nethttp.Header {
+func (w *mockResponseWriter) Header() http.Header {
 	return w.header
 }
 
@@ -62,27 +59,28 @@ func (w *mockResponseWriter) WriteHeader(statusCode int) {
 	w.StatusCode = statusCode
 }
 
-type dataWithStatusCode struct {
-	A string `json:"a"`
-	B int64  `json:"b"`
-}
-
 func TestDefaultResponseEncoder(t *testing.T) {
-	w := &mockResponseWriter{StatusCode: 200, header: make(nethttp.Header)}
-	req1 := &nethttp.Request{
-		Header: make(nethttp.Header),
-	}
-	req1.Header.Set("Content-Type", "application/json")
-
-	v1 := &dataWithStatusCode{A: "1", B: 2}
-	err := DefaultResponseEncoder(w, req1, v1)
+	var (
+		w    = &mockResponseWriter{StatusCode: 200, header: make(http.Header)}
+		r, _ = http.NewRequest(http.MethodPost, "", nil)
+		v    = &struct {
+			A string `json:"a"`
+			B int64  `json:"b"`
+		}{
+			A: "1",
+			B: 2,
+		}
+	)
+	r.Header.Set("Content-Type", "application/json")
+
+	err := DefaultResponseEncoder(w, r, v)
 	if err != nil {
-		t.Errorf("expected no error, got %v", err)
+		t.Fatal(err)
 	}
-	if !reflect.DeepEqual("application/json", w.Header().Get("Content-Type")) {
+	if w.Header().Get("Content-Type") != "application/json" {
 		t.Errorf("expected %v, got %v", "application/json", w.Header().Get("Content-Type"))
 	}
-	if !reflect.DeepEqual(200, w.StatusCode) {
+	if w.StatusCode != 200 {
 		t.Errorf("expected %v, got %v", 200, w.StatusCode)
 	}
 	if w.Data == nil {
@@ -90,19 +88,19 @@ func TestDefaultResponseEncoder(t *testing.T) {
 	}
 }
 
-func TestDefaultResponseEncoderWithError(t *testing.T) {
-	w := &mockResponseWriter{header: make(nethttp.Header)}
-	req := &nethttp.Request{
-		Header: make(nethttp.Header),
-	}
-	req.Header.Set("Content-Type", "application/json")
+func TestDefaultErrorEncoder(t *testing.T) {
+	var (
+		w    = &mockResponseWriter{header: make(http.Header)}
+		r, _ = http.NewRequest(http.MethodPost, "", nil)
+		err  = errors.New(511, "", "")
+	)
+	r.Header.Set("Content-Type", "application/json")
 
-	se := errors.New(511, "", "")
-	DefaultErrorEncoder(w, req, se)
-	if !reflect.DeepEqual("application/json", w.Header().Get("Content-Type")) {
+	DefaultErrorEncoder(w, r, err)
+	if w.Header().Get("Content-Type") != "application/json" {
 		t.Errorf("expected %v, got %v", "application/json", w.Header().Get("Content-Type"))
 	}
-	if !reflect.DeepEqual(511, w.StatusCode) {
+	if w.StatusCode != 511 {
 		t.Errorf("expected %v, got %v", 511, w.StatusCode)
 	}
 	if w.Data == nil {
@@ -111,20 +109,20 @@ func TestDefaultResponseEncoderWithError(t *testing.T) {
 }
 
 func TestDefaultResponseEncoderEncodeNil(t *testing.T) {
-	w := &mockResponseWriter{StatusCode: 204, header: make(nethttp.Header)}
-	req1 := &nethttp.Request{
-		Header: make(nethttp.Header),
-	}
-	req1.Header.Set("Content-Type", "application/json")
+	var (
+		w    = &mockResponseWriter{StatusCode: 204, header: make(http.Header)}
+		r, _ = http.NewRequest(http.MethodPost, "", io.NopCloser(bytes.NewBufferString("<xml></xml>")))
+	)
+	r.Header.Set("Content-Type", "application/json")
 
-	err := DefaultResponseEncoder(w, req1, nil)
+	err := DefaultResponseEncoder(w, r, nil)
 	if err != nil {
-		t.Errorf("expected no error, got %v", err)
+		t.Fatal(err)
 	}
-	if !reflect.DeepEqual("", w.Header().Get("Content-Type")) {
+	if w.Header().Get("Content-Type") != "" {
 		t.Errorf("expected empty string, got %v", w.Header().Get("Content-Type"))
 	}
-	if !reflect.DeepEqual(204, w.StatusCode) {
+	if w.StatusCode != 204 {
 		t.Errorf("expected %v, got %v", 204, w.StatusCode)
 	}
 	if w.Data != nil {
@@ -133,31 +131,23 @@ func TestDefaultResponseEncoderEncodeNil(t *testing.T) {
 }
 
 func TestCodecForRequest(t *testing.T) {
-	req1 := &nethttp.Request{
-		Header: make(nethttp.Header),
-		Body:   io.NopCloser(bytes.NewBufferString("<xml></xml>")),
-	}
-	req1.Header.Set("Content-Type", "application/xml")
-
-	c, ok := CodecForRequest(req1, "Content-Type")
+	r, _ := http.NewRequest(http.MethodPost, "", io.NopCloser(bytes.NewBufferString("<xml></xml>")))
+	r.Header.Set("Content-Type", "application/xml")
+	c, ok := CodecForRequest(r, "Content-Type")
 	if !ok {
-		t.Errorf("expected true, got %v", ok)
+		t.Fatalf("expected true, got %v", ok)
 	}
-	if !reflect.DeepEqual("xml", c.Name()) {
+	if c.Name() != "xml" {
 		t.Errorf("expected %v, got %v", "xml", c.Name())
 	}
 
-	req2 := &nethttp.Request{
-		Header: make(nethttp.Header),
-		Body:   io.NopCloser(bytes.NewBufferString("{\"a\":\"1\", \"b\": 2}")),
-	}
-	req2.Header.Set("Content-Type", "blablablabla")
-
-	c, ok = CodecForRequest(req2, "Content-Type")
+	r, _ = http.NewRequest(http.MethodPost, "", io.NopCloser(bytes.NewBufferString(`{"a":"1", "b": 2}`)))
+	r.Header.Set("Content-Type", "blablablabla")
+	c, ok = CodecForRequest(r, "Content-Type")
 	if ok {
-		t.Errorf("expected false, got %v", ok)
+		t.Fatalf("expected false, got %v", ok)
 	}
-	if !reflect.DeepEqual("json", c.Name()) {
+	if c.Name() != "json" {
 		t.Errorf("expected %v, got %v", "json", c.Name())
 	}
 }