From 99f0fb14a102a00736798607fdf355e21ea30711 Mon Sep 17 00:00:00 2001 From: Wlynxg Date: Wed, 22 Jan 2025 09:28:06 +0800 Subject: [PATCH 1/4] fix(net/ghttp): BufferWriter.Flush writes additional information after custom response wrote (#4116) --- net/ghttp/ghttp_z_unit_issue_test.go | 22 +++++++++++++++++++ .../response/response_buffer_writer.go | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/net/ghttp/ghttp_z_unit_issue_test.go b/net/ghttp/ghttp_z_unit_issue_test.go index e14a38eed46..f8b2069e2ec 100644 --- a/net/ghttp/ghttp_z_unit_issue_test.go +++ b/net/ghttp/ghttp_z_unit_issue_test.go @@ -656,3 +656,25 @@ func Test_Issue4108(t *testing.T) { t.Assert(rsp.ReadAllString(), "hello") }) } + +// https://github.com/gogf/gf/issues/4115 +func Test_Issue4115(t *testing.T) { + s := g.Server(guid.S()) + s.Use(func(r *ghttp.Request) { + r.Response.Writer.Write([]byte("hello")) + }) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + time.Sleep(100 * time.Millisecond) + + gtest.C(t, func(t *gtest.T) { + client := g.Client() + client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) + + rsp, err := client.Get(ctx, "/") + t.AssertNil(err) + t.Assert(rsp.StatusCode, http.StatusOK) + t.Assert(rsp.ReadAllString(), "hello") + }) +} diff --git a/net/ghttp/internal/response/response_buffer_writer.go b/net/ghttp/internal/response/response_buffer_writer.go index f1f65c88e19..8b334d79049 100644 --- a/net/ghttp/internal/response/response_buffer_writer.go +++ b/net/ghttp/internal/response/response_buffer_writer.go @@ -82,7 +82,7 @@ func (w *BufferWriter) Flush() { w.Writer.WriteHeader(w.Status) } // Default status text output. - if w.Status != http.StatusOK && w.buffer.Len() == 0 { + if w.Status != http.StatusOK && w.buffer.Len() == 0 && w.Writer.BytesWritten() == 0 { w.buffer.WriteString(http.StatusText(w.Status)) } if w.buffer.Len() > 0 { From 1f8845291adea65d4468a4c81d5c7ac1e0bbf033 Mon Sep 17 00:00:00 2001 From: star liu Date: Wed, 22 Jan 2025 19:20:21 +0800 Subject: [PATCH 2/4] fix(contrib/config/polaris): it only supports json format for configuration contents, add more content formats support (#4126) --- contrib/config/polaris/polaris.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/config/polaris/polaris.go b/contrib/config/polaris/polaris.go index 04765d6591a..1f9d6ee0576 100644 --- a/contrib/config/polaris/polaris.go +++ b/contrib/config/polaris/polaris.go @@ -147,7 +147,7 @@ func (c *Client) doUpdate(ctx context.Context) (err error) { return gerror.New("config file is empty") } var j *gjson.Json - if j, err = gjson.DecodeToJson([]byte(c.client.GetContent())); err != nil { + if j, err = gjson.LoadContent([]byte(c.client.GetContent())); err != nil { return gerror.Wrap(err, `parse config map item from polaris failed`) } c.value.Set(j) From f9c7eae23bd06eb038effc0f6a9c55853f79f9c1 Mon Sep 17 00:00:00 2001 From: heansheng <77931774@qq.com> Date: Wed, 22 Jan 2025 19:22:02 +0800 Subject: [PATCH 3/4] fix(net/ghttp): remove unused code snippet (#4131) --- net/ghttp/ghttp_request_param_request.go | 4 ++-- net/ghttp/ghttp_server_service_handler.go | 17 ----------------- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/net/ghttp/ghttp_request_param_request.go b/net/ghttp/ghttp_request_param_request.go index a2874d9de92..601e3f06a92 100644 --- a/net/ghttp/ghttp_request_param_request.go +++ b/net/ghttp/ghttp_request_param_request.go @@ -183,7 +183,7 @@ func (r *Request) doGetRequestStruct(pointer interface{}, mapping ...map[string] return data, nil } // `in` Tag Struct values. - if err = r.mergeInTagStructValue(data, pointer); err != nil { + if err = r.mergeInTagStructValue(data); err != nil { return data, nil } @@ -239,7 +239,7 @@ func (r *Request) mergeDefaultStructValue(data map[string]interface{}, pointer i } // mergeInTagStructValue merges the request parameters with header or cookie values from struct `in` tag definition. -func (r *Request) mergeInTagStructValue(data map[string]interface{}, pointer interface{}) error { +func (r *Request) mergeInTagStructValue(data map[string]interface{}) error { fields := r.serveHandler.Handler.Info.ReqStructFields if len(fields) > 0 { var ( diff --git a/net/ghttp/ghttp_server_service_handler.go b/net/ghttp/ghttp_server_service_handler.go index 76de26aaae8..7e248c75c5e 100644 --- a/net/ghttp/ghttp_server_service_handler.go +++ b/net/ghttp/ghttp_server_service_handler.go @@ -282,20 +282,3 @@ func createRouterFunc(funcInfo handlerFuncInfo) func(r *Request) { } } } - -// trimGeneric removes type definitions string from response type name if generic -func trimGeneric(structName string) string { - var ( - leftBraceIndex = strings.LastIndex(structName, "[") // for generic, it is faster to start at the end than at the beginning - rightBraceIndex = strings.LastIndex(structName, "]") - ) - if leftBraceIndex == -1 || rightBraceIndex == -1 { - // not found '[' or ']' - return structName - } else if leftBraceIndex+1 == rightBraceIndex { - // may be a slice, because generic is '[X]', not '[]' - // to be compatible with bad return parameter type: []XxxRes - return structName - } - return structName[:leftBraceIndex] -} From 20b19878286703c073e558a06ad05ee5d323672a Mon Sep 17 00:00:00 2001 From: heansheng <77931774@qq.com> Date: Thu, 23 Jan 2025 17:58:32 +0800 Subject: [PATCH 4/4] feat(test/gtest): add map type support for `AssertNI/AssertIN` (#4135) --- test/gtest/gtest_util.go | 18 ++++++++++++++++-- test/gtest/gtest_z_unit_test.go | 16 ++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/test/gtest/gtest_util.go b/test/gtest/gtest_util.go index c9ccb9f0b49..c1609474d56 100644 --- a/test/gtest/gtest_util.go +++ b/test/gtest/gtest_util.go @@ -220,7 +220,6 @@ func AssertLE(value, expect interface{}) { // AssertIN checks `value` is IN `expect`. // The `expect` should be a slice, // but the `value` can be a slice or a basic type variable. -// TODO map support. // TODO: gconv.Strings(0) is not [0] func AssertIN(value, expect interface{}) { var ( @@ -249,6 +248,14 @@ func AssertIN(value, expect interface{}) { expectStr = gconv.String(expect) ) passed = gstr.Contains(expectStr, valueStr) + case reflect.Map: + expectMap := gconv.Map(expect) + for _, v1 := range gconv.Strings(value) { + if _, exists := expectMap[v1]; !exists { + passed = false + break + } + } default: panic(fmt.Sprintf(`[ASSERT] INVALID EXPECT VALUE TYPE: %v`, expectKind)) } @@ -260,7 +267,6 @@ func AssertIN(value, expect interface{}) { // AssertNI checks `value` is NOT IN `expect`. // The `expect` should be a slice, // but the `value` can be a slice or a basic type variable. -// TODO map support. func AssertNI(value, expect interface{}) { var ( passed = true @@ -287,6 +293,14 @@ func AssertNI(value, expect interface{}) { expectStr = gconv.String(expect) ) passed = !gstr.Contains(expectStr, valueStr) + case reflect.Map: + expectMap := gconv.Map(expect) + for _, v1 := range gconv.Strings(value) { + if _, exists := expectMap[v1]; exists { + passed = false + break + } + } default: panic(fmt.Sprintf(`[ASSERT] INVALID EXPECT VALUE TYPE: %v`, expectKind)) } diff --git a/test/gtest/gtest_z_unit_test.go b/test/gtest/gtest_z_unit_test.go index 2c1197f22e6..7d576fd791a 100644 --- a/test/gtest/gtest_z_unit_test.go +++ b/test/gtest/gtest_z_unit_test.go @@ -322,6 +322,22 @@ func TestAssertIN(t *testing.T) { }) } +func TestAssertIN_Map(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + t.AssertIN("k1", map[string]string{"k1": "v1", "k2": "v2"}) + t.AssertIN(1, map[int64]string{1: "v1", 2: "v2"}) + t.AssertIN([]string{"k1", "k2"}, map[string]string{"k1": "v1", "k2": "v2"}) + }) +} + +func TestAssertNI_Map(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + t.AssertNI("k3", map[string]string{"k1": "v1", "k2": "v2"}) + t.AssertNI(3, map[int64]string{1: "v1", 2: "v2"}) + t.AssertNI([]string{"k3", "k4"}, map[string]string{"k1": "v1", "k2": "v2"}) + }) +} + func TestAssertNI(t *testing.T) { gtest.C(t, func(t *gtest.T) { t.AssertNI("d", []string{"a", "b", "c"})