Repository: cloudwego/hertz
Pull request #437 (2022-11-29 16:32:36)

ci: add a labeler to limit the specification of the issue template
#### What type of PR is this?

ci
<!--
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.

添加 labeler 来规范使用 issue 模版。


#### (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.
-->

There are often users who do not follow the issue template when submitting issues. Adding a labeler can effectively avoid this problem.

When it is judged as `invalid issue`, there will be a buffer period of 3 days. If there is no change, this issue will be closed directly.

When the issue is edited, it will be checked again, and if there is no problem, the label will be removed.

#### Which issue(s) this PR fixes:

<!--
Automatically closes linked issue when PR is merged.
Eg: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
-->

None.

li-jin-gou: Good job👍🏻
codecov[bot]: # [Codecov](https://codecov.io/gh/cloudwego/hertz/pull/437?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego) Report
Base: **68.05**% // Head: **68.10**% // Increases project coverage by **`+0.04%`** :tada:
> Coverage data is based on head [(`1c4e7df`)](https://codecov.io/gh/cloudwego/hertz/pull/437?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego) compared to base [(`f4b9e2b`)](https://codecov.io/gh/cloudwego/hertz/commit/f4b9e2b17dd345c086c0bf0af6c744df5fb6f8f5?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     #437      +/-   ##
===========================================
+ Coverage    68.05%   68.10%   +0.04%     
===========================================
  Files           90       90              
  Lines         8627     8627              
===========================================
+ Hits          5871     5875       +4     
+ Misses        2395     2391       -4     
  Partials       361      361              
```


| [Impacted Files](https://codecov.io/gh/cloudwego/hertz/pull/437?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/437/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego#diff-cGtnL2NvbW1vbi90aW1lci90aW1lci5nbw==) | `80.95% <0.00%> (+19.04%)` | :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/437?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/README.md b/README.md
index 554319c..387b2f4 100644
--- a/README.md
+++ b/README.md
@@ -58,32 +58,35 @@ Hertz [həːts] is a high-usability, high-performance and high-extensibility Gol
 - [Example](https://github.com/cloudwego/hertz-examples): Use examples of Hertz.
 ## Extensions
 
-| Extensions                                                                                         | Description                                                                                                                                                             |
-|----------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [Websocket](https://github.com/hertz-contrib/websocket)                                            | Enable Hertz to support the Websocket protocol.                                                                                                                         |
-| [Pprof](https://github.com/hertz-contrib/pprof)                                                    | Extension for Hertz integration with Pprof.                                                                                                                             |
-| [Sessions](https://github.com/hertz-contrib/sessions)                                              | Session middleware with multi-state store support.                                                                                                                      |
-| [Obs-opentelemetry](https://github.com/hertz-contrib/obs-opentelemetry)                            | Hertz's Opentelemetry extension that supports Metric, Logger, Tracing and works out of the box.                                                                         |
+| Extensions                                                                                         | Description                                                                                                                                                                    |
+|----------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [Autotls](https://github.com/hertz-contrib/autotls)                                                | Make Hertz support Let's Encrypt.                                                                                                                                              |
+| [Http2](https://github.com/hertz-contrib/http2)                                                    | HTTP2 support for Hertz.                                                                                                                                                       |
+| [Websocket](https://github.com/hertz-contrib/websocket)                                            | Enable Hertz to support the Websocket protocol.                                                                                                                                |
+| [Limiter](https://github.com/hertz-contrib/limiter)                                                | Provides a current limiter based on the bbr algorithm.                                                                                                                         |
+| [Monitor-prometheus](https://github.com/hertz-contrib/monitor-prometheus)                          | Provides service monitoring based on Prometheus.                                                                                                                               |
+| [Obs-opentelemetry](https://github.com/hertz-contrib/obs-opentelemetry)                            | Hertz's Opentelemetry extension that supports Metric, Logger, Tracing and works out of the box.                                                                                |
+| [Opensergo](https://github.com/hertz-contrib/opensergo)                                            | The Opensergo extension.                                                                                                                                                       |
+| [Pprof](https://github.com/hertz-contrib/pprof)                                                    | Extension for Hertz integration with Pprof.                                                                                                                                    |
 | [Registry](https://github.com/hertz-contrib/registry)                                              | Provides service registry and discovery functions. So far, the supported service discovery extensions are nacos, consul, etcd, eureka, polaris, servicecomb, zookeeper, redis. |
-| [Keyauth](https://github.com/hertz-contrib/keyauth)                                                | Provides token-based authentication.                                                                                                                                    |
-| [Secure](https://github.com/hertz-contrib/secure)                                                  | Secure middleware with multiple configuration items.                                                                                                                    |
-| [Sentry](https://github.com/hertz-contrib/hertzsentry)                                             | Sentry extension provides some unified interfaces to help users perform real-time error monitoring.                                                                     |
-| [Requestid](https://github.com/hertz-contrib/requestid)                                            | Add request id in response.                                                                                                                                             |
-| [Limiter](https://github.com/hertz-contrib/limiter)                                                | Provides a current limiter based on the bbr algorithm.                                                                                                                  |
-| [Jwt](https://github.com/hertz-contrib/jwt)                                                        | Jwt extension.                                                                                                                                                          |
-| [Autotls](https://github.com/hertz-contrib/autotls)                                                | Make Hertz support Let's Encrypt.                                                                                                                                       |
-| [Monitor-prometheus](https://github.com/hertz-contrib/monitor-prometheus)                          | Provides service monitoring based on Prometheus.                                                                                                                        |
-| [I18n](https://github.com/hertz-contrib/i18n)                                                      | Helps translate Hertz programs into multi programming languages.                                                                                                        |
-| [Reverseproxy](https://github.com/hertz-contrib/reverseproxy)                                      | Implement a reverse proxy.                                                                                                                                              |
-| [Opensergo](https://github.com/hertz-contrib/opensergo)                                            | The Opensergo extension.                                                                                                                                                |
-| [Gzip](https://github.com/hertz-contrib/gzip)                                                      | A Gzip extension with multiple options.                                                                                                                                 |
-| [Cors](https://github.com/hertz-contrib/cors)                                                      | Provides cross-domain resource sharing support.                                                                                                                         |
-| [Swagger](https://github.com/hertz-contrib/swagger)                                                | Automatically generate RESTful API documentation with Swagger 2.0.                                                                                                      |
-| [Tracer](https://github.com/hertz-contrib/tracer)                                                  | Link tracing based on Opentracing.                                                                                                                                      |
-| [Recovery](https://github.com/cloudwego/hertz/tree/develop/pkg/app/middlewares/server/recovery)    | Recovery middleware for Hertz.                                                                                                                                          |
-| [Basicauth](https://github.com/cloudwego/hertz/tree/develop/pkg/app/middlewares/server/basic_auth) | Basicauth middleware can provide HTTP basic authentication.                                                                                                             |
-| [Lark](https://github.com/hertz-contrib/lark-hertz)                                                | Use hertz handle Lark/Feishu card message and event callback.                                                                                                           |
-| [Logger](https://github.com/hertz-contrib/logger)                                                  | Logger extension for Hertz, which provides support for zap, logrus, zerologs logging frameworks.                                                                        |
+| [Sentry](https://github.com/hertz-contrib/hertzsentry)                                             | Sentry extension provides some unified interfaces to help users perform real-time error monitoring.                                                                            |
+| [Tracer](https://github.com/hertz-contrib/tracer)                                                  | Link tracing based on Opentracing.                                                                                                                                             |
+| [Basicauth](https://github.com/cloudwego/hertz/tree/develop/pkg/app/middlewares/server/basic_auth) | Basicauth middleware can provide HTTP basic authentication.                                                                                                                    |
+| [Jwt](https://github.com/hertz-contrib/jwt)                                                        | Jwt extension.                                                                                                                                                                 |
+| [Keyauth](https://github.com/hertz-contrib/keyauth)                                                | Provides token-based authentication.                                                                                                                                           |
+| [Requestid](https://github.com/hertz-contrib/requestid)                                            | Add request id in response.                                                                                                                                                    |
+| [Sessions](https://github.com/hertz-contrib/sessions)                                              | Session middleware with multi-state store support.                                                                                                                             |
+| [Cors](https://github.com/hertz-contrib/cors)                                                      | Provides cross-domain resource sharing support.                                                                                                                                |
+| [Csrf](https://github.com/hertz-contrib/csrf)                                                      | Csrf middleware is used to prevent cross-site request forgery attacks.                                                                                                         |
+| [Secure](https://github.com/hertz-contrib/secure)                                                  | Secure middleware with multiple configuration items.                                                                                                                           |
+| [Gzip](https://github.com/hertz-contrib/gzip)                                                      | A Gzip extension with multiple options.                                                                                                                                        |
+| [I18n](https://github.com/hertz-contrib/i18n)                                                      | Helps translate Hertz programs into multi programming languages.                                                                                                               |
+| [Lark](https://github.com/hertz-contrib/lark-hertz)                                                | Use hertz handle Lark/Feishu card message and event callback.                                                                                                                  |
+| [Loadbalance](https://github.com/hertz-contrib/loadbalance)                                        | Provides load balancing algorithms for Hertz.                                                                                                                                  |
+| [Logger](https://github.com/hertz-contrib/logger)                                                  | Logger extension for Hertz, which provides support for zap, logrus, zerologs logging frameworks.                                                                               |
+| [Recovery](https://github.com/cloudwego/hertz/tree/develop/pkg/app/middlewares/server/recovery)    | Recovery middleware for Hertz.                                                                                                                                                 |
+| [Reverseproxy](https://github.com/hertz-contrib/reverseproxy)                                      | Implement a reverse proxy.                                                                                                                                                     |
+| [Swagger](https://github.com/hertz-contrib/swagger)                                                | Automatically generate RESTful API documentation with Swagger 2.0.                                                                                                             |
 
 ## Blogs
 - [ByteDance Practice on Go Network Library](https://www.cloudwego.io/blog/2021/10/09/bytedance-practices-on-go-network-library/)
diff --git a/README_cn.md b/README_cn.md
index 942b743..2ca5823 100644
--- a/README_cn.md
+++ b/README_cn.md
@@ -58,32 +58,35 @@ Hertz[həːts] 是一个 Golang 微服务 HTTP 框架，在设计之初参考了
 - [Example](https://github.com/cloudwego/hertz-examples): Hertz 使用例子
 ## 相关拓展
 
-| 拓展                                                                                                 | 描述                                                                                         |
-|----------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|
-| [Websocket](https://github.com/hertz-contrib/websocket)                                            | 使 Hertz 支持 Websocket 协议。                                                                   |
-| [Pprof](https://github.com/hertz-contrib/pprof)                                                    | Hertz 集成 Pprof 的扩展。                                                                        |
-| [Sessions](https://github.com/hertz-contrib/sessions)                                              | 具有多状态存储支持的 Session 中间件。                                                                    |
-| [Obs-opentelemetry](https://github.com/hertz-contrib/obs-opentelemetry)                            | Hertz 的 Opentelemetry 扩展，支持 Metric、Logger、Tracing并且达到开箱即用。                                 |
+| 拓展                                                                                                 | 描述                                                                                                |
+|----------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------|
+| [Autotls](https://github.com/hertz-contrib/autotls)                                                | 为 Hertz 支持 Let's Encrypt 。                                                                        |
+| [Http2](https://github.com/hertz-contrib/http2)                                                    | 提供对 HTTP2 的支持。                                                                                    |
+| [Websocket](https://github.com/hertz-contrib/websocket)                                            | 使 Hertz 支持 Websocket 协议。                                                                          |
+| [Limiter](https://github.com/hertz-contrib/limiter)                                                | 提供了基于 bbr 算法的限流器。                                                                                 |
+| [Monitor-prometheus](https://github.com/hertz-contrib/monitor-prometheus)                          | 提供基于 Prometheus 服务监控功能。                                                                           |
+| [Obs-opentelemetry](https://github.com/hertz-contrib/obs-opentelemetry)                            | Hertz 的 Opentelemetry 扩展，支持 Metric、Logger、Tracing并且达到开箱即用。                                        |
+| [Opensergo](https://github.com/hertz-contrib/opensergo)                                            | Opensergo 扩展。                                                                                     |
+| [Pprof](https://github.com/hertz-contrib/pprof)                                                    | Hertz 集成 Pprof 的扩展。                                                                               |
 | [Registry](https://github.com/hertz-contrib/registry)                                              | 提供服务注册与发现功能。到现在为止，支持的服务发现拓展有 nacos， consul， etcd， eureka， polaris， servicecomb， zookeeper， redis。 |
-| [Keyauth](https://github.com/hertz-contrib/keyauth)                                                | 提供基于 token 的身份验证。                                                                          |
-| [Secure](https://github.com/hertz-contrib/secure)                                                  | 具有多配置项的 Secure 中间件。                                                                        |
-| [Sentry](https://github.com/hertz-contrib/hertzsentry)                                             | Sentry 拓展提供了一些统一的接口来帮助用户进行实时的错误监控。                                                         |
-| [Requestid](https://github.com/hertz-contrib/requestid)                                            | 在 response 中添加 request id。                                                                 |
-| [Limiter](https://github.com/hertz-contrib/limiter)                                                | 提供了基于 bbr 算法的限流器。                                                                          |
-| [Jwt](https://github.com/hertz-contrib/jwt)                                                        | Jwt 拓展。                                                                                    |
-| [Autotls](https://github.com/hertz-contrib/autotls)                                                | 为 Hertz 支持 Let's Encrypt 。                                                                 |
-| [Monitor-prometheus](https://github.com/hertz-contrib/monitor-prometheus)                          | 提供基于 Prometheus 服务监控功能。                                                                    |
-| [I18n](https://github.com/hertz-contrib/i18n)                                                      | 可帮助将 Hertz 程序翻译成多种语言。                                                                      |
-| [Reverseproxy](https://github.com/hertz-contrib/reverseproxy)                                      | 实现反向代理。                                                                                    |
-| [Opensergo](https://github.com/hertz-contrib/opensergo)                                            | Opensergo 扩展。                                                                              |
-| [Gzip](https://github.com/hertz-contrib/gzip)                                                      | 含多个可选项的 Gzip 拓展。                                                                           |
-| [Cors](https://github.com/hertz-contrib/cors)                                                      | 提供跨域资源共享支持。                                                                                |
-| [Swagger](https://github.com/hertz-contrib/swagger)                                                | 使用 Swagger 2.0 自动生成 RESTful API 文档。                                                        |
-| [Tracer](https://github.com/hertz-contrib/tracer)                                                  | 基于 Opentracing 的链路追踪。                                                                      |
-| [Recovery](https://github.com/cloudwego/hertz/tree/develop/pkg/app/middlewares/server/recovery)    | Hertz 的异常恢复中间件。                                                                            |
-| [Basicauth](https://github.com/cloudwego/hertz/tree/develop/pkg/app/middlewares/server/basic_auth) | Basicauth 中间件能够提供 HTTP 基本身份验证。                                                             |
-| [Lark](https://github.com/hertz-contrib/lark-hertz)                                                | 在 Hertz 中处理 Lark/飞书的卡片消息和事件的回调。                                                            |
-| [Logger](https://github.com/hertz-contrib/logger)                                                  | Hertz 的日志拓展，提供了对 zap、logrus、zerologs 日志框架的支持。                                              |
+| [Sentry](https://github.com/hertz-contrib/hertzsentry)                                             | Sentry 拓展提供了一些统一的接口来帮助用户进行实时的错误监控。                                                                |
+| [Tracer](https://github.com/hertz-contrib/tracer)                                                  | 基于 Opentracing 的链路追踪。                                                                             |
+| [Basicauth](https://github.com/cloudwego/hertz/tree/develop/pkg/app/middlewares/server/basic_auth) | Basicauth 中间件能够提供 HTTP 基本身份验证。                                                                    |
+| [Jwt](https://github.com/hertz-contrib/jwt)                                                        | Jwt 拓展。                                                                                           |
+| [Keyauth](https://github.com/hertz-contrib/keyauth)                                                | 提供基于 token 的身份验证。                                                                                 |
+| [Requestid](https://github.com/hertz-contrib/requestid)                                            | 在 response 中添加 request id。                                                                        |
+| [Sessions](https://github.com/hertz-contrib/sessions)                                              | 具有多状态存储支持的 Session 中间件。                                                                           |
+| [Cors](https://github.com/hertz-contrib/cors)                                                      | 提供跨域资源共享支持。                                                                                       |
+| [Csrf](https://github.com/hertz-contrib/csrf)                                                      | Csrf 中间件用于防止跨站点请求伪造攻击。                                                                            |
+| [Secure](https://github.com/hertz-contrib/secure)                                                  | 具有多配置项的 Secure 中间件。                                                                               |
+| [Gzip](https://github.com/hertz-contrib/gzip)                                                      | 含多个可选项的 Gzip 拓展。                                                                                  |
+| [I18n](https://github.com/hertz-contrib/i18n)                                                      | 可帮助将 Hertz 程序翻译成多种语言。                                                                             |
+| [Lark](https://github.com/hertz-contrib/lark-hertz)                                                | 在 Hertz 中处理 Lark/飞书的卡片消息和事件的回调。                                                                   |
+| [Loadbalance](https://github.com/hertz-contrib/loadbalance)                                        | 提供适用于 Hertz 的负载均衡算法。                                                                              |
+| [Logger](https://github.com/hertz-contrib/logger)                                                  | Hertz 的日志拓展，提供了对 zap、logrus、zerologs 日志框架的支持。                                                     |
+| [Recovery](https://github.com/cloudwego/hertz/tree/develop/pkg/app/middlewares/server/recovery)    | Hertz 的异常恢复中间件。                                                                                   |
+| [Reverseproxy](https://github.com/hertz-contrib/reverseproxy)                                      | 实现反向代理。                                                                                           |
+| [Swagger](https://github.com/hertz-contrib/swagger)                                                | 使用 Swagger 2.0 自动生成 RESTful API 文档。                                                               |
 
 ## 相关文章
 - [字节跳动在 Go 网络库上的实践](https://www.cloudwego.io/blog/2021/10/09/bytedance-practices-on-go-network-library/)
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/app/client/client.go b/pkg/app/client/client.go
index 99d32a5..3fd2571 100644
--- a/pkg/app/client/client.go
+++ b/pkg/app/client/client.go
@@ -116,7 +116,8 @@ func Do(ctx context.Context, req *protocol.Request, resp *protocol.Response) err
 // Warning: DoTimeout does not terminate the request itself. The request will
 // continue in the background and the response will be discarded.
 // If requests take too long and the connection pool gets filled up please
-// try using a Client and setting a ReadTimeout.
+// try using a customized Client instance with a ReadTimeout config or set the request level read timeout like:
+// `req.SetOptions(config.WithReadTimeout(1 * time.Second))`
 func DoTimeout(ctx context.Context, req *protocol.Request, resp *protocol.Response, timeout time.Duration) error {
 	return defaultClient.DoTimeout(ctx, req, resp, timeout)
 }
@@ -144,6 +145,12 @@ func DoTimeout(ctx context.Context, req *protocol.Request, resp *protocol.Respon
 //
 // It is recommended obtaining req and resp via AcquireRequest
 // and AcquireResponse in performance-critical code.
+//
+// Warning: DoDeadline does not terminate the request itself. The request will
+// continue in the background and the response will be discarded.
+// If requests take too long and the connection pool gets filled up please
+// try using a customized Client instance with a ReadTimeout config or set the request level read timeout like:
+// `req.SetOptions(config.WithReadTimeout(1 * time.Second))`
 func DoDeadline(ctx context.Context, req *protocol.Request, resp *protocol.Response, deadline time.Time) error {
 	return defaultClient.DoDeadline(ctx, req, resp, deadline)
 }
@@ -178,8 +185,9 @@ func DoRedirects(ctx context.Context, req *protocol.Request, resp *protocol.Resp
 // is too small a new slice will be allocated.
 //
 // The function follows redirects. Use Do* for manually handling redirects.
-func Get(ctx context.Context, dst []byte, url string) (statusCode int, body []byte, err error) {
-	return defaultClient.Get(ctx, dst, url)
+//
+func Get(ctx context.Context, dst []byte, url string, requestOptions ...config.RequestOption) (statusCode int, body []byte, err error) {
+	return defaultClient.Get(ctx, dst, url, requestOptions...)
 }
 
 // GetTimeout returns the status code and body of url.
@@ -191,8 +199,14 @@ func Get(ctx context.Context, dst []byte, url string) (statusCode int, body []by
 //
 // errTimeout error is returned if url contents couldn't be fetched
 // during the given timeout.
-func GetTimeout(ctx context.Context, dst []byte, url string, timeout time.Duration) (statusCode int, body []byte, err error) {
-	return defaultClient.GetTimeout(ctx, dst, url, timeout)
+//
+// Warning: GetTimeout does not terminate the request itself. The request will
+// continue in the background and the response will be discarded.
+// If requests take too long and the connection pool gets filled up please
+// try using a customized Client instance with a ReadTimeout config or set the request level read timeout like:
+// `GetTimeout(ctx, dst, url, timeout, config.WithReadTimeout(1 * time.Second))`
+func GetTimeout(ctx context.Context, dst []byte, url string, timeout time.Duration, requestOptions ...config.RequestOption) (statusCode int, body []byte, err error) {
+	return defaultClient.GetTimeout(ctx, dst, url, timeout, requestOptions...)
 }
 
 // GetDeadline returns the status code and body of url.
@@ -204,8 +218,14 @@ func GetTimeout(ctx context.Context, dst []byte, url string, timeout time.Durati
 //
 // errTimeout error is returned if url contents couldn't be fetched
 // until the given deadline.
-func GetDeadline(ctx context.Context, dst []byte, url string, deadline time.Time) (statusCode int, body []byte, err error) {
-	return defaultClient.GetDeadline(ctx, dst, url, deadline)
+//
+// Warning: GetDeadline does not terminate the request itself. The request will
+// continue in the background and the response will be discarded.
+// If requests take too long and the connection pool gets filled up please
+// try using a customized Client instance with a ReadTimeout config or set the request level read timeout like:
+// `GetDeadline(ctx, dst, url, timeout, config.WithReadTimeout(1 * time.Second))`
+func GetDeadline(ctx context.Context, dst []byte, url string, deadline time.Time, requestOptions ...config.RequestOption) (statusCode int, body []byte, err error) {
+	return defaultClient.GetDeadline(ctx, dst, url, deadline, requestOptions...)
 }
 
 // Post sends POST request to the given url with the given POST arguments.
@@ -216,8 +236,8 @@ func GetDeadline(ctx context.Context, dst []byte, url string, deadline time.Time
 // The function follows redirects. Use Do* for manually handling redirects.
 //
 // Empty POST body is sent if postArgs is nil.
-func Post(ctx context.Context, dst []byte, url string, postArgs *protocol.Args) (statusCode int, body []byte, err error) {
-	return defaultClient.Post(ctx, dst, url, postArgs)
+func Post(ctx context.Context, dst []byte, url string, postArgs *protocol.Args, requestOptions ...config.RequestOption) (statusCode int, body []byte, err error) {
+	return defaultClient.Post(ctx, dst, url, postArgs, requestOptions...)
 }
 
 var defaultClient, _ = NewClient(WithDialTimeout(consts.DefaultDialTimeout))
@@ -353,7 +373,8 @@ func (c *Client) Post(ctx context.Context, dst []byte, url string, postArgs *pro
 // Warning: DoTimeout does not terminate the request itself. The request will
 // continue in the background and the response will be discarded.
 // If requests take too long and the connection pool gets filled up please
-// try setting a ReadTimeout.
+// try using a customized Client instance with a ReadTimeout config or set the request level read timeout like:
+// `req.SetOptions(config.WithReadTimeout(1 * time.Second))`
 func (c *Client) DoTimeout(ctx context.Context, req *protocol.Request, resp *protocol.Response, timeout time.Duration) error {
 	return client.DoTimeout(ctx, req, resp, timeout, c)
 }
diff --git a/pkg/app/server/hertz.go b/pkg/app/server/hertz.go
index 651b1ed..72a19c8 100644
--- a/pkg/app/server/hertz.go
+++ b/pkg/app/server/hertz.go
@@ -95,8 +95,13 @@ func (h *Hertz) SetCustomSignalWaiter(f func(err chan error) error) {
 // SIGTERM triggers immediately close.
 // SIGHUP|SIGINT triggers graceful shutdown.
 func waitSignal(errCh chan error) error {
+	signalToNotify := []os.Signal{syscall.SIGINT, syscall.SIGHUP, syscall.SIGTERM}
+	if signal.Ignored(syscall.SIGHUP) {
+		signalToNotify = []os.Signal{syscall.SIGINT, syscall.SIGTERM}
+	}
+
 	signals := make(chan os.Signal, 1)
-	signal.Notify(signals, syscall.SIGINT, syscall.SIGHUP, syscall.SIGTERM)
+	signal.Notify(signals, signalToNotify...)
 
 	select {
 	case sig := <-signals:
@@ -105,6 +110,7 @@ func waitSignal(errCh chan error) error {
 			// force exit
 			return errors.New(sig.String()) // nolint
 		case syscall.SIGHUP, syscall.SIGINT:
+			hlog.SystemLogger().Infof("Received signal: %s\n", sig)
 			// graceful shutdown
 			return nil
 		}
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/client/client.go b/pkg/protocol/client/client.go
index 33d7c39..e770547 100644
--- a/pkg/protocol/client/client.go
+++ b/pkg/protocol/client/client.go
@@ -220,7 +220,9 @@ func doRequestFollowRedirectsBuffer(ctx context.Context, req *protocol.Request,
 
 	statusCode, _, err = DoRequestFollowRedirects(ctx, req, resp, url, defaultMaxRedirectsCount, c)
 
-	body = bodyBuf.B
+	// In HTTP2 scenario, client use stream mode to create a request and its body is in body stream.
+	// In HTTP1, only client recv body exceed max body size and client is in stream mode can trig it.
+	body = resp.Body()
 	bodyBuf.B = oldBody
 	protocol.ReleaseResponse(resp)
 
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
 	}
 
diff --git a/pkg/protocol/http1/server.go b/pkg/protocol/http1/server.go
index 16a65b5..6ff8d7d 100644
--- a/pkg/protocol/http1/server.go
+++ b/pkg/protocol/http1/server.go
@@ -374,6 +374,8 @@ func writeResponse(ctx *app.RequestContext, w network.Writer) error {
 func defaultErrorHandler(ctx *app.RequestContext, err error) {
 	if netErr, ok := err.(*net.OpError); ok && netErr.Timeout() {
 		ctx.AbortWithMsg("Request timeout", consts.StatusRequestTimeout)
+	} else if errors.Is(err, errs.ErrBodyTooLarge) {
+		ctx.AbortWithMsg("Request Entity Too Large", consts.StatusRequestEntityTooLarge)
 	} else {
 		ctx.AbortWithMsg("Error when parsing request", consts.StatusBadRequest)
 	}
diff --git a/pkg/protocol/response.go b/pkg/protocol/response.go
index a170ffd..f46395b 100644
--- a/pkg/protocol/response.go
+++ b/pkg/protocol/response.go
@@ -193,6 +193,13 @@ func (resp *Response) SetBodyStream(bodyStream io.Reader, bodySize int) {
 	resp.Header.SetContentLength(bodySize)
 }
 
+// SetBodyStreamNoReset is almost the same as SetBodyStream,
+// but it doesn't reset the bodyStream before.
+func (resp *Response) SetBodyStreamNoReset(bodyStream io.Reader, bodySize int) {
+	resp.bodyStream = bodyStream
+	resp.Header.SetContentLength(bodySize)
+}
+
 // BodyE returns response body.
 func (resp *Response) BodyE() ([]byte, error) {
 	if resp.bodyStream != nil {
diff --git a/version.go b/version.go
index 006b989..2f877ce 100644
--- a/version.go
+++ b/version.go
@@ -19,5 +19,5 @@ package hertz
 // Name and Version info of this framework, used for statistics and debug
 const (
 	Name    = "Hertz"
-	Version = "v0.4.1"
+	Version = "v0.4.2"
 )


Test patch:
diff --git a/pkg/app/client/client_test.go b/pkg/app/client/client_test.go
index 8c86aff..c754ce5 100644
--- a/pkg/app/client/client_test.go
+++ b/pkg/app/client/client_test.go
@@ -68,6 +68,7 @@ import (
 	"github.com/cloudwego/hertz/pkg/app/client/retry"
 	"github.com/cloudwego/hertz/pkg/common/config"
 	errs "github.com/cloudwego/hertz/pkg/common/errors"
+	"github.com/cloudwego/hertz/pkg/common/test/assert"
 	"github.com/cloudwego/hertz/pkg/network"
 	"github.com/cloudwego/hertz/pkg/network/dialer"
 	"github.com/cloudwego/hertz/pkg/network/netpoll"
@@ -193,6 +194,39 @@ func TestClientGetWithBody(t *testing.T) {
 	}
 }
 
+func TestClientPostBodyStream(t *testing.T) {
+	t.Parallel()
+
+	opt := config.NewOptions([]config.Option{})
+	opt.Addr = "unix-test-10102"
+	opt.Network = "unix"
+	engine := route.NewEngine(opt)
+	engine.POST("/", func(c context.Context, ctx *app.RequestContext) {
+		body := ctx.Request.Body()
+		ctx.Write(body) //nolint:errcheck
+	})
+	go engine.Run()
+	defer func() {
+		engine.Close()
+	}()
+	time.Sleep(time.Millisecond * 500)
+
+	cStream, _ := NewClient(WithDialer(newMockDialerWithCustomFunc(opt.Network, opt.Addr, 1*time.Second, nil)), WithResponseBodyStream(true))
+	args := &protocol.Args{}
+	// There is some data in databuf and others is in bodystream, so we need
+	// to let the data exceed the max bodysize of bodystream
+	v := ""
+	for i := 0; i < 10240; i++ {
+		v += "b"
+	}
+	args.Add("a", v)
+	_, body, err := cStream.Post(context.Background(), nil, "http://example.com", args)
+	if err != nil {
+		t.Fatal(err)
+	}
+	assert.DeepEqual(t, "a="+v, string(body))
+}
+
 func TestClientURLAuth(t *testing.T) {
 	t.Parallel()
 
@@ -450,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() {
@@ -484,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() {
@@ -515,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() {
@@ -1249,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/client/retry/retry_test.go b/pkg/app/client/retry/retry_test.go
new file mode 100644
index 0000000..c77c4f0
--- /dev/null
+++ b/pkg/app/client/retry/retry_test.go
@@ -0,0 +1,87 @@
+/*
+ * 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 retry
+
+import (
+	"math"
+	"testing"
+	"time"
+
+	"github.com/cloudwego/hertz/pkg/common/test/assert"
+)
+
+func TestApply(t *testing.T) {
+	delayPolicyFunc := func(attempts uint, err error, retryConfig *Config) time.Duration {
+		return time.Second
+	}
+	options := []Option{}
+	options = append(options, WithMaxAttemptTimes(100), WithInitDelay(time.Second),
+		WithMaxDelay(time.Second), WithDelayPolicy(delayPolicyFunc), WithMaxJitter(time.Second))
+
+	config := Config{}
+	config.Apply(options)
+
+	assert.DeepEqual(t, uint(100), config.MaxAttemptTimes)
+	assert.DeepEqual(t, time.Second, config.Delay)
+	assert.DeepEqual(t, time.Second, config.MaxDelay)
+	assert.DeepEqual(t, time.Second, Delay(0, nil, &config))
+	assert.DeepEqual(t, time.Second, config.MaxJitter)
+}
+
+func TestPolicy(t *testing.T) {
+	dur := DefaultDelayPolicy(0, nil, nil)
+	assert.DeepEqual(t, 0*time.Millisecond, dur)
+
+	config := Config{
+		Delay: time.Second,
+	}
+	dur = FixedDelayPolicy(0, nil, &config)
+	assert.DeepEqual(t, time.Second, dur)
+
+	dur = RandomDelayPolicy(0, nil, &config)
+	assert.DeepEqual(t, 0*time.Millisecond, dur)
+	config.MaxJitter = time.Second * 1
+	dur = RandomDelayPolicy(0, nil, &config)
+	assert.NotEqual(t, time.Second*1, dur)
+
+	dur = BackOffDelayPolicy(0, nil, &config)
+	assert.DeepEqual(t, time.Second*1, dur)
+	config.Delay = time.Duration(-1)
+	dur = BackOffDelayPolicy(0, nil, &config)
+	assert.DeepEqual(t, time.Second*0, dur)
+	config.Delay = time.Duration(1)
+	dur = BackOffDelayPolicy(63, nil, &config)
+	durExp := config.Delay << 62
+	assert.DeepEqual(t, durExp, dur)
+
+	dur = Delay(0, nil, &config)
+	assert.DeepEqual(t, 0*time.Millisecond, dur)
+	delayPolicyFunc := func(attempts uint, err error, retryConfig *Config) time.Duration {
+		return time.Second
+	}
+	config.DelayPolicy = delayPolicyFunc
+	config.MaxDelay = time.Second / 2
+	dur = Delay(0, nil, &config)
+	assert.DeepEqual(t, config.MaxDelay, dur)
+
+	delayPolicyFunc2 := func(attempts uint, err error, retryConfig *Config) time.Duration {
+		return time.Duration(math.MaxInt64)
+	}
+	delayFunc := CombineDelay(delayPolicyFunc2, delayPolicyFunc)
+	dur = delayFunc(0, nil, &config)
+	assert.DeepEqual(t, time.Duration(math.MaxInt64), dur)
+}
diff --git a/pkg/app/context_test.go b/pkg/app/context_test.go
index 2e55eeb..6ae9443 100644
--- a/pkg/app/context_test.go
+++ b/pkg/app/context_test.go
@@ -21,6 +21,7 @@ import (
 	"errors"
 	"fmt"
 	"io/ioutil"
+	"reflect"
 	"strings"
 	"testing"
 	"time"
@@ -32,7 +33,9 @@ import (
 	"github.com/cloudwego/hertz/pkg/common/test/assert"
 	"github.com/cloudwego/hertz/pkg/common/test/mock"
 	"github.com/cloudwego/hertz/pkg/common/testdata/proto"
+	"github.com/cloudwego/hertz/pkg/common/tracer/traceinfo"
 	"github.com/cloudwego/hertz/pkg/common/utils"
+	"github.com/cloudwego/hertz/pkg/network"
 	"github.com/cloudwego/hertz/pkg/protocol"
 	"github.com/cloudwego/hertz/pkg/protocol/consts"
 	"github.com/cloudwego/hertz/pkg/protocol/http1/req"
@@ -44,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")
 }
@@ -135,6 +138,23 @@ func TestNotFound(t *testing.T) {
 	}
 }
 
+func TestRedirect(t *testing.T) {
+	ctx := NewContext(0)
+	ctx.Redirect(consts.StatusFound, []byte("/hello"))
+	assert.DeepEqual(t, consts.StatusFound, ctx.Response.StatusCode())
+
+	ctx.redirect([]byte("/hello"), consts.StatusMovedPermanently)
+	assert.DeepEqual(t, consts.StatusMovedPermanently, ctx.Response.StatusCode())
+}
+
+func TestGetRedirectStatusCode(t *testing.T) {
+	val := getRedirectStatusCode(consts.StatusMovedPermanently)
+	assert.DeepEqual(t, consts.StatusMovedPermanently, val)
+
+	val = getRedirectStatusCode(consts.StatusNotFound)
+	assert.DeepEqual(t, consts.StatusFound, val)
+}
+
 func TestCookie(t *testing.T) {
 	ctx := NewContext(0)
 	ctx.Request.Header.SetCookie("cookie", "test cookie")
@@ -171,6 +191,15 @@ func TestPost(t *testing.T) {
 	}
 }
 
+func TestGet(t *testing.T) {
+	ctx := NewContext(0)
+	ctx.Request.Header.SetMethod(consts.MethodPost)
+	assert.False(t, ctx.IsGet())
+
+	ctx.Request.Header.SetMethod(consts.MethodGet)
+	assert.True(t, ctx.IsGet())
+}
+
 func TestCopy(t *testing.T) {
 	t.Parallel()
 	ctx := NewContext(0)
@@ -311,6 +340,36 @@ hello=world`)
 	}
 }
 
