Repository: zeromicro/go-zero
Pull request #1356 (2021-12-21 08:42:51)

go-zero tools ,fix a func,api new can not choose style
add a option for api new

goctl api new  utils.api -style go_zero




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/timeouthandler.go b/rest/handler/timeouthandler.go
index 0e81c161..1b9532cf 100644
--- a/rest/handler/timeouthandler.go
+++ b/rest/handler/timeouthandler.go
@@ -89,6 +89,8 @@ func (h *timeoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	case <-ctx.Done():
 		tw.mu.Lock()
 		defer tw.mu.Unlock()
+		// there isn't any user-defined middleware before TimoutHandler,
+		// so we can guarantee that cancelation in biz related code won't come here.
 		if errors.Is(ctx.Err(), context.Canceled) {
 			w.WriteHeader(statusClientClosedRequest)
 		} else {
diff --git a/rest/httpx/requests.go b/rest/httpx/requests.go
index 238efa24..170e31c9 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         = ";"
@@ -106,14 +105,12 @@ func ParseHeader(headerValue string) map[string]string {
 
 // ParseJsonBody parses the post request which contains json in body.
 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)
+		reader := io.LimitReader(r.Body, maxBodyLen)
+		return mapping.UnmarshalJsonReader(reader, v)
 	}
 
-	return mapping.UnmarshalJsonReader(reader, v)
+	return mapping.UnmarshalJsonMap(nil, 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..4ed4237a 100644
--- a/rest/internal/security/contentsecurity.go
+++ b/rest/internal/security/contentsecurity.go
@@ -119,16 +119,13 @@ func VerifySignature(r *http.Request, securityHeader *ContentSecurityHeader, tol
 	}, "\n")
 	actualSignature := codec.HmacBase64(securityHeader.Key, signContent)
 
-	passed := securityHeader.Signature == actualSignature
-	if !passed {
-		logx.Infof("signature different, expect: %s, actual: %s",
-			securityHeader.Signature, actualSignature)
-	}
-
-	if passed {
+	if securityHeader.Signature == actualSignature {
 		return httpx.CodeSignaturePass
 	}
 
+	logx.Infof("signature different, expect: %s, actual: %s",
+		securityHeader.Signature, actualSignature)
+
 	return httpx.CodeSignatureInvalidToken
 }
 
diff --git a/tools/goctl/api/new/newservice.go b/tools/goctl/api/new/newservice.go
index cc5fc1b3..7ea373cf 100644
--- a/tools/goctl/api/new/newservice.go
+++ b/tools/goctl/api/new/newservice.go
@@ -36,6 +36,10 @@ func CreateServiceCommand(c *cli.Context) error {
 		dirName = "greet"
 	}
 
+	dirStyle := c.String("style")
+	if len(dirStyle) == 0 {
+		dirStyle = conf.DefaultFormat
+	}
 	if strings.Contains(dirName, "-") {
 		return errors.New("api new command service name not support strikethrough, because this will used by function name")
 	}
@@ -78,6 +82,6 @@ func CreateServiceCommand(c *cli.Context) error {
 		return err
 	}
 
-	err = gogen.DoGenProject(apiFilePath, abs, conf.DefaultFormat)
+	err = gogen.DoGenProject(apiFilePath, abs, dirStyle)
 	return err
 }
diff --git a/tools/goctl/bug/env.go b/tools/goctl/bug/env.go
index 6f954520..da66e8bd 100644
--- a/tools/goctl/bug/env.go
+++ b/tools/goctl/bug/env.go
@@ -21,7 +21,7 @@ func (e env) string() string {
 		w.WriteString(fmt.Sprintf("%s = %q\n", k, v))
 	}
 
-	return strings.TrimSuffix(w.String(),"\n")
+	return strings.TrimSuffix(w.String(), "\n")
 }
 
 func getEnv() env {
diff --git a/tools/goctl/bug/issue.go b/tools/goctl/bug/issue.go
index c3cd0981..0c623aad 100644
--- a/tools/goctl/bug/issue.go
+++ b/tools/goctl/bug/issue.go
@@ -1,6 +1,6 @@
 package bug
 
-const issueTemplate=`
+const issueTemplate = `
 <!-- Please answer these questions before submitting your issue. Thanks! -->
 
 ### What category of issue (<code>goctl</code> or <code>sdk</code>)?
diff --git a/tools/goctl/goctl.go b/tools/goctl/goctl.go
index 9f4dda49..fc14a334 100644
--- a/tools/goctl/goctl.go
+++ b/tools/goctl/goctl.go
@@ -69,6 +69,10 @@ var commands = []cli.Command{
 						Name:  "home",
 						Usage: "the goctl home path of the template",
 					},
+					cli.StringFlag{
+						Name:  "style",
+						Usage: "the file naming format, see [https://github.com/zeromicro/go-zero/blob/master/tools/goctl/config/readme.md]",
+					},
 				},
 			},
 			{


Test patch:
diff --git a/core/mapping/jsonunmarshaler_test.go b/core/mapping/jsonunmarshaler_test.go
index c98244c7..ccaf6b6c 100644
--- a/core/mapping/jsonunmarshaler_test.go
+++ b/core/mapping/jsonunmarshaler_test.go
@@ -871,3 +871,50 @@ func TestUnmarshalReaderError(t *testing.T) {
 	assert.NotNil(t, err)
 	assert.True(t, strings.Contains(err.Error(), payload))
 }
+
+func TestUnmarshalMap(t *testing.T) {
+	t.Run("nil map and valid", func(t *testing.T) {
+		var m map[string]interface{}
+		var v struct {
+			Any string `json:",optional"`
+		}
+
+		err := UnmarshalJsonMap(m, &v)
+		assert.Nil(t, err)
+		assert.True(t, len(v.Any) == 0)
+	})
+
+	t.Run("empty map but not valid", func(t *testing.T) {
+		m := map[string]interface{}{}
+		var v struct {
+			Any string
+		}
+
+		err := UnmarshalJsonMap(m, &v)
+		assert.NotNil(t, err)
+	})
+
+	t.Run("empty map and valid", func(t *testing.T) {
+		m := map[string]interface{}{}
+		var v struct {
+			Any string `json:",optional"`
+		}
+
+		err := UnmarshalJsonMap(m, &v)
+		assert.Nil(t, err)
+		assert.True(t, len(v.Any) == 0)
+	})
+
+	t.Run("valid map", func(t *testing.T) {
+		m := map[string]interface{}{
+			"Any": "foo",
+		}
+		var v struct {
+			Any string
+		}
+
+		err := UnmarshalJsonMap(m, &v)
+		assert.Nil(t, err)
+		assert.Equal(t, "foo", v.Any)
+	})
+}
diff --git a/rest/httpx/requests_test.go b/rest/httpx/requests_test.go
index 15c2cbeb..7e40fb94 100644
--- a/rest/httpx/requests_test.go
+++ b/rest/httpx/requests_test.go
@@ -196,18 +196,32 @@ Content-Disposition: form-data; name="age"
 }
 
 func TestParseJsonBody(t *testing.T) {
-	var v struct {
-		Name string `json:"name"`
-		Age  int    `json:"age"`
-	}
+	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)
+		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)
+		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)
+	})
 }
 
 func TestParseRequired(t *testing.T) {