From 20301bc2125b9aebb22a849cc76b4bb3ecb3f404 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 24 Feb 2016 10:31:44 +0800 Subject: [PATCH 1/5] multiple response.WriteHeader calls --- context/context.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/context/context.go b/context/context.go index db790ff2..837a1b45 100644 --- a/context/context.go +++ b/context/context.go @@ -187,6 +187,10 @@ func (w *Response) Write(p []byte) (int, error) { // WriteHeader sends an HTTP response header with status code, // and sets `started` to true. func (w *Response) WriteHeader(code int) { + if w.Status > 0 { + //prevent multiple response.WriteHeader calls + return + } w.Status = code w.Started = true w.ResponseWriter.WriteHeader(code) From 76d69b6e5143cd642a6d3f712f9768cf3a54a48a Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 24 Feb 2016 10:34:20 +0800 Subject: [PATCH 2/5] prevent auto detect of content-type https://golang.org/src/net/http/server.go#L1031 --- router.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/router.go b/router.go index 82a602e1..80956bd7 100644 --- a/router.go +++ b/router.go @@ -616,6 +616,8 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) context.Output.Header("Server", BConfig.ServerName) } + context.Output.Header("Content-Type", "text/html; charset=utf-8") + var urlPath string if !BConfig.RouterCaseSensitive { urlPath = strings.ToLower(r.URL.Path) From 8c37e765038f2d904b63a594e5696eaf7a9b4fdc Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 24 Feb 2016 11:47:55 +0800 Subject: [PATCH 3/5] the net/http should set header first,the set http status code and then write the content --- context/context.go | 24 +++++++++++++++++++----- router.go | 3 +-- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/context/context.go b/context/context.go index 837a1b45..83d5a866 100644 --- a/context/context.go +++ b/context/context.go @@ -59,7 +59,10 @@ type Context struct { // Reset init Context, BeegoInput and BeegoOutput func (ctx *Context) Reset(rw http.ResponseWriter, r *http.Request) { ctx.Request = r - ctx.ResponseWriter = &Response{rw, false, 0} + if ctx.ResponseWriter == nil { + ctx.ResponseWriter = &Response{} + } + ctx.ResponseWriter.reset(rw) ctx.Input.Reset(ctx) ctx.Output.Reset(ctx) } @@ -172,8 +175,16 @@ func (ctx *Context) CheckXSRFCookie() bool { //started set to true if response was written to then don't execute other handler type Response struct { http.ResponseWriter - Started bool - Status int + Started bool + Status int + wroteHeader bool +} + +func (r *Response) reset(rw http.ResponseWriter) { + r.ResponseWriter = rw + r.Status = 0 + r.Started = false + r.wroteHeader = false } // Write writes the data to the connection as part of an HTTP reply, @@ -181,6 +192,11 @@ type Response struct { // started means the response has sent out. func (w *Response) Write(p []byte) (int, error) { w.Started = true + if !w.wroteHeader { + w.ResponseWriter.WriteHeader(w.Status) + //prevent multiple response.WriteHeader calls + w.wroteHeader = true + } return w.ResponseWriter.Write(p) } @@ -188,12 +204,10 @@ func (w *Response) Write(p []byte) (int, error) { // and sets `started` to true. func (w *Response) WriteHeader(code int) { if w.Status > 0 { - //prevent multiple response.WriteHeader calls return } w.Status = code w.Started = true - w.ResponseWriter.WriteHeader(code) } // Hijack hijacker for http diff --git a/router.go b/router.go index 80956bd7..d0bf534f 100644 --- a/router.go +++ b/router.go @@ -607,6 +607,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) ) context := p.pool.Get().(*beecontext.Context) context.Reset(rw, r) + defer p.pool.Put(context) defer p.recoverPanic(context) @@ -616,8 +617,6 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) context.Output.Header("Server", BConfig.ServerName) } - context.Output.Header("Content-Type", "text/html; charset=utf-8") - var urlPath string if !BConfig.RouterCaseSensitive { urlPath = strings.ToLower(r.URL.Path) From 9a2696d216c3c873690c72dc301d4686eed265a4 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 9 Mar 2016 15:56:18 +0800 Subject: [PATCH 4/5] accept asta's idea see the talk https://github.com/astaxie/beego/pull/1719 --- context/context.go | 13 ++++--------- controller.go | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/context/context.go b/context/context.go index 83d5a866..f7c16e31 100644 --- a/context/context.go +++ b/context/context.go @@ -175,16 +175,14 @@ func (ctx *Context) CheckXSRFCookie() bool { //started set to true if response was written to then don't execute other handler type Response struct { http.ResponseWriter - Started bool - Status int - wroteHeader bool + Started bool + Status int } func (r *Response) reset(rw http.ResponseWriter) { r.ResponseWriter = rw r.Status = 0 r.Started = false - r.wroteHeader = false } // Write writes the data to the connection as part of an HTTP reply, @@ -192,11 +190,6 @@ func (r *Response) reset(rw http.ResponseWriter) { // started means the response has sent out. func (w *Response) Write(p []byte) (int, error) { w.Started = true - if !w.wroteHeader { - w.ResponseWriter.WriteHeader(w.Status) - //prevent multiple response.WriteHeader calls - w.wroteHeader = true - } return w.ResponseWriter.Write(p) } @@ -204,10 +197,12 @@ func (w *Response) Write(p []byte) (int, error) { // and sets `started` to true. func (w *Response) WriteHeader(code int) { if w.Status > 0 { + //prevent multiple response.WriteHeader calls return } w.Status = code w.Started = true + w.ResponseWriter.WriteHeader(w.Status) } // Hijack hijacker for http diff --git a/controller.go b/controller.go index a2943d42..2ad9d7cd 100644 --- a/controller.go +++ b/controller.go @@ -286,7 +286,7 @@ func (c *Controller) Abort(code string) { // CustomAbort stops controller handler and show the error data, it's similar Aborts, but support status code and body. func (c *Controller) CustomAbort(status int, body string) { - c.Ctx.ResponseWriter.WriteHeader(status) + c.Ctx.Output.Status = status // first panic from ErrorMaps, is is user defined error functions. if _, ok := ErrorMaps[body]; ok { panic(body) From f21cff01667473dfd94a46c7fd94e1fabbf00fd5 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 9 Mar 2016 16:00:52 +0800 Subject: [PATCH 5/5] some typo fixed --- context/context.go | 2 +- logs/{mulitfile.go => multifile.go} | 14 +++++++------- logs/{mulitfile_test.go => multifile_test.go} | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) rename logs/{mulitfile.go => multifile.go} (90%) rename logs/{mulitfile_test.go => multifile_test.go} (96%) diff --git a/context/context.go b/context/context.go index d7160e4a..31698c85 100644 --- a/context/context.go +++ b/context/context.go @@ -212,7 +212,7 @@ func (w *Response) WriteHeader(code int) { } w.Status = code w.Started = true - w.ResponseWriter.WriteHeader(w.Status) + w.ResponseWriter.WriteHeader(code) } // Hijack hijacker for http diff --git a/logs/mulitfile.go b/logs/multifile.go similarity index 90% rename from logs/mulitfile.go rename to logs/multifile.go index cf22f7a8..b82ba274 100644 --- a/logs/mulitfile.go +++ b/logs/multifile.go @@ -24,7 +24,7 @@ import ( // means if the file name in configuration is project.log filesLogWriter will create project.error.log/project.debug.log // and write the error-level logs to project.error.log and write the debug-level logs to project.debug.log // the rotate attribute also acts like fileLogWriter -type mulitFileLogWriter struct { +type multiFileLogWriter struct { writers [LevelDebug + 1 + 1]*fileLogWriter // the last one for fullLogWriter fullLogWriter *fileLogWriter Separate []string `json:"separate"` @@ -45,7 +45,7 @@ var levelNames = [...]string{"emergency", "alert", "critical", "error", "warning // "separate":["emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"], // } -func (f *mulitFileLogWriter) Init(config string) error { +func (f *multiFileLogWriter) Init(config string) error { writer := newFileWriter().(*fileLogWriter) err := writer.Init(config) if err != nil { @@ -76,7 +76,7 @@ func (f *mulitFileLogWriter) Init(config string) error { return nil } -func (f *mulitFileLogWriter) Destroy() { +func (f *multiFileLogWriter) Destroy() { for i := 0; i < len(f.writers); i++ { if f.writers[i] != nil { f.writers[i].Destroy() @@ -84,7 +84,7 @@ func (f *mulitFileLogWriter) Destroy() { } } -func (f *mulitFileLogWriter) WriteMsg(when time.Time, msg string, level int) error { +func (f *multiFileLogWriter) WriteMsg(when time.Time, msg string, level int) error { if f.fullLogWriter != nil { f.fullLogWriter.WriteMsg(when, msg, level) } @@ -98,7 +98,7 @@ func (f *mulitFileLogWriter) WriteMsg(when time.Time, msg string, level int) err return nil } -func (f *mulitFileLogWriter) Flush() { +func (f *multiFileLogWriter) Flush() { for i := 0; i < len(f.writers); i++ { if f.writers[i] != nil { f.writers[i].Flush() @@ -108,9 +108,9 @@ func (f *mulitFileLogWriter) Flush() { // newFilesWriter create a FileLogWriter returning as LoggerInterface. func newFilesWriter() Logger { - return &mulitFileLogWriter{} + return &multiFileLogWriter{} } func init() { - Register("mulitfile", newFilesWriter) + Register("multifile", newFilesWriter) } diff --git a/logs/mulitfile_test.go b/logs/multifile_test.go similarity index 96% rename from logs/mulitfile_test.go rename to logs/multifile_test.go index 5e1e3f06..57b96094 100644 --- a/logs/mulitfile_test.go +++ b/logs/multifile_test.go @@ -24,7 +24,7 @@ import ( func TestFiles_1(t *testing.T) { log := NewLogger(10000) - log.SetLogger("mulitfile", `{"filename":"test.log","separate":["emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"]}`) + log.SetLogger("multifile", `{"filename":"test.log","separate":["emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"]}`) log.Debug("debug") log.Informational("info") log.Notice("notice")