+func TestDefaultPostForm(t *testing.T) {
+	ctx := makeCtxByReqString(t, `POST /upload HTTP/1.1
+Host: localhost:10000
+Content-Length: 521
+Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryJwfATyF8tmxSJnLg
+
+------WebKitFormBoundaryJwfATyF8tmxSJnLg
+Content-Disposition: form-data; name="f1"
+
+value1
+------WebKitFormBoundaryJwfATyF8tmxSJnLg
+Content-Disposition: form-data; name="fileaaa"; filename="TODO"
+Content-Type: application/octet-stream
+
+- SessionClient with referer and cookies support.
+- Client with requests' pipelining support.
+- ProxyHandler similar to FSHandler.
+- WebSockets. See https://tools.ietf.org/html/rfc6455 .
+- HTTP/2.0. See https://tools.ietf.org/html/rfc7540 .
+
+------WebKitFormBoundaryJwfATyF8tmxSJnLg--
+`)
+
+	val := ctx.DefaultPostForm("f1", "no val")
+	assert.DeepEqual(t, "value1", val)
+
+	val = ctx.DefaultPostForm("f99", "no val")
+	assert.DeepEqual(t, "no val", val)
+}
+
 func TestRequestContext_FormFile(t *testing.T) {
 	t.Parallel()
 
@@ -445,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),
@@ -497,6 +556,17 @@ func TestRequestContext_Handler(t *testing.T) {
 	}
 }
 
