From 1c12f3a30d223e4887eecf810c9d05808b144170 Mon Sep 17 00:00:00 2001 From: John Guo Date: Thu, 28 Mar 2024 22:08:54 +0800 Subject: [PATCH] fix: http superfluous response.WriteHeader call in some scenario (#3428) --- frame/g/g_func.go | 4 ++-- .../internal/response/response_writer.go | 5 +++++ util/gutil/gutil_dump.go | 22 ++++++++++++++++--- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/frame/g/g_func.go b/frame/g/g_func.go index 738acfadd..3aba33570 100644 --- a/frame/g/g_func.go +++ b/frame/g/g_func.go @@ -72,8 +72,8 @@ func DumpWithOption(value interface{}, option gutil.DumpOption) { } // DumpJson pretty dumps json content to stdout. -func DumpJson(jsonContent string) { - gutil.DumpJson(jsonContent) +func DumpJson(value any) { + gutil.DumpJson(value) } // Throw throws an exception, which can be caught by TryCatch function. diff --git a/net/ghttp/internal/response/response_writer.go b/net/ghttp/internal/response/response_writer.go index fccd476f1..9c3419941 100644 --- a/net/ghttp/internal/response/response_writer.go +++ b/net/ghttp/internal/response/response_writer.go @@ -28,7 +28,11 @@ func NewWriter(writer http.ResponseWriter) *Writer { } // WriteHeader implements the interface of http.ResponseWriter.WriteHeader. +// Note that the underlying `WriteHeader` can only be called once in a http response. func (w *Writer) WriteHeader(status int) { + if w.wroteHeader { + return + } w.ResponseWriter.WriteHeader(status) w.wroteHeader = true } @@ -42,6 +46,7 @@ func (w *Writer) BytesWritten() int64 { func (w *Writer) Write(data []byte) (int, error) { n, err := w.ResponseWriter.Write(data) w.bytesWritten += int64(n) + w.wroteHeader = true return n, err } diff --git a/util/gutil/gutil_dump.go b/util/gutil/gutil_dump.go index e25509a49..d30f79b6f 100644 --- a/util/gutil/gutil_dump.go +++ b/util/gutil/gutil_dump.go @@ -472,12 +472,28 @@ func addSlashesForString(s string) string { } // DumpJson pretty dumps json content to stdout. -func DumpJson(jsonContent string) { +func DumpJson(value any) { + switch result := value.(type) { + case []byte: + doDumpJson(result) + case string: + doDumpJson([]byte(result)) + default: + jsonContent, err := json.Marshal(value) + if err != nil { + fmt.Println(err.Error()) + return + } + doDumpJson(jsonContent) + } +} + +func doDumpJson(jsonContent []byte) { var ( buffer = bytes.NewBuffer(nil) - jsonBytes = []byte(jsonContent) + jsonBytes = jsonContent ) - if err := json.Indent(buffer, jsonBytes, "", "\t"); err != nil { + if err := json.Indent(buffer, jsonBytes, "", " "); err != nil { fmt.Println(err.Error()) } fmt.Println(buffer.String())