Repository: zeromicro/go-zero
Pull request #1353 (2021-12-21 01:04:37)

chore: optimize `ParseJsonBody`


Patch:
diff --git a/core/mapping/jsonunmarshaler.go b/core/mapping/jsonunmarshaler.go
index 523a8ca2..7dfeb653 100644
--- a/core/mapping/jsonunmarshaler.go
+++ b/core/mapping/jsonunmarshaler.go
@@ -15,6 +15,11 @@ func UnmarshalJsonBytes(content []byte, v interface{}) error {
 	return unmarshalJsonBytes(content, v, jsonUnmarshaler)
 }
 
+// UnmarshalJsonMap unmarshals content from m into v.
+func UnmarshalJsonMap(m map[string]interface{}, v interface{}) error {
+	return jsonUnmarshaler.Unmarshal(m, v)
+}
+
 // UnmarshalJsonReader unmarshals content from reader into v.
 func UnmarshalJsonReader(reader io.Reader, v interface{}) error {
 	return unmarshalJsonReader(reader, v, jsonUnmarshaler)
diff --git a/rest/handler/loghandler.go b/rest/handler/loghandler.go
index 57d147b8..3e336b54 100644
--- a/rest/handler/loghandler.go
+++ b/rest/handler/loghandler.go
@@ -196,12 +196,13 @@ func logDetails(r *http.Request, response *detailLoggedResponseWriter, timer *ut
 	logs *internal.LogCollector) {
 	var buf bytes.Buffer
 	duration := timer.Duration()
+	code := response.writer.code
 	logger := logx.WithContext(r.Context())
 	buf.WriteString(fmt.Sprintf("[HTTP] %s - %d - %s - %s\n=> %s\n",
-		r.Method, response.writer.code, r.RemoteAddr, timex.ReprOfDuration(duration), dumpRequest(r)))
+		r.Method, code, r.RemoteAddr, timex.ReprOfDuration(duration), dumpRequest(r)))
 	if duration > defaultSlowThreshold {
 		logger.Slowf("[HTTP] %s - %d - %s - slowcall(%s)\n=> %s\n",
-			r.Method, response.writer.code, r.RemoteAddr, timex.ReprOfDuration(duration), dumpRequest(r))
+			r.Method, code, r.RemoteAddr, timex.ReprOfDuration(duration), dumpRequest(r))
 	}
 
 	body := logs.Flush()
@@ -214,7 +215,11 @@ func logDetails(r *http.Request, response *detailLoggedResponseWriter, timer *ut
 		buf.WriteString(fmt.Sprintf("<= %s", respBuf))
 	}
 
-	logger.Info(buf.String())
+	if isOkResponse(code) {
+		logger.Info(buf.String())
+	} else {
+		logger.Error(buf.String())
+	}
 }
 
 func isOkResponse(code int) bool {
diff --git a/rest/httpx/requests.go b/rest/httpx/requests.go
index 238efa24..2609030d 100644
--- a/rest/httpx/requests.go
+++ b/rest/httpx/requests.go
@@ -14,7 +14,6 @@ const (
 	formKey           = "form"
 	pathKey           = "path"
 	headerKey         = "header"
-	emptyJson         = "{}"
 	maxMemory         = 32 << 20 // 32MB
 	maxBodyLen        = 8 << 20  // 8MB
 	separator         = ";"
@@ -26,6 +25,8 @@ var (
 	pathUnmarshaler   = mapping.NewUnmarshaler(pathKey, mapping.WithStringValues())
 	headerUnmarshaler = mapping.NewUnmarshaler(headerKey, mapping.WithStringValues(),
 		mapping.WithCanonicalKeyFunc(textproto.CanonicalMIMEHeaderKey))
+
+	emptyMap = map[string]interface{}{}
 )
 
 // Parse parses the request.
@@ -109,11 +110,10 @@ func ParseJsonBody(r *http.Request, v interface{}) error {
 	var reader io.Reader
 	if withJsonBody(r) {
 		reader = io.LimitReader(r.Body, maxBodyLen)
-	} else {
-		reader = strings.NewReader(emptyJson)
+		return mapping.UnmarshalJsonReader(reader, v)
 	}
 
-	return mapping.UnmarshalJsonReader(reader, v)
+	return mapping.UnmarshalJsonMap(emptyMap, v)
 }
 
 // ParsePath parses the symbols reside in url path.
diff --git a/rest/internal/security/contentsecurity.go b/rest/internal/security/contentsecurity.go
index 89710d7b..ec66f04c 100644
--- a/rest/internal/security/contentsecurity.go
+++ b/rest/internal/security/contentsecurity.go
@@ -119,7 +119,7 @@ func VerifySignature(r *http.Request, securityHeader *ContentSecurityHeader, tol
 	}, "\n")
 	actualSignature := codec.HmacBase64(securityHeader.Key, signContent)
 
-	passed := securityHeader.Signature == actualSignature
+	/*passed := securityHeader.Signature == actualSignature
 	if !passed {
 		logx.Infof("signature different, expect: %s, actual: %s",
 			securityHeader.Signature, actualSignature)
@@ -127,7 +127,12 @@ func VerifySignature(r *http.Request, securityHeader *ContentSecurityHeader, tol
 
 	if passed {
 		return httpx.CodeSignaturePass
+	}*/
+	if securityHeader.Signature == actualSignature {
+		return httpx.CodeSignaturePass
 	}
+	logx.Infof("signature different, expect: %s, actual: %s",
+		securityHeader.Signature, actualSignature)
 
 	return httpx.CodeSignatureInvalidToken
 }


Test patch:
diff --git a/rest/httpx/requests_test.go b/rest/httpx/requests_test.go
index 15c2cbeb..76cbe346 100644
--- a/rest/httpx/requests_test.go
+++ b/rest/httpx/requests_test.go
@@ -196,18 +196,38 @@ Content-Disposition: form-data; name="age"
 }
 
 func TestParseJsonBody(t *testing.T) {
-	var v struct {
-		Name string `json:"name"`
-		Age  int    `json:"age"`
-	}
 
-	body := `{"name":"kevin", "age": 18}`
-	r := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(body))
-	r.Header.Set(ContentType, ApplicationJson)
+	t.Run("has body", func(t *testing.T) {
+
+		var v struct {
+			Name string `json:"name"`
+			Age  int    `json:"age"`
+		}
+
+		body := `{"name":"kevin", "age": 18}`
+		r := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(body))
+		r.Header.Set(ContentType, ApplicationJson)
+
+		assert.Nil(t, Parse(r, &v))
+		assert.Equal(t, "kevin", v.Name)
+		assert.Equal(t, 18, v.Age)
+
+	})
+
+	t.Run("hasn't body", func(t *testing.T) {
+
+		var v struct {
+			Name string `json:"name,optional"`
+			Age  int    `json:"age,optional"`
+		}
+
+		r := httptest.NewRequest(http.MethodGet, "/", nil)
+		assert.Nil(t, Parse(r, &v))
+		assert.Equal(t, "", v.Name)
+		assert.Equal(t, 0, v.Age)
+
+	})
 
-	assert.Nil(t, Parse(r, &v))
-	assert.Equal(t, "kevin", v.Name)
-	assert.Equal(t, 18, v.Age)
 }
 
 func TestParseRequired(t *testing.T) {