+func TestRequestContext_Handlers(t *testing.T) {
+	c := NewContext(0)
+	hc := HandlersChain{testFunc, testFunc2}
+	c.SetHandlers(hc)
+	c.Handlers()[1](context.Background(), c)
+	val := c.GetString("key")
+	if val != "123" {
+		t.Fatalf("unexpected %v. Expecting %v", val, "123")
+	}
+}
+
 func TestRequestContext_HandlerName(t *testing.T) {
 	c := NewContext(0)
 	c.handlers = HandlersChain{testFunc, testFunc2}
@@ -617,6 +687,14 @@ func TestClientIp(t *testing.T) {
 	}
 }
 
+func TestSetClientIPFunc(t *testing.T) {
+	fn := func(ctx *RequestContext) string {
+		return ""
+	}
+	SetClientIPFunc(fn)
+	assert.DeepEqual(t, reflect.ValueOf(fn).Pointer(), reflect.ValueOf(defaultClientIP).Pointer())
+}
+
 func TestGetQuery(t *testing.T) {
 	c := NewContext(0)
 	c.Request.SetRequestURI("http://aaa.com?a=1&b=")
@@ -906,6 +984,131 @@ func TestContextGetStringMapStringSlice(t *testing.T) {
 	assert.DeepEqual(t, expected, c.GetStringMapStringSlice("string"))
 }
 
+func TestContextTraceInfo(t *testing.T) {
+	ctx := NewContext(0)
+	traceIn := traceinfo.NewTraceInfo()
+	ctx.SetTraceInfo(traceIn)
+	traceOut := ctx.GetTraceInfo()
+
+	assert.DeepEqual(t, traceIn, traceOut)
+}
+
+func TestEnableTrace(t *testing.T) {
+	ctx := NewContext(0)
+	ctx.SetEnableTrace(true)
+	trace := ctx.IsEnableTrace()
+	assert.True(t, trace)
+}
+
+func TestForEachKey(t *testing.T) {
+	ctx := NewContext(0)
+	ctx.Set("1", "2")
+	handle := func(k string, v interface{}) {
+		res := k + v.(string)
+		assert.DeepEqual(t, res, "12")
+	}
+	ctx.ForEachKey(handle)
+	val, ok := ctx.Get("1")
+	assert.DeepEqual(t, val, "2")
+	assert.True(t, ok)
+}
+
+func TestHijackHandler(t *testing.T) {
+	ctx := NewContext(0)
+	handle := func(c network.Conn) {
+		c.SetReadTimeout(time.Duration(1) * time.Second)
+	}
+	ctx.SetHijackHandler(handle)
+	handleRes := ctx.GetHijackHandler()
+
+	val1 := reflect.ValueOf(handle).Pointer()
+	val2 := reflect.ValueOf(handleRes).Pointer()
+	assert.DeepEqual(t, val1, val2)
+}
+
+func TestIndex(t *testing.T) {
+	ctx := NewContext(0)
+	ctx.ResetWithoutConn()
+	res := ctx.GetIndex()
+	exc := int8(-1)
+	assert.DeepEqual(t, exc, res)
+}
+
+func TestHandlerName(t *testing.T) {
+	h := func(c context.Context, ctx *RequestContext) {}
+	SetHandlerName(h, "test")
+	name := GetHandlerName(h)
+	assert.DeepEqual(t, "test", name)
+}
+
+func TestHijack(t *testing.T) {
+	ctx := NewContext(0)
+	h := func(c network.Conn) {}
+	ctx.Hijack(h)
+	assert.True(t, ctx.Hijacked())
+}
+
+func TestFinished(t *testing.T) {
+	ctx := NewContext(0)
+	ctx.Finished()
+
+	ch := make(chan struct{})
+	ctx.finished = ch
+	chRes := ctx.Finished()
+
+	send := func() {
+		time.Sleep(time.Duration(1) * time.Millisecond)
+		ch <- struct{}{}
+	}
+	go send()
+	val := <-chRes
+	assert.DeepEqual(t, struct{}{}, val)
+}
+
+func TestString(t *testing.T) {
+	ctx := NewContext(0)
+	ctx.String(consts.StatusOK, "ok")
+	assert.DeepEqual(t, consts.StatusOK, ctx.Response.StatusCode())
+}
+
+func TestFullPath(t *testing.T) {
+	ctx := NewContext(0)
+	str := "/hello"
+	ctx.SetFullPath(str)
+	val := ctx.FullPath()
+	assert.DeepEqual(t, str, val)
+}
+
+func TestReset(t *testing.T) {
+	ctx := NewContext(0)
+	ctx.Reset()
+	assert.DeepEqual(t, nil, ctx.conn)
+}
+
+// func TestParam(t *testing.T) {
+// 	ctx := NewContext(0)
+// 	val := ctx.Param("/user/john")
+// 	assert.DeepEqual(t, "john", val)
+// }
+
+func TestGetHeader(t *testing.T) {
+	ctx := NewContext(0)
+	ctx.Request.Header.SetContentTypeBytes([]byte("text/plain; charset=utf-8"))
+	val := ctx.GetHeader("Content-Type")
+	assert.DeepEqual(t, "text/plain; charset=utf-8", string(val))
+}
+
+func TestGetRawData(t *testing.T) {
+	ctx := NewContext(0)
+	ctx.Request.SetBody([]byte("hello"))
+	val := ctx.GetRawData()
+	assert.DeepEqual(t, "hello", string(val))
+
+	val2, err := ctx.Body()
+	assert.DeepEqual(t, val, val2)
+	assert.Nil(t, err)
+}
+
 func TestRequestContext_GetRequest(t *testing.T) {
 	c := &RequestContext{}
 	c.Request.Header.Set("key1", "value1")
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 80ddc0c..31206b0 100644
--- a/pkg/app/server/hertz_test.go
+++ b/pkg/app/server/hertz_test.go
@@ -23,6 +23,7 @@ import (
 	"fmt"
 	"html/template"
 	"io"
+	"io/ioutil"
 	"net"
 	"net/http"
 	"os"
@@ -217,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]))
@@ -239,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]))
@@ -282,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))
@@ -322,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"
@@ -333,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())
 }
 
