Repository: cloudwego/hertz
Pull request #1037 (2023-12-25 15:16:15)

optimize: filter shortConnErr in tracer
#### What type of PR is this?
optimize
<!--
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.
- [x] Attach the PR updating the user documentation if the current PR requires user awareness at the usage level. [User docs repo](https://github.com/cloudwego/cloudwego.github.io)


#### (Optional) Translate the PR title into Chinese.
- 在 trace 中过滤 shortConnErr 错误

#### (Optional) More detailed description for this PR(en: English/zh: Chinese).
<!--
Provide more detailed info for review(e.g., it's recommended to provide perf data if this is a perf type PR).
-->
en:
zh(optional):

#### (Optional) Which issue(s) this PR fixes:
<!--
Automatically closes linked issue when PR is merged.
Eg: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
-->

#### (Optional) The PR that updates user documentation:
<!--
If the current PR requires user awareness at the usage level, please submit a PR to update user docs. [User docs repo](https://github.com/cloudwego/cloudwego.github.io)
-->

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/cloudwego/hertz/pull/1037?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego) Report
Attention: `4 lines` in your changes are missing coverage. Please review.
> Comparison is base [(`82f9bfa`)](https://app.codecov.io/gh/cloudwego/hertz/commit/82f9bfa7e68d6fd724a39350f3b517ec68ab54fc?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego) 82.55% compared to head [(`44db515`)](https://app.codecov.io/gh/cloudwego/hertz/pull/1037?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego) 82.51%.

| [Files](https://app.codecov.io/gh/cloudwego/hertz/pull/1037?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego) | Patch % | Lines |
|---|---|---|
| [pkg/protocol/http1/server.go](https://app.codecov.io/gh/cloudwego/hertz/pull/1037?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego#diff-cGtnL3Byb3RvY29sL2h0dHAxL3NlcnZlci5nbw==) | 50.00% | [4 Missing :warning: ](https://app.codecov.io/gh/cloudwego/hertz/pull/1037?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego) |

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


```diff
@@             Coverage Diff             @@
##           develop    #1037      +/-   ##
===========================================
- Coverage    82.55%   82.51%   -0.05%     
===========================================
  Files           98       98              
  Lines         9974     9978       +4     
===========================================
- Hits          8234     8233       -1     
- Misses        1244     1250       +6     
+ Partials       496      495       -1     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/cloudwego/hertz/pull/1037?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudwego).   
:loudspeaker: Have feedback on the report? [Share it here](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/cmd/hz/meta/const.go b/cmd/hz/meta/const.go
index dfeafd2..7441eab 100644
--- a/cmd/hz/meta/const.go
+++ b/cmd/hz/meta/const.go
@@ -19,7 +19,7 @@ package meta
 import "runtime"
 
 // Version hz version
-const Version = "v0.8.0"
+const Version = "v0.8.1"
 
 const DefaultServiceName = "hertz_service"
 
diff --git a/pkg/app/context.go b/pkg/app/context.go
index 91b5e0d..9117e3b 100644
--- a/pkg/app/context.go
+++ b/pkg/app/context.go
@@ -1458,7 +1458,7 @@ func (ctx *RequestContext) BindByContentType(obj interface{}) error {
 		return ctx.BindQuery(obj)
 	}
 	ct := utils.FilterContentType(bytesconv.B2s(ctx.Request.Header.ContentType()))
-	switch ct {
+	switch strings.ToLower(ct) {
 	case consts.MIMEApplicationJSON:
 		return ctx.BindJSON(obj)
 	case consts.MIMEPROTOBUF:
diff --git a/pkg/app/server/binding/default.go b/pkg/app/server/binding/default.go
index 0634f26..7e09ac9 100644
--- a/pkg/app/server/binding/default.go
+++ b/pkg/app/server/binding/default.go
@@ -67,6 +67,7 @@ import (
 	"io"
 	"net/url"
 	"reflect"
+	"strings"
 	"sync"
 
 	exprValidator "github.com/bytedance/go-tagexpr/v2/validator"
@@ -175,9 +176,11 @@ func (b *defaultBinder) bindTag(req *protocol.Request, v interface{}, params par
 		return b.bindNonStruct(req, v)
 	}
 
-	err := b.preBindBody(req, v)
-	if err != nil {
-		return fmt.Errorf("bind body failed, err=%v", err)
+	if len(tag) == 0 {
+		err := b.preBindBody(req, v)
+		if err != nil {
+			return fmt.Errorf("bind body failed, err=%v", err)
+		}
 	}
 	cache := b.tagCache(tag)
 	cached, ok := cache.Load(typeID)
@@ -323,7 +326,7 @@ func (b *defaultBinder) preBindBody(req *protocol.Request, v interface{}) error
 		return nil
 	}
 	ct := bytesconv.B2s(req.Header.ContentType())
-	switch utils.FilterContentType(ct) {
+	switch strings.ToLower(utils.FilterContentType(ct)) {
 	case consts.MIMEApplicationJSON:
 		return hJson.Unmarshal(req.Body(), v)
 	case consts.MIMEPROTOBUF:
@@ -339,7 +342,7 @@ func (b *defaultBinder) preBindBody(req *protocol.Request, v interface{}) error
 
 func (b *defaultBinder) bindNonStruct(req *protocol.Request, v interface{}) (err error) {
 	ct := bytesconv.B2s(req.Header.ContentType())
-	switch utils.FilterContentType(ct) {
+	switch strings.ToLower(utils.FilterContentType(ct)) {
 	case consts.MIMEApplicationJSON:
 		err = hJson.Unmarshal(req.Body(), v)
 	case consts.MIMEPROTOBUF:
diff --git a/pkg/app/server/binding/internal/decoder/gjson_required.go b/pkg/app/server/binding/internal/decoder/gjson_required.go
index 88697e0..95e3c4f 100644
--- a/pkg/app/server/binding/internal/decoder/gjson_required.go
+++ b/pkg/app/server/binding/internal/decoder/gjson_required.go
@@ -33,7 +33,7 @@ func checkRequireJSON(req *protocol.Request, tagInfo TagInfo) bool {
 		return true
 	}
 	ct := bytesconv.B2s(req.Header.ContentType())
-	if utils.FilterContentType(ct) != consts.MIMEApplicationJSON {
+	if !strings.EqualFold(utils.FilterContentType(ct), consts.MIMEApplicationJSON) {
 		return false
 	}
 	result := gjson.GetBytes(req.Body(), tagInfo.JSONName)
diff --git a/pkg/app/server/binding/internal/decoder/sonic_required.go b/pkg/app/server/binding/internal/decoder/sonic_required.go
index 2aae0c3..e408901 100644
--- a/pkg/app/server/binding/internal/decoder/sonic_required.go
+++ b/pkg/app/server/binding/internal/decoder/sonic_required.go
@@ -35,7 +35,7 @@ func checkRequireJSON(req *protocol.Request, tagInfo TagInfo) bool {
 		return true
 	}
 	ct := bytesconv.B2s(req.Header.ContentType())
-	if utils.FilterContentType(ct) != consts.MIMEApplicationJSON {
+	if !strings.EqualFold(utils.FilterContentType(ct), consts.MIMEApplicationJSON) {
 		return false
 	}
 	node, _ := sonic.Get(req.Body(), stringSliceForInterface(tagInfo.JSONName)...)
diff --git a/pkg/protocol/http1/server.go b/pkg/protocol/http1/server.go
index a5d33f1..535d1d5 100644
--- a/pkg/protocol/http1/server.go
+++ b/pkg/protocol/http1/server.go
@@ -114,9 +114,6 @@ func (s Server) Serve(c context.Context, conn network.Conn) (err error) {
 
 	defer func() {
 		if s.EnableTrace {
-			if shouldRecordInTraceError(err) {
-				ctx.GetTraceInfo().Stats().SetError(err)
-			}
 			// in case of error, we need to trigger all events
 			if eventsToTrigger != nil {
 				for last := eventsToTrigger.pop(); last != nil; last = eventsToTrigger.pop() {
@@ -124,8 +121,11 @@ func (s Server) Serve(c context.Context, conn network.Conn) (err error) {
 				}
 				s.eventStackPool.Put(eventsToTrigger)
 			}
-
-			traceCtl.DoFinish(cc, ctx, err)
+			if shouldRecordInTraceError(err) {
+				traceCtl.DoFinish(cc, ctx, err)
+			} else {
+				traceCtl.DoFinish(cc, ctx, nil)
+			}
 		}
 
 		// Hijack may release and close the connection already
@@ -384,7 +384,11 @@ func (s Server) Serve(c context.Context, conn network.Conn) (err error) {
 		}
 		// general case
 		if s.EnableTrace {
-			traceCtl.DoFinish(cc, ctx, err)
+			if shouldRecordInTraceError(err) {
+				traceCtl.DoFinish(cc, ctx, err)
+			} else {
+				traceCtl.DoFinish(cc, ctx, nil)
+			}
 		}
 
 		ctx.ResetWithoutConn()
diff --git a/version.go b/version.go
index b6c0efd..b23641e 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.8.0"
+	Version = "v0.8.1"
 )


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 0325bef..e16ee73 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -81,7 +81,7 @@ jobs:
 
       - name: Get changed files
         id: changed-files
-        uses: tj-actions/changed-files@v35
+        uses: tj-actions/changed-files@v41
 
       - name: Hz Test
         if: contains(steps.changed-files.outputs.all_changed_files, 'cmd/hz')
@@ -105,7 +105,7 @@ jobs:
 
       - name: Get changed files
         id: changed-files
-        uses: tj-actions/changed-files@v35
+        uses: tj-actions/changed-files@v41
 
       - name: Install Protobuf
         shell: pwsh
diff --git a/pkg/app/server/binding/binder_test.go b/pkg/app/server/binding/binder_test.go
index 9071dbc..7919d8d 100644
--- a/pkg/app/server/binding/binder_test.go
+++ b/pkg/app/server/binding/binder_test.go
@@ -1549,6 +1549,48 @@ func TestBind_Issue1015(t *testing.T) {
 	assert.DeepEqual(t, "asd", result.A)
 }
 
+func TestBind_WithoutPreBindForTag(t *testing.T) {
+	type BaseQuery struct {
+		Action  string `query:"Action" binding:"required"`
+		Version string `query:"Version" binding:"required"`
+	}
+
+	req := newMockRequest().
+		SetJSONContentType().
+		SetRequestURI("http://foobar.com/?Action=action&Version=version").
+		SetBody([]byte(``))
+
+	var result BaseQuery
+
+	err := DefaultBinder().BindQuery(req.Req, &result)
+	if err != nil {
+		t.Error(err)
+	}
+	assert.DeepEqual(t, "action", result.Action)
+	assert.DeepEqual(t, "version", result.Version)
+}
+
+func TestBind_NormalizeContentType(t *testing.T) {
+	type BaseQuery struct {
+		Action  string `json:"action" binding:"required"`
+		Version string `json:"version" binding:"required"`
+	}
+
+	req := newMockRequest().
+		SetHeader("Content-Type", "ApplicAtion/json").
+		SetRequestURI("http://foobar.com/?Action=action&Version=version").
+		SetBody([]byte(`{"action":"action", "version":"version"}`))
+
+	var result BaseQuery
+
+	err := DefaultBinder().BindQuery(req.Req, &result)
+	if err != nil {
+		t.Error(err)
+	}
+	assert.DeepEqual(t, "action", result.Action)
+	assert.DeepEqual(t, "version", result.Version)
+}
+
 func Benchmark_Binding(b *testing.B) {
 	type Req struct {
 		Version string `path:"v"`
diff --git a/pkg/protocol/http1/server_test.go b/pkg/protocol/http1/server_test.go
index dc8790a..2263ece 100644
--- a/pkg/protocol/http1/server_test.go
+++ b/pkg/protocol/http1/server_test.go
@@ -70,6 +70,7 @@ func TestTraceEventCompleted(t *testing.T) {
 	assert.False(t, traceInfo.Stats().GetEvent(stats.WriteStart).IsNil())
 	assert.False(t, traceInfo.Stats().GetEvent(stats.WriteFinish).IsNil())
 	assert.False(t, traceInfo.Stats().GetEvent(stats.HTTPFinish).IsNil())
+	assert.Nil(t, traceInfo.Stats().Error())
 }
 
 func TestTraceEventReadHeaderError(t *testing.T) {