浏览代码

Fixes routing bug

Manu Mtz-Almeida 11 年之前
父节点
当前提交
1565111274
共有 2 个文件被更改,包括 27 次插入48 次删除
  1. 26 47
      gin.go
  2. 1 1
      logger.go

+ 26 - 47
gin.go

@@ -26,22 +26,11 @@ type (
 		Meta    interface{} `json:"meta"`
 		Meta    interface{} `json:"meta"`
 	}
 	}
 
 
-	ResponseWriter interface {
-		http.ResponseWriter
-		Status() int
-		Written() bool
-	}
-
-	responseWriter struct {
-		http.ResponseWriter
-		status int
-	}
-
 	// Context is the most important part of gin. It allows us to pass variables between middleware,
 	// Context is the most important part of gin. It allows us to pass variables between middleware,
 	// manage the flow, validate the JSON of a request and render a JSON response for example.
 	// manage the flow, validate the JSON of a request and render a JSON response for example.
 	Context struct {
 	Context struct {
 		Req      *http.Request
 		Req      *http.Request
-		Writer   ResponseWriter
+		Writer   http.ResponseWriter
 		Keys     map[string]interface{}
 		Keys     map[string]interface{}
 		Errors   []ErrorMsg
 		Errors   []ErrorMsg
 		Params   httprouter.Params
 		Params   httprouter.Params
@@ -68,28 +57,11 @@ type (
 	}
 	}
 )
 )
 
 