@@ -354,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"
@@ -365,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())
 }
 
@@ -379,8 +380,11 @@ func TestNotEnoughBodySize(t *testing.T) {
 	r.ParseForm()
 	r.Form.Add("xxxxxx", "xxx")
 	body := strings.NewReader(r.Form.Encode())
-	resp, _ := http.Post("http://127.0.0.1:8889/test", "application/x-www-form-urlencoded", body)
-	assert.DeepEqual(t, 400, resp.StatusCode)
+	resp, err := http.Post("http://127.0.0.1:8889/test", "application/x-www-form-urlencoded", body)
+	assert.Nil(t, err)
+	assert.DeepEqual(t, 413, resp.StatusCode)
+	bodyBytes, _ := ioutil.ReadAll(resp.Body)
+	assert.DeepEqual(t, "Request Entity Too Large", string(bodyBytes))
 }
 
 func TestEnoughBodySize(t *testing.T) {
@@ -394,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) {
@@ -587,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()
@@ -608,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/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 7195eec..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,34 @@ 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)
 }
+
+type closeBuffer struct {
+	*bytes.Buffer
+}
+
+func (b *closeBuffer) Close() error {
+	b.Reset()
+	return nil
+}
+
+func TestSetBodyStreamNoReset(t *testing.T) {
+	t.Parallel()
+	resp := Response{}
+	bsA := &closeBuffer{bytes.NewBufferString("A")}
+	bsB := &closeBuffer{bytes.NewBufferString("B")}
+	bsC := &closeBuffer{bytes.NewBufferString("C")}
+
+	resp.SetBodyStream(bsA, 1)
+	resp.SetBodyStreamNoReset(bsB, 1)
+	// resp.Body() has closed bsB
+	assert.DeepEqual(t, string(resp.Body()), "B")
+	assert.DeepEqual(t, bsA.String(), "A")
+
+	resp.bodyStream = bsA
+	resp.SetBodyStream(bsC, 1)
+	assert.DeepEqual(t, bsA.String(), "")
+}
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) {