Repository: cloudwego/hertz
Pull request #457 (2022-12-06 03:47:58)

test: add tests for pkg/app/server/registry
#### What type of PR is this?
test: Adding missing tests or correcting existing tests
pkg/app/server/registry test coverage reached **_100%_**
<!--
Add one of the following kinds:

build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
docs: Documentation only changes
feat: A new feature
optimize: A new optimization
fix: A bug fix
perf: A code change that improves performance
refactor: A code change that neither fixes a bug nor adds a feature
style: Changes that do not affect the meaning of the code (white space, formatting, missing semi-colons, etc)
test: Adding missing tests or correcting existing tests
chore: Changes to the build process or auxiliary tools and libraries such as documentation generation
-->

#### Check the PR title.
<!--
The description of the title will be attached in Release Notes, 
so please describe it from user-oriented, what this PR does / why we need it.
Please check your PR title with the below requirements:
-->
- [x] This PR title match the format: \<type\>(optional scope): \<description\>
- [x] The description of this PR title is user-oriented and clear enough for others to understand.


#### (Optional) Translate the PR title into Chinese.
为 pkg/app/server/registry添加测试

#### (Optional) More detail description for this PR(en: English/zh: Chinese).
<!--
Provide more detailed info for review. If it is a perf type PR, perf data is suggested to give.
-->
en: Add tests for  pkg/app/server/registry
zh(optional): 为 pkg/app/server/registry添加测试

#### Which issue(s) this PR fixes:
#257 
<!--
Automatically closes linked issue when PR is merged.
Eg: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
-->


