Browse Source

Deferring WriteHeader. Part 1

Manu Mtz-Almeida 11 years ago
parent
commit
dcafad3ced
4 changed files with 34 additions and 16 deletions
  1. 8 2
      gin.go
  2. 0 1
      logger.go
  3. 2 4
      render/render.go
  4. 24 9
      response_writer.go

+ 8 - 2
gin.go

@@ -45,10 +45,15 @@ type (
 
 func (engine *Engine) handle404(w http.ResponseWriter, req *http.Request) {
 	c := engine.createContext(w, req, nil, engine.finalNoRoute)
-	c.Writer.setStatus(404)
+	// set 404 by default, useful for logging
+	c.Writer.WriteHeader(404)
 	c.Next()
 	if !c.Writer.Written() {
-		c.Data(404, MIMEPlain, []byte("404 page not found"))
+		if c.Writer.Status() == 404 {
+			c.Data(-1, MIMEPlain, []byte("404 page not found"))
+		} else {
+			c.Writer.WriteHeaderNow()
+		}
 	}
 	engine.cache.Put(c)
 }
@@ -166,6 +171,7 @@ func (group *RouterGroup) Handle(method, p string, handlers []HandlerFunc) {
 	group.engine.router.Handle(method, p, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
 		c := group.engine.createContext(w, req, params, handlers)
 		c.Next()
+		c.Writer.WriteHeaderNow()
 		group.engine.cache.Put(c)
 	})
 }

+ 0 - 1
logger.go

@@ -47,7 +47,6 @@ func Logger() HandlerFunc {
 		if len(requester) == 0 {
 			requester = c.Request.Header.Get("X-Forwarded-For")
 		}
-
 		// if the requester is still empty, use the hard-coded address from the socket
 		if len(requester) == 0 {
 			requester = c.Request.RemoteAddr

+ 2 - 4
render/render.go

@@ -35,10 +35,8 @@ var (
 )
 
 func writeHeader(w http.ResponseWriter, code int, contentType string) {
-	if code >= 0 {
-		w.Header().Set("Content-Type", contentType)
-		w.WriteHeader(code)
-	}
+	w.Header().Set("Content-Type", contentType)
+	w.WriteHeader(code)
 }
 
 func (_ jsonRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {

+ 24 - 9
response_writer.go

@@ -1,6 +1,7 @@
 package gin
 
 import (
+	"log"
 	"net/http"
 )
 
@@ -9,9 +10,7 @@ type (
 		http.ResponseWriter
 		Status() int
 		Written() bool
-
-		// private
-		setStatus(int)
+		WriteHeaderNow()
 	}
 
 	responseWriter struct {
@@ -27,14 +26,30 @@ func (w *responseWriter) reset(writer http.ResponseWriter) {
 	w.written = false
 }
 
-func (w *responseWriter) setStatus(code int) {
-	w.status = code
+func (w *responseWriter) WriteHeader(code int) {
+	if code != 0 {
+		w.status = code
+		if w.written {
+			log.Println("[GIN] WARNING. Headers were already written!")
+		}
+	}
 }
 
-func (w *responseWriter) WriteHeader(code int) {
-	w.status = code
-	w.written = true
-	w.ResponseWriter.WriteHeader(code)
+func (w *responseWriter) WriteHeaderNow() {
+	if !w.written {
+		w.written = true
+		w.ResponseWriter.WriteHeader(w.status)
+	}
+}
+
+func (w *responseWriter) Write(data []byte) (n int, err error) {
+	if !w.written {
+		if w.status != 0 {
+			w.ResponseWriter.WriteHeader(w.status)
+		}
+		w.written = true
+	}
+	return w.ResponseWriter.Write(data)
 }
 
 func (w *responseWriter) Status() int {