-func (rw *responseWriter) WriteHeader(s int) {
-	rw.ResponseWriter.WriteHeader(s)
-	rw.status = s
-}
-
-func (rw *responseWriter) Write(b []byte) (int, error) {
-	return rw.ResponseWriter.Write(b)
-}
-
-func (rw *responseWriter) Status() int {
-	return rw.status
-}
-
-func (rw *responseWriter) Written() bool {
-	return rw.status != 0
-}
-
 // Returns a new blank Engine instance without any middleware attached.
 // Returns a new blank Engine instance without any middleware attached.
 // The most basic configuration
 // The most basic configuration
 func New() *Engine {
 func New() *Engine {
 	engine := &Engine{}
 	engine := &Engine{}
-	engine.RouterGroup = &RouterGroup{nil, "/", nil, engine}
+	engine.RouterGroup = &RouterGroup{nil, "", nil, engine}
 	engine.router = httprouter.New()
 	engine.router = httprouter.New()
 	engine.router.NotFound = engine.handle404
 	engine.router.NotFound = engine.handle404
 	return engine
 	return engine
@@ -112,13 +84,15 @@ func (engine *Engine) NotFound404(handlers ...HandlerFunc) {
 }
 }
 
 
 func (engine *Engine) handle404(w http.ResponseWriter, req *http.Request) {
 func (engine *Engine) handle404(w http.ResponseWriter, req *http.Request) {
-
-	handlers := engine.allHandlers(engine.handlers404)
+	handlers := engine.combineHandlers(engine.handlers404)
 	c := engine.createContext(w, req, nil, handlers)
 	c := engine.createContext(w, req, nil, handlers)
-	c.Next()
-	if !c.Writer.Written() {
+	if engine.handlers404 == nil {
 		http.NotFound(c.Writer, c.Req)
 		http.NotFound(c.Writer, c.Req)
+	} else {
+		c.Writer.WriteHeader(404)
 	}
 	}
+
+	c.Next()
 }
 }
 
 
 // ServeFiles serves files from the given file system root.
 // ServeFiles serves files from the given file system root.
@@ -150,7 +124,7 @@ func (engine *Engine) Run(addr string) {
 
 
 func (group *RouterGroup) createContext(w http.ResponseWriter, req *http.Request, params httprouter.Params, handlers []HandlerFunc) *Context {
 func (group *RouterGroup) createContext(w http.ResponseWriter, req *http.Request, params httprouter.Params, handlers []HandlerFunc) *Context {
 	return &Context{
 	return &Context{
-		Writer:   &responseWriter{w, 0},
+		Writer:   w,
 		Req:      req,
 		Req:      req,
 		index:    -1,
 		index:    -1,
 		engine:   group.engine,
 		engine:   group.engine,
@@ -169,7 +143,7 @@ func (group *RouterGroup) Use(middlewares ...HandlerFunc) {
 func (group *RouterGroup) Group(component string, handlers ...HandlerFunc) *RouterGroup {
 func (group *RouterGroup) Group(component string, handlers ...HandlerFunc) *RouterGroup {
 	prefix := path.Join(group.prefix, component)
 	prefix := path.Join(group.prefix, component)
 	return &RouterGroup{
 	return &RouterGroup{
-		Handlers: handlers,
+		Handlers: group.combineHandlers(handlers),
 		parent:   group,
 		parent:   group,
 		prefix:   prefix,
 		prefix:   prefix,
 		engine:   group.engine,
 		engine:   group.engine,
@@ -188,7 +162,7 @@ func (group *RouterGroup) Group(component string, handlers ...HandlerFunc) *Rout
 // communication with a proxy).
 // communication with a proxy).
 func (group *RouterGroup) Handle(method, p string, handlers []HandlerFunc) {
 func (group *RouterGroup) Handle(method, p string, handlers []HandlerFunc) {
 	p = path.Join(group.prefix, p)
 	p = path.Join(group.prefix, p)
-	handlers = group.allHandlers(handlers)
+	handlers = group.combineHandlers(handlers)
 	group.engine.router.Handle(method, p, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
 	group.engine.router.Handle(method, p, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
 		group.createContext(w, req, params, handlers).Next()
 		group.createContext(w, req, params, handlers).Next()
 	})
 	})
@@ -219,13 +193,12 @@ func (group *RouterGroup) PUT(path string, handlers ...HandlerFunc) {
 	group.Handle("PUT", path, handlers)
 	group.Handle("PUT", path, handlers)
 }
 }
 
 
-func (group *RouterGroup) allHandlers(handlers []HandlerFunc) []HandlerFunc {
-	local := append(group.Handlers, handlers...)
-	if group.parent != nil {
-		return group.parent.allHandlers(local)
-	} else {
-		return local
-	}
+func (group *RouterGroup) combineHandlers(handlers []HandlerFunc) []HandlerFunc {
+	s := len(group.Handlers) + len(handlers)
+	h := make([]HandlerFunc, 0, s)
+	h = append(h, group.Handlers...)
+	h = append(h, handlers...)
+	return h
 }
 }
 
 
 /************************************/
 /************************************/
@@ -327,7 +300,9 @@ func (c *Context) ParseBody(item interface{}) error {
 // Serializes the given struct as a JSON into the response body in a fast and efficient way.
 // Serializes the given struct as a JSON into the response body in a fast and efficient way.
 // It also sets the Content-Type as "application/json"
 // It also sets the Content-Type as "application/json"
 func (c *Context) JSON(code int, obj interface{}) {
 func (c *Context) JSON(code int, obj interface{}) {
-	c.Writer.WriteHeader(code)
+	if code >= 0 {
+		c.Writer.WriteHeader(code)
+	}
 	c.Writer.Header().Set("Content-Type", "application/json")
 	c.Writer.Header().Set("Content-Type", "application/json")
 	encoder := json.NewEncoder(c.Writer)
 	encoder := json.NewEncoder(c.Writer)
 	if err := encoder.Encode(obj); err != nil {
 	if err := encoder.Encode(obj); err != nil {
@@ -339,7 +314,9 @@ func (c *Context) JSON(code int, obj interface{}) {
 // Serializes the given struct as a XML into the response body in a fast and efficient way.
 // Serializes the given struct as a XML into the response body in a fast and efficient way.
 // It also sets the Content-Type as "application/xml"
 // It also sets the Content-Type as "application/xml"
 func (c *Context) XML(code int, obj interface{}) {
 func (c *Context) XML(code int, obj interface{}) {
-	c.Writer.WriteHeader(code)
+	if code >= 0 {
+		c.Writer.WriteHeader(code)
+	}
 	c.Writer.Header().Set("Content-Type", "application/xml")
 	c.Writer.Header().Set("Content-Type", "application/xml")
 	encoder := xml.NewEncoder(c.Writer)
 	encoder := xml.NewEncoder(c.Writer)
 	if err := encoder.Encode(obj); err != nil {
 	if err := encoder.Encode(obj); err != nil {
@@ -352,7 +329,9 @@ func (c *Context) XML(code int, obj interface{}) {
 // It also update the HTTP code and sets the Content-Type as "text/html".
 // It also update the HTTP code and sets the Content-Type as "text/html".
 // See http://golang.org/doc/articles/wiki/
 // See http://golang.org/doc/articles/wiki/
 func (c *Context) HTML(code int, name string, data interface{}) {
 func (c *Context) HTML(code int, name string, data interface{}) {
-	c.Writer.WriteHeader(code)
+	if code >= 0 {
+		c.Writer.WriteHeader(code)
+	}
 	c.Writer.Header().Set("Content-Type", "text/html")
 	c.Writer.Header().Set("Content-Type", "text/html")
 	if err := c.engine.HTMLTemplates.ExecuteTemplate(c.Writer, name, data); err != nil {
 	if err := c.engine.HTMLTemplates.ExecuteTemplate(c.Writer, name, data); err != nil {
 		c.Error(err, map[string]interface{}{
 		c.Error(err, map[string]interface{}{

+ 1 - 1
logger.go

@@ -15,6 +15,6 @@ func Logger() HandlerFunc {
 		c.Next()
 		c.Next()
 
 
 		// Calculate resolution time
 		// Calculate resolution time
-		log.Printf("[%d] %s in %v", c.Writer.Status(), c.Req.RequestURI, time.Since(t))
+		log.Printf("%s in %v", c.Req.RequestURI, time.Since(t))
 	}
 	}
 }
 }