codecov[bot]: # [Codecov](https://codecov.io/gh/cloudwego/hertz/pull/457?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego) Report
Base: **68.35**% // Head: **68.35**% // Increases project coverage by **`+0.00%`** :tada:
> Coverage data is based on head [(`e6c4a2e`)](https://codecov.io/gh/cloudwego/hertz/pull/457?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego) compared to base [(`9b9ec92`)](https://codecov.io/gh/cloudwego/hertz/commit/9b9ec92704e19626225f6fc10d69a62f1762dbda?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego).
> Patch has no changes to coverable lines.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff            @@
##           develop     #457   +/-   ##
========================================
  Coverage    68.35%   68.35%           
========================================
  Files           92       93    +1     
  Lines         8684     8688    +4     
========================================
+ Hits          5936     5939    +3     
- Misses        2388     2389    +1     
  Partials       360      360           
```


| [Impacted Files](https://codecov.io/gh/cloudwego/hertz/pull/457?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego) | Coverage Δ | |
|---|---|---|
| [pkg/common/timer/timer.go](https://codecov.io/gh/cloudwego/hertz/pull/457/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego#diff-cGtnL2NvbW1vbi90aW1lci90aW1lci5nbw==) | `61.90% <0.00%> (-19.05%)` | :arrow_down: |
| [pkg/app/server/registry/registry.go](https://codecov.io/gh/cloudwego/hertz/pull/457/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego#diff-cGtnL2FwcC9zZXJ2ZXIvcmVnaXN0cnkvcmVnaXN0cnkuZ28=) | `100.00% <0.00%> (ø)` | |
| [pkg/common/compress/compress.go](https://codecov.io/gh/cloudwego/hertz/pull/457/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego#diff-cGtnL2NvbW1vbi9jb21wcmVzcy9jb21wcmVzcy5nbw==) | `83.80% <0.00%> (+2.85%)` | :arrow_up: |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/cloudwego/hertz/pull/457?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego).


Patch:
diff --git a/.github/labels.json b/.github/labels.json
new file mode 100644
index 0000000..ca8ef3b
--- /dev/null
+++ b/.github/labels.json
@@ -0,0 +1,24 @@
+{
+  "labels": {
+    "invalid_issue": {
+      "name": "invalid issue",
+      "colour": "#CF2E1F",
+      "description": "invalid issue (not related to Hertz or described in document or not enough information provided)"
+    }
+  },
+  "issue": {
+    "invalid_issue": {
+      "requires": 2,
+      "conditions": [
+        {
+          "type": "descriptionMatches",
+          "pattern": "/^((?!Describe the bug).)*$/is"
+        },
+        {
+          "type": "descriptionMatches",
+          "pattern": "/^((?!Is your feature request related to a problem\\? Please describe).)*$/is"
+        }
+      ]
+    }
+  }
+}
diff --git a/.github/workflows/invalid_question.yml b/.github/workflows/invalid_question.yml
new file mode 100644
index 0000000..f465cd4
--- /dev/null
+++ b/.github/workflows/invalid_question.yml
@@ -0,0 +1,26 @@
+name: "Close Invalid Issue"
+on:
+  schedule:
+    - cron: "*/10 * * * *"
+
+permissions:
+  contents: read
+
+jobs:
+  stale:
+    permissions:
+      issues: write
+    runs-on: ubuntu-latest
+    env:
+      ACTIONS_STEP_DEBUG: true
+    steps:
+      - name: Close Stale Issues
+        uses: actions/stale@v6
+        with:
+          repo-token: ${{ secrets.GITHUB_TOKEN }}
+          stale-issue-message: "This issue has been marked as invalid question, please give more information by following the `issue` template. The issue will be closed in 3 days if no further activity occurs."
+          stale-issue-label: "stale"
+          days-before-stale: 0
+          days-before-close: 3
+          remove-stale-when-updated: true
+          only-labels: "invalid issue"
diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml
new file mode 100644
index 0000000..080e937
--- /dev/null
+++ b/.github/workflows/labeler.yml
@@ -0,0 +1,17 @@
+name: "Labeler"
+on:
+  issues:
+    types: [ opened, edited, reopened ]
+
+jobs:
+  triage:
+    runs-on: ubuntu-latest
+    name: Label issues
+    steps:
+      - name: check out
+        uses: actions/checkout@v3
+
+      - name: labeler
+        uses: jbinda/super-labeler-action@develop
+        with:
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/cmd/hz/generator/layout_tpl.go b/cmd/hz/generator/layout_tpl.go
index 38b6f36..3be1543 100644
--- a/cmd/hz/generator/layout_tpl.go
+++ b/cmd/hz/generator/layout_tpl.go
@@ -140,11 +140,12 @@ import (
 
 	"github.com/cloudwego/hertz/pkg/app"
 	"github.com/cloudwego/hertz/pkg/common/utils"
+	"github.com/cloudwego/hertz/pkg/protocol/consts"
 )
 
 // Ping .
 func Ping(ctx context.Context, c *app.RequestContext) {
-	c.JSON(200, utils.H{
+	c.JSON(consts.StatusOK, utils.H{
 		"message": "pong",
 	})
 }
diff --git a/cmd/hz/generator/package_tpl.go b/cmd/hz/generator/package_tpl.go
index 5a2324e..b089fba 100644
--- a/cmd/hz/generator/package_tpl.go
+++ b/cmd/hz/generator/package_tpl.go
@@ -62,6 +62,7 @@ import (
 	"context"
 
 	"github.com/cloudwego/hertz/pkg/app"
+	"github.com/cloudwego/hertz/pkg/protocol/consts"
 
 {{- range $k, $v := .Imports}}
 	{{$k}} "{{$v.Package}}"
@@ -76,13 +77,13 @@ func {{$MethodInfo.Name}}(ctx context.Context, c *app.RequestContext) {
 	var req {{$MethodInfo.RequestTypeName}}
 	err = c.BindAndValidate(&req)
 	if err != nil {
-		c.String(400, err.Error())
+		c.String(consts.StatusBadRequest, err.Error())
 		return
 	}
 	{{end}}
 	resp := new({{$MethodInfo.ReturnTypeName}})
 
-	c.{{.Serializer}}(200, resp)
+	c.{{.Serializer}}(consts.StatusOK, resp)
 }
 {{end}}
 			`,
@@ -222,13 +223,13 @@ func {{.Name}}(ctx context.Context, c *app.RequestContext) {
 	var req {{.RequestTypeName}}
 	err = c.BindAndValidate(&req)
 	if err != nil {
-		c.String(400, err.Error())
+		c.String(consts.StatusBadRequest, err.Error())
 		return
 	}
 	{{end}}
 	resp := new({{.ReturnTypeName}})
 
-	c.{{.Serializer}}(200, resp)
+	c.{{.Serializer}}(consts.StatusOK, resp)
 }
 `,
 		},
diff --git a/pkg/common/errors/errors.go b/pkg/common/errors/errors.go
index dc3f4bb..e9cccdb 100644
--- a/pkg/common/errors/errors.go
+++ b/pkg/common/errors/errors.go
@@ -49,17 +49,18 @@ import (
 
 var (
 	// These errors are the base error, which are used for checking in errors.Is()
-	ErrNeedMore        = errors.New("need more data")
-	ErrChunkedStream   = errors.New("chunked stream")
-	ErrBodyTooLarge    = errors.New("body size exceeds the given limit")
-	ErrHijacked        = errors.New("connection has been hijacked")
-	ErrIdleTimeout     = errors.New("idle timeout")
-	ErrTimeout         = errors.New("timeout")
-	ErrReadTimeout     = errors.New("read timeout")
-	ErrWriteTimeout    = errors.New("write timeout")
-	ErrDialTimeout     = errors.New("dial timeout")
-	ErrNothingRead     = errors.New("nothing read")
-	ErrShortConnection = errors.New("short connection")
+	ErrNeedMore         = errors.New("need more data")
+	ErrChunkedStream    = errors.New("chunked stream")
+	ErrBodyTooLarge     = errors.New("body size exceeds the given limit")
+	ErrHijacked         = errors.New("connection has been hijacked")
+	ErrIdleTimeout      = errors.New("idle timeout")
+	ErrTimeout          = errors.New("timeout")
+	ErrReadTimeout      = errors.New("read timeout")
+	ErrWriteTimeout     = errors.New("write timeout")
+	ErrDialTimeout      = errors.New("dial timeout")
+	ErrNothingRead      = errors.New("nothing read")
+	ErrShortConnection  = errors.New("short connection")
+	ErrConnectionClosed = errors.New("connection closed")
 )
 
 // ErrorType is an unsigned 64-bit error code as defined in the hertz spec.
diff --git a/pkg/network/connection.go b/pkg/network/connection.go
index c963f2b..1559c1c 100644
--- a/pkg/network/connection.go
+++ b/pkg/network/connection.go
@@ -94,3 +94,7 @@ type ConnTLSer interface {
 type HandleSpecificError interface {
 	HandleSpecificError(err error, rip string) (needIgnore bool)
 }
+
+type ErrorNormalization interface {
+	ToHertzError(err error) error
+}
diff --git a/pkg/network/netpoll/connection.go b/pkg/network/netpoll/connection.go
index 9281e64..33d2875 100644
--- a/pkg/network/netpoll/connection.go
+++ b/pkg/network/netpoll/connection.go
@@ -25,15 +25,24 @@ import (
 	"strings"
 	"syscall"
 
+	errs "github.com/cloudwego/hertz/pkg/common/errors"
 	"github.com/cloudwego/hertz/pkg/common/hlog"
 	"github.com/cloudwego/hertz/pkg/network"
 	"github.com/cloudwego/netpoll"
+	"golang.org/x/sys/unix"
 )
 
 type Conn struct {
 	network.Conn
 }
 
+func (c *Conn) ToHertzError(err error) error {
+	if errors.Is(err, netpoll.ErrConnClosed) || errors.Is(err, unix.EPIPE) {
+		return errs.ErrConnectionClosed
+	}
+	return err
+}
+
 func (c *Conn) Peek(n int) (b []byte, err error) {
 	b, err = c.Conn.Peek(n)
 	err = normalizeErr(err)
diff --git a/pkg/network/standard/connection.go b/pkg/network/standard/connection.go
index b1d96e0..b9b2e83 100644
--- a/pkg/network/standard/connection.go
+++ b/pkg/network/standard/connection.go
@@ -18,13 +18,15 @@ package standard
 
 import (
 	"crypto/tls"
+	"errors"
 	"io"
 	"net"
 	"strconv"
 	"time"
 
-	"github.com/cloudwego/hertz/pkg/common/errors"
+	errs "github.com/cloudwego/hertz/pkg/common/errors"
 	"github.com/cloudwego/hertz/pkg/network"
+	"golang.org/x/sys/unix"
 )
 
 const (
@@ -44,6 +46,13 @@ type Conn struct {
 	maxSize      int      // history max malloc size
 }
 
+func (c *Conn) ToHertzError(err error) error {
+	if errors.Is(err, unix.EPIPE) || errors.Is(err, unix.ENOTCONN) {
+		return errs.ErrConnectionClosed
+	}
+	return err
+}
+
 func (c *Conn) SetWriteTimeout(t time.Duration) error {
 	if t <= 0 {
 		return c.c.SetWriteDeadline(time.Time{})
@@ -383,7 +392,7 @@ func (c *Conn) fill(i int) (err error) {
 func (c *Conn) Skip(n int) error {
 	// check whether enough or not.
 	if c.Len() < n {
-		return errors.NewPrivate("link buffer skip[" + strconv.Itoa(n) + "] not enough")
+		return errs.NewPrivate("link buffer skip[" + strconv.Itoa(n) + "] not enough")
 	}
 	c.inputBuffer.len -= n // re-cal length
 
diff --git a/pkg/protocol/http1/client.go b/pkg/protocol/http1/client.go
index a1f18cb..6d42636 100644
--- a/pkg/protocol/http1/client.go
+++ b/pkg/protocol/http1/client.go
@@ -508,7 +508,32 @@ func (c *HostClient) doNonNilReqResp(req *protocol.Request, resp *protocol.Respo
 	}
 	// error happened when writing request, close the connection, and try another connection if retry is enabled
 	if err != nil {
-		c.closeConn(cc)
+		defer c.closeConn(cc)
+
+		errNorm, ok := conn.(network.ErrorNormalization)
+		if ok {
+			err = errNorm.ToHertzError(err)
+		}
+
+		if !errors.Is(err, errs.ErrConnectionClosed) {
+			return true, err
+		}
+
+		// set a protection timeout to avoid infinite loop.
+		if conn.SetReadTimeout(time.Second) != nil {
+			return true, err
+		}
+
+		// Only if the connection is closed while writing the request. Try to parse the response and return.
+		// In this case, the request/response is considered as successful.
+		// Otherwise, return the former error.
+
+		zr := c.acquireReader(conn)
+		defer zr.Release()
+		if respI.ReadHeaderAndLimitBody(resp, zr, c.MaxResponseBodySize) == nil {
+			return false, nil
+		}
+
 		return true, err
 	}
 


Test patch:
diff --git a/pkg/app/client/client_test.go b/pkg/app/client/client_test.go
index e325a0e..c754ce5 100644
--- a/pkg/app/client/client_test.go
+++ b/pkg/app/client/client_test.go
@@ -484,7 +484,7 @@ func TestClientDefaultUserAgent(t *testing.T) {
 	engine := route.NewEngine(opt)
 
 	engine.GET("/", func(c context.Context, ctx *app.RequestContext) {
-		ctx.Data(200, "text/plain; charset=utf-8", ctx.UserAgent())
+		ctx.Data(consts.StatusOK, "text/plain; charset=utf-8", ctx.UserAgent())
 	})
 	go engine.Run()
 	defer func() {
@@ -518,7 +518,7 @@ func TestClientSetUserAgent(t *testing.T) {
 	engine := route.NewEngine(opt)
 
 	engine.GET("/", func(c context.Context, ctx *app.RequestContext) {
-		ctx.Data(200, "text/plain; charset=utf-8", ctx.UserAgent())
+		ctx.Data(consts.StatusOK, "text/plain; charset=utf-8", ctx.UserAgent())
 	})
 	go engine.Run()
 	defer func() {
@@ -549,7 +549,7 @@ func TestClientNoUserAgent(t *testing.T) {
 	engine := route.NewEngine(opt)
 
 	engine.GET("/", func(c context.Context, ctx *app.RequestContext) {
-		ctx.Data(200, "text/plain; charset=utf-8", ctx.UserAgent())
+		ctx.Data(consts.StatusOK, "text/plain; charset=utf-8", ctx.UserAgent())
 	})
 	go engine.Run()
 	defer func() {
@@ -1283,7 +1283,7 @@ func TestPostWithFormData(t *testing.T) {
 			ans = ans + string(key) + "=" + string(value) + "&"
 		})
 		ans = strings.TrimRight(ans, "&")
-		ctx.Data(200, "text/plain; charset=utf-8", []byte(ans))
+		ctx.Data(consts.StatusOK, "text/plain; charset=utf-8", []byte(ans))
 	})
 	go engine.Run()
 
diff --git a/pkg/app/context_test.go b/pkg/app/context_test.go
index 6161506..6ae9443 100644
--- a/pkg/app/context_test.go
+++ b/pkg/app/context_test.go
@@ -47,7 +47,7 @@ import (
 func TestProtobuf(t *testing.T) {
 	ctx := NewContext(0)
 	body := proto.TestStruct{Body: []byte("Hello World")}
-	ctx.ProtoBuf(200, &body)
+	ctx.ProtoBuf(consts.StatusOK, &body)
 
 	assert.DeepEqual(t, string(ctx.Response.Body()), "\n\vHello World")
 }
@@ -140,19 +140,19 @@ func TestNotFound(t *testing.T) {
 
 func TestRedirect(t *testing.T) {
 	ctx := NewContext(0)
-	ctx.Redirect(302, []byte("/hello"))
-	assert.DeepEqual(t, 302, ctx.Response.StatusCode())
+	ctx.Redirect(consts.StatusFound, []byte("/hello"))
+	assert.DeepEqual(t, consts.StatusFound, ctx.Response.StatusCode())
 
-	ctx.redirect([]byte("/hello"), 301)
-	assert.DeepEqual(t, 301, ctx.Response.StatusCode())
+	ctx.redirect([]byte("/hello"), consts.StatusMovedPermanently)
+	assert.DeepEqual(t, consts.StatusMovedPermanently, ctx.Response.StatusCode())
 }
 
 func TestGetRedirectStatusCode(t *testing.T) {
-	val := getRedirectStatusCode(301)
-	assert.DeepEqual(t, 301, val)
+	val := getRedirectStatusCode(consts.StatusMovedPermanently)
+	assert.DeepEqual(t, consts.StatusMovedPermanently, val)
 
-	val = getRedirectStatusCode(404)
-	assert.DeepEqual(t, 302, val)
+	val = getRedirectStatusCode(consts.StatusNotFound)
+	assert.DeepEqual(t, consts.StatusFound, val)
 }
 
 func TestCookie(t *testing.T) {
@@ -504,7 +504,7 @@ func TestContextRenderAttachment(t *testing.T) {
 
 	ctx.FileAttachment("./context.go", newFilename)
 
-	assert.DeepEqual(t, 200, ctx.Response.StatusCode())
+	assert.DeepEqual(t, consts.StatusOK, ctx.Response.StatusCode())
 	assert.True(t, strings.Contains(resp.GetHTTP1Response(&ctx.Response).String(),
 		"func (ctx *RequestContext) FileAttachment(filepath, filename string) {"))
 	assert.DeepEqual(t, fmt.Sprintf("attachment; filename=\"%s\"", newFilename),
@@ -1067,8 +1067,8 @@ func TestFinished(t *testing.T) {
 
 func TestString(t *testing.T) {
 	ctx := NewContext(0)
-	ctx.String(200, "ok")
-	assert.DeepEqual(t, 200, ctx.Response.StatusCode())
+	ctx.String(consts.StatusOK, "ok")
+	assert.DeepEqual(t, consts.StatusOK, ctx.Response.StatusCode())
 }
 
 func TestFullPath(t *testing.T) {
diff --git a/pkg/app/middlewares/server/recovery/option_test.go b/pkg/app/middlewares/server/recovery/option_test.go
index 4a2140d..be3e7d6 100644
--- a/pkg/app/middlewares/server/recovery/option_test.go
+++ b/pkg/app/middlewares/server/recovery/option_test.go
@@ -25,6 +25,7 @@ import (
 	"github.com/cloudwego/hertz/pkg/common/hlog"
 	"github.com/cloudwego/hertz/pkg/common/test/assert"
 	"github.com/cloudwego/hertz/pkg/common/utils"
+	"github.com/cloudwego/hertz/pkg/protocol/consts"
 )
 
 func TestDefaultOption(t *testing.T) {
@@ -35,7 +36,7 @@ func TestDefaultOption(t *testing.T) {
 func newRecoveryHandler(c context.Context, ctx *app.RequestContext, err interface{}, stack []byte) {
 	hlog.SystemLogger().CtxErrorf(c, "[New Recovery] panic recovered:\n%s\n%s\n",
 		err, stack)
-	ctx.JSON(501, utils.H{"msg": err.(string)})
+	ctx.JSON(consts.StatusNotImplemented, utils.H{"msg": err.(string)})
 }
 
 func TestOption(t *testing.T) {
diff --git a/pkg/app/middlewares/server/recovery/recovery_test.go b/pkg/app/middlewares/server/recovery/recovery_test.go
index ffaa1a3..b7211b3 100644
--- a/pkg/app/middlewares/server/recovery/recovery_test.go
+++ b/pkg/app/middlewares/server/recovery/recovery_test.go
@@ -23,6 +23,7 @@ import (
 
 	"github.com/cloudwego/hertz/pkg/app"
 	"github.com/cloudwego/hertz/pkg/common/test/assert"
+	"github.com/cloudwego/hertz/pkg/protocol/consts"
 )
 
 func TestRecovery(t *testing.T) {
@@ -52,7 +53,7 @@ func TestWithRecoveryHandler(t *testing.T) {
 
 	Recovery(WithRecoveryHandler(newRecoveryHandler))(context.Background(), ctx)
 
-	if ctx.Response.StatusCode() != 501 {
+	if ctx.Response.StatusCode() != consts.StatusNotImplemented {
 		t.Fatalf("unexpected %v. Expecting %v", ctx.Response.StatusCode(), 501)
 	}
 	assert.DeepEqual(t, "{\"msg\":\"test\"}", string(ctx.Response.Body()))
diff --git a/pkg/app/server/hertz_test.go b/pkg/app/server/hertz_test.go
index f15db14..31206b0 100644
--- a/pkg/app/server/hertz_test.go
+++ b/pkg/app/server/hertz_test.go
@@ -218,7 +218,7 @@ func TestLoadHTMLGlob(t *testing.T) {
 	go engine.Run()
 	time.Sleep(200 * time.Millisecond)
 	resp, _ := http.Get("http://127.0.0.1:8890/index")
-	assert.DeepEqual(t, 200, resp.StatusCode)
+	assert.DeepEqual(t, consts.StatusOK, resp.StatusCode)
 	b := make([]byte, 100)
 	n, _ := resp.Body.Read(b)
 	assert.DeepEqual(t, "<html>\n<h1>\n    Main website\n</h1>\n</html>", string(b[0:n]))
@@ -240,7 +240,7 @@ func TestLoadHTMLFiles(t *testing.T) {
 	go engine.Run()
 	time.Sleep(200 * time.Millisecond)
 	resp, _ := http.Get("http://127.0.0.1:8891/raw")
-	assert.DeepEqual(t, 200, resp.StatusCode)
+	assert.DeepEqual(t, consts.StatusOK, resp.StatusCode)
 	b := make([]byte, 100)
 	n, _ := resp.Body.Read(b)
 	assert.DeepEqual(t, "<h1>Date: 2017/07/01</h1>", string(b[0:n]))
@@ -283,18 +283,18 @@ func TestServer_Run(t *testing.T) {
 	time.Sleep(100 * time.Microsecond)
 	resp, err := http.Get("http://127.0.0.1:8888/test")
 	assert.Nil(t, err)
-	assert.DeepEqual(t, 200, resp.StatusCode)
+	assert.DeepEqual(t, consts.StatusOK, resp.StatusCode)
 	b := make([]byte, 5)
 	resp.Body.Read(b)
 	assert.DeepEqual(t, "/test", string(b))
 
 	resp, err = http.Get("http://127.0.0.1:8888/foo")
 	assert.Nil(t, err)
-	assert.DeepEqual(t, 404, resp.StatusCode)
+	assert.DeepEqual(t, consts.StatusNotFound, resp.StatusCode)
 
 	resp, err = http.Post("http://127.0.0.1:8888/redirect", "", nil)
 	assert.Nil(t, err)
-	assert.DeepEqual(t, 200, resp.StatusCode)
+	assert.DeepEqual(t, consts.StatusOK, resp.StatusCode)
 	b = make([]byte, 5)
 	resp.Body.Read(b)
 	assert.DeepEqual(t, "/test", string(b))
@@ -323,7 +323,7 @@ func TestNotAbsolutePath(t *testing.T) {
 		t.Fatalf("unexpected error: %s", err)
 	}
 	engine.ServeHTTP(context.Background(), ctx)
-	assert.DeepEqual(t, 200, ctx.Response.StatusCode())
+	assert.DeepEqual(t, consts.StatusOK, ctx.Response.StatusCode())
 	assert.DeepEqual(t, ctx.Request.Body(), ctx.Response.Body())
 
 	s = "POST a?a=b HTTP/1.1\r\nContent-Length: 5\r\nContent-Type: foo/bar\r\n\r\nabcdef4343"
@@ -334,7 +334,7 @@ func TestNotAbsolutePath(t *testing.T) {
 		t.Fatalf("unexpected error: %s", err)
 	}
 	engine.ServeHTTP(context.Background(), ctx)
-	assert.DeepEqual(t, 200, ctx.Response.StatusCode())
+	assert.DeepEqual(t, consts.StatusOK, ctx.Response.StatusCode())
 	assert.DeepEqual(t, ctx.Request.Body(), ctx.Response.Body())
 }
 
@@ -355,7 +355,7 @@ func TestNotAbsolutePathWithRawPath(t *testing.T) {
 		t.Fatalf("unexpected error: %s", err)
 	}
 	engine.ServeHTTP(context.Background(), ctx)
-	assert.DeepEqual(t, 400, ctx.Response.StatusCode())
+	assert.DeepEqual(t, consts.StatusBadRequest, ctx.Response.StatusCode())
 	assert.DeepEqual(t, default400Body, ctx.Response.Body())
 
 	s = "POST a?a=b HTTP/1.1\r\nContent-Length: 5\r\nContent-Type: foo/bar\r\n\r\nabcdef4343"
@@ -366,7 +366,7 @@ func TestNotAbsolutePathWithRawPath(t *testing.T) {
 		t.Fatalf("unexpected error: %s", err)
 	}
 	engine.ServeHTTP(context.Background(), ctx)
-	assert.DeepEqual(t, 400, ctx.Response.StatusCode())
+	assert.DeepEqual(t, consts.StatusBadRequest, ctx.Response.StatusCode())
 	assert.DeepEqual(t, default400Body, ctx.Response.Body())
 }
 
@@ -398,7 +398,7 @@ func TestEnoughBodySize(t *testing.T) {
 	r.Form.Add("xxxxxx", "xxx")
 	body := strings.NewReader(r.Form.Encode())
 	resp, _ := http.Post("http://127.0.0.1:8892/test", "application/x-www-form-urlencoded", body)
-	assert.DeepEqual(t, 200, resp.StatusCode)
+	assert.DeepEqual(t, consts.StatusOK, resp.StatusCode)
 }
 
 func TestRequestCtxHijack(t *testing.T) {
@@ -591,16 +591,16 @@ func TestReusePorts(t *testing.T) {
 	hc := New(WithHostPorts("localhost:10093"), WithListenConfig(cfg))
 	hd := New(WithHostPorts("localhost:10093"), WithListenConfig(cfg))
 	ha.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
-		ctx.JSON(200, utils.H{"ping": "pong"})
+		ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"})
 	})
 	hc.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
-		ctx.JSON(200, utils.H{"ping": "pong"})
+		ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"})
 	})
 	hd.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
-		ctx.JSON(200, utils.H{"ping": "pong"})
+		ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"})
 	})
 	hb.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
-		ctx.JSON(200, utils.H{"ping": "pong"})
+		ctx.JSON(consts.StatusOK, utils.H{"ping": "pong"})
 	})
 	go ha.Run()
 	go hb.Run()
@@ -612,7 +612,7 @@ func TestReusePorts(t *testing.T) {
 	for i := 0; i < 1000; i++ {
 		statusCode, body, err := client.Get(context.Background(), nil, "http://localhost:10093/ping")
 		assert.Nil(t, err)
-		assert.DeepEqual(t, 200, statusCode)
+		assert.DeepEqual(t, consts.StatusOK, statusCode)
 		assert.DeepEqual(t, "{\"ping\":\"pong\"}", string(body))
 	}
 }
diff --git a/pkg/app/server/registry/registry_test.go b/pkg/app/server/registry/registry_test.go
new file mode 100644
index 0000000..77afdb4
--- /dev/null
+++ b/pkg/app/server/registry/registry_test.go
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2022 CloudWeGo Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package registry
+
+import (
+	"testing"
+
+	"github.com/cloudwego/hertz/pkg/common/test/assert"
+)
+
+func TestNoopRegistry(t *testing.T) {
+	reg := noopRegistry{}
+	assert.Nil(t, reg.Deregister(&Info{}))
+	assert.Nil(t, reg.Register(&Info{}))
+}
diff --git a/pkg/common/ut/request_test.go b/pkg/common/ut/request_test.go
index d888335..8580d54 100644
--- a/pkg/common/ut/request_test.go
+++ b/pkg/common/ut/request_test.go
@@ -25,6 +25,7 @@ import (
 	"github.com/cloudwego/hertz/pkg/app"
 	"github.com/cloudwego/hertz/pkg/common/config"
 	"github.com/cloudwego/hertz/pkg/common/test/assert"
+	"github.com/cloudwego/hertz/pkg/protocol/consts"
 	"github.com/cloudwego/hertz/pkg/route"
 )
 
@@ -40,12 +41,12 @@ func TestPerformRequest(t *testing.T) {
 		if string(c.Request.Body()) == "1" {
 			assert.DeepEqual(t, "close", c.Request.Header.Get("Connection"))
 			c.Response.SetConnectionClose()
-			c.JSON(201, map[string]string{"hi": user})
+			c.JSON(consts.StatusCreated, map[string]string{"hi": user})
 		} else if string(c.Request.Body()) == "" {
-			c.AbortWithMsg("unauthorized", 401)
+			c.AbortWithMsg("unauthorized", consts.StatusUnauthorized)
 		} else {
 			assert.DeepEqual(t, "PUT /hey/dy HTTP/1.1\r\nContent-Type: application/x-www-form-urlencoded\r\nTransfer-Encoding: chunked\r\n\r\n", string(c.Request.Header.Header()))
-			c.String(202, "body:%v", string(c.Request.Body()))
+			c.String(consts.StatusAccepted, "body:%v", string(c.Request.Body()))
 		}
 	})
 	router.GET("/her/header", func(ctx context.Context, c *app.RequestContext) {
@@ -58,7 +59,7 @@ func TestPerformRequest(t *testing.T) {
 	w := PerformRequest(router, "PUT", "/hey/dy", &Body{bytes.NewBufferString("1"), 1},
 		Header{"Connection", "close"})
 	resp := w.Result()
-	assert.DeepEqual(t, 201, resp.StatusCode())
+	assert.DeepEqual(t, consts.StatusCreated, resp.StatusCode())
 	assert.DeepEqual(t, "{\"hi\":\"dy\"}", string(resp.Body()))
 	assert.DeepEqual(t, "application/json; charset=utf-8", string(resp.Header.ContentType()))
 	assert.DeepEqual(t, true, resp.Header.ConnectionClose())
@@ -67,7 +68,7 @@ func TestPerformRequest(t *testing.T) {
 	w = PerformRequest(router, "PUT", "/hey/dy", nil)
 	_ = w.Result()
 	resp = w.Result()
-	assert.DeepEqual(t, 401, resp.StatusCode())
+	assert.DeepEqual(t, consts.StatusUnauthorized, resp.StatusCode())
 	assert.DeepEqual(t, "unauthorized", string(resp.Body()))
 	assert.DeepEqual(t, "text/plain; charset=utf-8", string(resp.Header.ContentType()))
 	assert.DeepEqual(t, 12, resp.Header.ContentLength())
@@ -83,21 +84,21 @@ func TestPerformRequest(t *testing.T) {
 	// not found
 	w = PerformRequest(router, "GET", "/hey", nil)
 	resp = w.Result()
-	assert.DeepEqual(t, 404, resp.StatusCode())
+	assert.DeepEqual(t, consts.StatusNotFound, resp.StatusCode())
 
 	// fake body
 	w = PerformRequest(router, "GET", "/hey", nil)
 	_, err := w.WriteString(", faker")
 	resp = w.Result()
 	assert.Nil(t, err)
-	assert.DeepEqual(t, 404, resp.StatusCode())
+	assert.DeepEqual(t, consts.StatusNotFound, resp.StatusCode())
 	assert.DeepEqual(t, "404 page not found, faker", string(resp.Body()))
 
 	// chunked body
 	body := bytes.NewReader(createChunkedBody([]byte("hello world!")))
 	w = PerformRequest(router, "PUT", "/hey/dy", &Body{body, -1})
 	resp = w.Result()
-	assert.DeepEqual(t, 202, resp.StatusCode())
+	assert.DeepEqual(t, consts.StatusAccepted, resp.StatusCode())
 	assert.DeepEqual(t, "body:1\r\nh\r\n2\r\nel\r\n3\r\nlo \r\n4\r\nworl\r\n2\r\nd!\r\n0\r\n\r\n", string(resp.Body()))
 }
 
diff --git a/pkg/common/ut/response_test.go b/pkg/common/ut/response_test.go
index 662714e..bec9f13 100644
--- a/pkg/common/ut/response_test.go
+++ b/pkg/common/ut/response_test.go
@@ -20,27 +20,28 @@ import (
 	"testing"
 
 	"github.com/cloudwego/hertz/pkg/common/test/assert"
+	"github.com/cloudwego/hertz/pkg/protocol/consts"
 )
 
 func TestResult(t *testing.T) {
 	r := new(ResponseRecorder)
 	ret := r.Result()
-	assert.DeepEqual(t, 200, ret.StatusCode())
+	assert.DeepEqual(t, consts.StatusOK, ret.StatusCode())
 }
 
 func TestFlush(t *testing.T) {
 	r := new(ResponseRecorder)
 	r.Flush()
 	ret := r.Result()
-	assert.DeepEqual(t, 200, ret.StatusCode())
+	assert.DeepEqual(t, consts.StatusOK, ret.StatusCode())
 }
 
 func TestWriterHeader(t *testing.T) {
 	r := NewRecorder()
-	r.WriteHeader(201)
-	r.WriteHeader(200)
+	r.WriteHeader(consts.StatusCreated)
+	r.WriteHeader(consts.StatusOK)
 	ret := r.Result()
-	assert.DeepEqual(t, 201, ret.StatusCode())
+	assert.DeepEqual(t, consts.StatusCreated, ret.StatusCode())
 }
 
 func TestWriteString(t *testing.T) {
diff --git a/pkg/protocol/http1/client_test.go b/pkg/protocol/http1/client_test.go
index fa6d6c9..ad63f41 100644
--- a/pkg/protocol/http1/client_test.go
+++ b/pkg/protocol/http1/client_test.go
@@ -266,6 +266,46 @@ func TestReadTimeoutPriority(t *testing.T) {
 	}
 }
 
+func TestDoNonNilReqResp(t *testing.T) {
+	c := &HostClient{
+		ClientOptions: &ClientOptions{
+			Dialer: newSlowConnDialer(func(network, addr string) (network.Conn, error) {
+				return &writeErrConn{
+						Conn: mock.NewConn("HTTP/1.1 400 OK\nContent-Length: 6\n\n123456"),
+					},
+					nil
+			}),
+		},
+	}
+	req := protocol.AcquireRequest()
+	resp := protocol.AcquireResponse()
+	req.SetHost("foobar")
+	retry, err := c.doNonNilReqResp(req, resp)
+	assert.False(t, retry)
+	assert.Nil(t, err)
+	assert.DeepEqual(t, resp.StatusCode(), 400)
+	assert.DeepEqual(t, resp.Body(), []byte("123456"))
+}
+
+func TestDoNonNilReqResp1(t *testing.T) {
+	c := &HostClient{
+		ClientOptions: &ClientOptions{
+			Dialer: newSlowConnDialer(func(network, addr string) (network.Conn, error) {
+				return &writeErrConn{
+						Conn: mock.NewConn(""),
+					},
+					nil
+			}),
+		},
+	}
+	req := protocol.AcquireRequest()
+	resp := protocol.AcquireResponse()
+	req.SetHost("foobar")
+	retry, err := c.doNonNilReqResp(req, resp)
+	assert.True(t, retry)
+	assert.NotNil(t, err)
+}
+
 func TestWriteTimeoutPriority(t *testing.T) {
 	c := &HostClient{
 		ClientOptions: &ClientOptions{
@@ -289,7 +329,7 @@ func TestWriteTimeoutPriority(t *testing.T) {
 		ch <- c.Do(context.Background(), req, resp)
 	}()
 	select {
-	case <-time.After(time.Second * 2000):
+	case <-time.After(time.Second * 2):
 		t.Fatalf("should use writeTimeout in request options")
 	case err := <-ch:
 		assert.DeepEqual(t, errs.ErrWriteTimeout.Error(), err.Error())
@@ -323,3 +363,12 @@ func TestDialTimeoutPriority(t *testing.T) {
 		assert.DeepEqual(t, errs.ErrDialTimeout.Error(), err.Error())
 	}
 }
+
+// mockConn for getting error when write binary data.
+type writeErrConn struct {
+	network.Conn
+}
+
+func (w writeErrConn) WriteBinary(b []byte) (n int, err error) {
+	return 0, errs.ErrConnectionClosed
+}
diff --git a/pkg/protocol/http1/resp/response_test.go b/pkg/protocol/http1/resp/response_test.go
index 83680c7..f23f6df 100644
--- a/pkg/protocol/http1/resp/response_test.go
+++ b/pkg/protocol/http1/resp/response_test.go
@@ -155,7 +155,7 @@ func testResponseReadError(t *testing.T, resp *protocol.Response, response strin
 	}
 
 	testResponseReadSuccess(t, resp, "HTTP/1.1 303 Redisred sedfs sdf\r\nContent-Type: aaa\r\nContent-Length: 5\r\n\r\nHELLOaaa",
-		303, 5, "aaa", "HELLO", "aaa")
+		consts.StatusSeeOther, 5, "aaa", "HELLO", "aaa")
 }
 
 func testResponseReadSuccess(t *testing.T, resp *protocol.Response, response string, expectedStatusCode, expectedContentLength int,
@@ -181,19 +181,19 @@ func TestResponseReadSuccess(t *testing.T) {
 
 	// usual response
 	testResponseReadSuccess(t, resp, "HTTP/1.1 200 OK\r\nContent-Length: 10\r\nContent-Type: foo/bar\r\n\r\n0123456789",
-		200, 10, "foo/bar", "0123456789", "")
+		consts.StatusOK, 10, "foo/bar", "0123456789", "")
 
 	// zero response
 	testResponseReadSuccess(t, resp, "HTTP/1.1 500 OK\r\nContent-Length: 0\r\nContent-Type: foo/bar\r\n\r\n",
-		500, 0, "foo/bar", "", "")
+		consts.StatusInternalServerError, 0, "foo/bar", "", "")
 
 	// response with trailer
 	testResponseReadSuccess(t, resp, "HTTP/1.1 300 OK\r\nContent-Length: 5\r\nContent-Type: bar\r\n\r\n56789aaa",
-		300, 5, "bar", "56789", "aaa")
+		consts.StatusMultipleChoices, 5, "bar", "56789", "aaa")
 
 	// no content-length ('identity' transfer-encoding)
 	testResponseReadSuccess(t, resp, "HTTP/1.1 200 OK\r\nContent-Type: foobar\r\n\r\nzxxc",
-		200, 4, "foobar", "zxxc", "")
+		consts.StatusOK, 4, "foobar", "zxxc", "")
 
 	// explicitly stated 'Transfer-Encoding: identity'
 	testResponseReadSuccess(t, resp, "HTTP/1.1 234 ss\r\nContent-Type: xxx\r\n\r\nxag",
@@ -202,11 +202,11 @@ func TestResponseReadSuccess(t *testing.T) {
 	// big 'identity' response
 	body := string(mock.CreateFixedBody(100500))
 	testResponseReadSuccess(t, resp, "HTTP/1.1 200 OK\r\nContent-Type: aa\r\n\r\n"+body,
-		200, 100500, "aa", body, "")
+		consts.StatusOK, 100500, "aa", body, "")
 
 	// chunked response
 	testResponseReadSuccess(t, resp, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nTransfer-Encoding: chunked\r\n\r\n4\r\nqwer\r\n2\r\nty\r\n0\r\n\r\nzzzzz",
-		200, 6, "text/html", "qwerty", "zzzzz")
+		consts.StatusOK, 6, "text/html", "qwerty", "zzzzz")
 
 	// chunked response with non-chunked Transfer-Encoding.
 	testResponseReadSuccess(t, resp, "HTTP/1.1 230 OK\r\nContent-Type: text\r\nTransfer-Encoding: aaabbb\r\n\r\n2\r\ner\r\n2\r\nty\r\n0\r\n\r\nwe",
@@ -214,7 +214,7 @@ func TestResponseReadSuccess(t *testing.T) {
 
 	// zero chunked response
 	testResponseReadSuccess(t, resp, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\nzzz",
-		200, 0, "text/html", "", "zzz")
+		consts.StatusOK, 0, "text/html", "", "zzz")
 }
 
 func TestResponseReadError(t *testing.T) {
@@ -360,24 +360,24 @@ func TestResponseSuccess(t *testing.T) {
 	t.Parallel()
 
 	// 200 response
-	testResponseSuccess(t, 200, "test/plain", "server", "foobar",
-		200, "test/plain", "server")
+	testResponseSuccess(t, consts.StatusOK, "test/plain", "server", "foobar",
+		consts.StatusOK, "test/plain", "server")
 
 	// response with missing statusCode
 	testResponseSuccess(t, 0, "text/plain", "server", "foobar",
-		200, "text/plain", "server")
+		consts.StatusOK, "text/plain", "server")
 
 	// response with missing server
-	testResponseSuccess(t, 500, "aaa", "", "aaadfsd",
-		500, "aaa", "")
+	testResponseSuccess(t, consts.StatusInternalServerError, "aaa", "", "aaadfsd",
+		consts.StatusInternalServerError, "aaa", "")
 
 	// empty body
-	testResponseSuccess(t, 200, "bbb", "qwer", "",
-		200, "bbb", "qwer")
+	testResponseSuccess(t, consts.StatusOK, "bbb", "qwer", "",
+		consts.StatusOK, "bbb", "qwer")
 
 	// missing content-type
-	testResponseSuccess(t, 200, "", "asdfsd", "asdf",
-		200, string(bytestr.DefaultContentType), "asdfsd")
+	testResponseSuccess(t, consts.StatusOK, "", "asdfsd", "asdf",
+		consts.StatusOK, string(bytestr.DefaultContentType), "asdfsd")
 }
 
 func TestResponseReadLimitBody(t *testing.T) {
@@ -405,16 +405,16 @@ func TestResponseReadWithoutBody(t *testing.T) {
 	var resp protocol.Response
 
 	testResponseReadWithoutBody(t, &resp, "HTTP/1.1 304 Not Modified\r\nContent-Type: aa\r\nContent-Length: 1235\r\n\r\nfoobar", false,
-		304, 1235, "aa", "foobar")
+		consts.StatusNotModified, 1235, "aa", "foobar")
 
 	testResponseReadWithoutBody(t, &resp, "HTTP/1.1 204 Foo Bar\r\nContent-Type: aab\r\nTransfer-Encoding: chunked\r\n\r\n123\r\nss", false,
-		204, -1, "aab", "123\r\nss")
+		consts.StatusNoContent, -1, "aab", "123\r\nss")
 
 	testResponseReadWithoutBody(t, &resp, "HTTP/1.1 123 AAA\r\nContent-Type: xxx\r\nContent-Length: 3434\r\n\r\naaaa", false,
 		123, 3434, "xxx", "aaaa")
 
 	testResponseReadWithoutBody(t, &resp, "HTTP 200 OK\r\nContent-Type: text/xml\r\nContent-Length: 123\r\n\r\nxxxx", true,
-		200, 123, "text/xml", "xxxx")
+		consts.StatusOK, 123, "text/xml", "xxxx")
 
 	// '100 Continue' must be skipped.
 	testResponseReadWithoutBody(t, &resp, "HTTP/1.1 100 Continue\r\nFoo-bar: baz\r\n\r\nHTTP/1.1 329 aaa\r\nContent-Type: qwe\r\nContent-Length: 894\r\n\r\nfoobar", true,
@@ -495,7 +495,7 @@ func testResponseReadWithoutBody(t *testing.T, resp *protocol.Response, s string
 	// verify that ordinal response is read after null-body response
 	resp.SkipBody = false
 	testResponseReadSuccess(t, resp, "HTTP/1.1 300 OK\r\nContent-Length: 5\r\nContent-Type: bar\r\n\r\n56789aaa",
-		300, 5, "bar", "56789", "aaa")
+		consts.StatusMultipleChoices, 5, "bar", "56789", "aaa")
 }
 
 func testResponseReadLimitBodyError(t *testing.T, s string, maxBodySize int) {
diff --git a/pkg/protocol/response_test.go b/pkg/protocol/response_test.go
index 4f2f56e..7d88e0b 100644
--- a/pkg/protocol/response_test.go
+++ b/pkg/protocol/response_test.go
@@ -51,6 +51,7 @@ import (
 	"github.com/cloudwego/hertz/pkg/common/bytebufferpool"
 	"github.com/cloudwego/hertz/pkg/common/compress"
 	"github.com/cloudwego/hertz/pkg/common/test/assert"
+	"github.com/cloudwego/hertz/pkg/protocol/consts"
 )
 
 func TestResponseCopyTo(t *testing.T) {
@@ -64,7 +65,7 @@ func TestResponseCopyTo(t *testing.T) {
 	// init resp
 	// resp.laddr = zeroTCPAddr
 	resp.SkipBody = true
-	resp.Header.SetStatusCode(200)
+	resp.Header.SetStatusCode(consts.StatusOK)
 	resp.SetBodyString("test")
 	testResponseCopyTo(t, &resp)
 }
@@ -179,11 +180,11 @@ func testResponseCopyTo(t *testing.T, src *Response) {
 
 func TestResponseMustSkipBody(t *testing.T) {
 	resp := Response{}
-	resp.SetStatusCode(200)
+	resp.SetStatusCode(consts.StatusOK)
 	resp.SetBodyString("test")
 	assert.False(t, resp.MustSkipBody())
 	// no content 204 means that skip body is necessary
-	resp.SetStatusCode(204)
+	resp.SetStatusCode(consts.StatusNoContent)
 	resp.ResetBody()
 	assert.True(t, resp.MustSkipBody())
 }
@@ -225,7 +226,7 @@ func TestResponseAcquireResponse(t *testing.T) {
 	resp1 := AcquireResponse()
 	assert.NotNil(t, resp1)
 	resp1.SetBody([]byte("test"))
-	resp1.SetStatusCode(200)
+	resp1.SetStatusCode(consts.StatusOK)
 	ReleaseResponse(resp1)
 	assert.Nil(t, resp1.body)
 }
diff --git a/pkg/route/engine_test.go b/pkg/route/engine_test.go
index 379b53f..83ffc10 100644
--- a/pkg/route/engine_test.go
+++ b/pkg/route/engine_test.go
@@ -61,6 +61,7 @@ import (
 	"github.com/cloudwego/hertz/pkg/network"
 	"github.com/cloudwego/hertz/pkg/network/netpoll"
 	"github.com/cloudwego/hertz/pkg/network/standard"
+	"github.com/cloudwego/hertz/pkg/protocol/consts"
 )
 
 func TestNew_Engine(t *testing.T) {
@@ -105,7 +106,7 @@ func TestEngineUnescape(t *testing.T) {
 
 	for _, r := range routes {
 		e.GET(r, func(c context.Context, ctx *app.RequestContext) {
-			ctx.String(200, ctx.Param(ctx.Query("key")))
+			ctx.String(consts.StatusOK, ctx.Param(ctx.Query("key")))
 		})
 	}
 
@@ -122,7 +123,7 @@ func TestEngineUnescape(t *testing.T) {
 	}
 	for _, tr := range testRoutes {
 		w := performRequest(e, http.MethodGet, tr.route+"?key="+tr.key)
-		assert.DeepEqual(t, 200, w.Code)
+		assert.DeepEqual(t, consts.StatusOK, w.Code)
 		assert.DeepEqual(t, tr.want, w.Body.String())
 	}
 }
@@ -142,7 +143,7 @@ func TestEngineUnescapeRaw(t *testing.T) {
 
 	for _, r := range routes {
 		e.GET(r, func(c context.Context, ctx *app.RequestContext) {
-			ctx.String(200, ctx.Param(ctx.Query("key")))
+			ctx.String(consts.StatusOK, ctx.Param(ctx.Query("key")))
 		})
 	}
 
@@ -169,7 +170,7 @@ func TestEngineUnescapeRaw(t *testing.T) {
 	}
 	for _, tr := range testRoutes {
 		w := performRequest(e, http.MethodGet, tr.route+"?key="+tr.key)
-		assert.DeepEqual(t, 200, w.Code)
+		assert.DeepEqual(t, consts.StatusOK, w.Code)
 		assert.DeepEqual(t, tr.want, w.Body.String())
 	}
 }
@@ -179,7 +180,7 @@ func TestConnectionClose(t *testing.T) {
 	atomic.StoreUint32(&engine.status, statusRunning)
 	engine.Init()
 	engine.GET("/foo", func(c context.Context, ctx *app.RequestContext) {
-		ctx.String(200, "ok")
+		ctx.String(consts.StatusOK, "ok")
 	})
 	conn := mock.NewConn("GET /foo HTTP/1.1\r\nHost: google.com\r\nConnection: close\r\n\r\n")
 	err := engine.Serve(context.Background(), conn)
@@ -192,7 +193,7 @@ func TestConnectionClose01(t *testing.T) {
 	engine.Init()
 	engine.GET("/foo", func(c context.Context, ctx *app.RequestContext) {
 		ctx.SetConnectionClose()
-		ctx.String(200, "ok")
+		ctx.String(consts.StatusOK, "ok")
 	})
 	conn := mock.NewConn("GET /foo HTTP/1.1\r\nHost: google.com\r\n\r\n")
 	err := engine.Serve(context.Background(), conn)
@@ -206,7 +207,7 @@ func TestIdleTimeout(t *testing.T) {
 	engine.Init()
 	engine.GET("/foo", func(c context.Context, ctx *app.RequestContext) {
 		time.Sleep(100 * time.Millisecond)
-		ctx.String(200, "ok")
+		ctx.String(consts.StatusOK, "ok")
 	})
 
 	conn := mock.NewConn("GET /foo HTTP/1.1\r\nHost: google.com\r\n\r\n")
@@ -237,7 +238,7 @@ func TestIdleTimeout01(t *testing.T) {
 	atomic.StoreUint32(&engine.status, statusRunning)
 	engine.GET("/foo", func(c context.Context, ctx *app.RequestContext) {
 		time.Sleep(10 * time.Millisecond)
-		ctx.String(200, "ok")
+		ctx.String(consts.StatusOK, "ok")
 	})
 
 	conn := mock.NewConn("GET /foo HTTP/1.1\r\nHost: google.com\r\n\r\n")
@@ -266,7 +267,7 @@ func TestIdleTimeout03(t *testing.T) {
 	atomic.StoreUint32(&engine.status, statusRunning)
 	engine.GET("/foo", func(c context.Context, ctx *app.RequestContext) {
 		time.Sleep(50 * time.Millisecond)
-		ctx.String(200, "ok")
+		ctx.String(consts.StatusOK, "ok")
 	})
 
 	conn := mock.NewConn("GET /foo HTTP/1.1\r\nHost: google.com\r\n\r\n" +
@@ -412,7 +413,7 @@ func TestRenderHtml(t *testing.T) {
 	})
 	rr := performRequest(e, "GET", "/templateName")
 	b, _ := ioutil.ReadAll(rr.Body)
-	assert.DeepEqual(t, 200, rr.Code)
+	assert.DeepEqual(t, consts.StatusOK, rr.Code)
 	assert.DeepEqual(t, []byte("<h1>Date: 2017/07/01</h1>"), b)
 	assert.DeepEqual(t, "text/html; charset=utf-8", rr.Header().Get("Content-Type"))
 }
@@ -460,7 +461,7 @@ func TestRenderHtmlOfGlobWithAutoRender(t *testing.T) {
 	})
 	rr := performRequest(e, "GET", "/templateName")
 	b, _ := ioutil.ReadAll(rr.Body)
-	assert.DeepEqual(t, 200, rr.Code)
+	assert.DeepEqual(t, consts.StatusOK, rr.Code)
 	assert.DeepEqual(t, []byte("<h1>Date: 2017/07/01</h1>"), b)
 	assert.DeepEqual(t, "text/html; charset=utf-8", rr.Header().Get("Content-Type"))
 }
@@ -481,7 +482,7 @@ func TestRenderHtmlOfFilesWithAutoRender(t *testing.T) {
 	})
 	rr := performRequest(e, "GET", "/templateName")
 	b, _ := ioutil.ReadAll(rr.Body)
-	assert.DeepEqual(t, 200, rr.Code)
+	assert.DeepEqual(t, consts.StatusOK, rr.Code)
 	assert.DeepEqual(t, []byte("<h1>Date: 2017/07/01</h1>"), b)
 	assert.DeepEqual(t, "text/html; charset=utf-8", rr.Header().Get("Content-Type"))
 }
diff --git a/pkg/route/routes_test.go b/pkg/route/routes_test.go
index 6d8cac6..1e76d67 100644
--- a/pkg/route/routes_test.go
+++ b/pkg/route/routes_test.go
@@ -267,10 +267,10 @@ func TestRouteRedirectTrailingSlash(t *testing.T) {
 
 	w = performRequest(router, consts.MethodGet, "/path2", header{Key: "X-Forwarded-Prefix", Value: "/api"})
 	assert.DeepEqual(t, "/api/path2/", w.Header().Get("Location"))
-	assert.DeepEqual(t, 301, w.Code)
+	assert.DeepEqual(t, consts.StatusMovedPermanently, w.Code)
 
 	w = performRequest(router, consts.MethodGet, "/path2/", header{Key: "X-Forwarded-Prefix", Value: "/api/"})
-	assert.DeepEqual(t, 200, w.Code)
+	assert.DeepEqual(t, consts.StatusOK, w.Code)
 
 	router.options.RedirectTrailingSlash = false
 
@@ -593,7 +593,7 @@ func TestRouterStaticFSNotFound(t *testing.T) {
 	router := NewEngine(config.NewOptions(nil))
 	router.StaticFS("/", &app.FS{Root: "/thisreallydoesntexist/"})
 	router.NoRoute(func(c context.Context, ctx *app.RequestContext) {
-		ctx.String(404, "non existent")
+		ctx.String(consts.StatusNotFound, "non existent")
 	})
 
 	w := performRequest(router, consts.MethodGet, "/nonexistent")
@@ -825,7 +825,7 @@ func TestRouterParamWithSlash(t *testing.T) {
 	ctx.Request.Header.SetMethod(consts.MethodGet)
 	e.ServeHTTP(context.Background(), ctx)
 	assert.Nil(t, getHelper(ctx, "path"))
-	assert.DeepEqual(t, 404, ctx.Response.StatusCode())
+	assert.DeepEqual(t, consts.StatusNotFound, ctx.Response.StatusCode())
 }
 
 func TestRouteMultiLevelBacktracking(t *testing.T) {