فهرست منبع

Include NoMethod Method to Gin to allow middlewares to handle 405 No Method Errors in the gin router

Adonis 10 سال پیش
والد
کامیت
a04d9e271c
1فایلهای تغییر یافته به همراه44 افزوده شده و 16 حذف شده
  1. 44 16
      gin.go

+ 44 - 16
gin.go

@@ -14,14 +14,13 @@ import (
 )
 
 const (
-	AbortIndex            = math.MaxInt8 / 2
-	MIMEJSON              = "application/json"
-	MIMEHTML              = "text/html"
-	MIMEXML               = "application/xml"
-	MIMEXML2              = "text/xml"
-	MIMEPlain             = "text/plain"
-	MIMEPOSTForm          = "application/x-www-form-urlencoded"
-	MIMEMultipartPOSTForm = "multipart/form-data"
+	AbortIndex   = math.MaxInt8 / 2
+	MIMEJSON     = "application/json"
+	MIMEHTML     = "text/html"
+	MIMEXML      = "application/xml"
+	MIMEXML2     = "text/xml"
+	MIMEPlain    = "text/plain"
+	MIMEPOSTForm = "application/x-www-form-urlencoded"
 )
 
 type (
@@ -30,12 +29,14 @@ type (
 	// Represents the web framework, it wraps the blazing fast httprouter multiplexer and a list of global middlewares.
 	Engine struct {
 		*RouterGroup
-		HTMLRender     render.Render
-		Default404Body []byte
-		pool           sync.Pool
-		allNoRoute     []HandlerFunc
-		noRoute        []HandlerFunc
-		router         *httprouter.Router
+		HTMLRender         render.Render
+		Default404Body     []byte
+		Default405Body     []byte
+		pool               sync.Pool
+		allNoRouteNoMethod []HandlerFunc
+		noRoute            []HandlerFunc
+		noMethod           []HandlerFunc
+		router             *httprouter.Router
 	}
 )
 
@@ -50,7 +51,9 @@ func New() *Engine {
 	}
 	engine.router = httprouter.New()
 	engine.Default404Body = []byte("404 page not found")
+	engine.Default405Body = []byte("405 method not allowed")
 	engine.router.NotFound = engine.handle404
+	engine.router.MethodNotAllowed = engine.handle405
 	engine.pool.New = func() interface{} {
 		c := &Context{Engine: engine}
 		c.Writer = &c.writermem
@@ -98,17 +101,27 @@ func (engine *Engine) NoRoute(handlers ...HandlerFunc) {
 	engine.rebuild404Handlers()
 }
 
+func (engine *Engine) NoMethod(handlers ...HandlerFunc) {
+	engine.noMethod = handlers
+	engine.rebuild405Handlers()
+}
+
 func (engine *Engine) Use(middlewares ...HandlerFunc) {
 	engine.RouterGroup.Use(middlewares...)
 	engine.rebuild404Handlers()
+	engine.rebuild405Handlers()
 }
 
 func (engine *Engine) rebuild404Handlers() {
-	engine.allNoRoute = engine.combineHandlers(engine.noRoute)
+	engine.allNoRouteNoMethod = engine.combineHandlers(engine.noRoute)
+}
+
+func (engine *Engine) rebuild405Handlers() {
+	engine.allNoRouteNoMethod = engine.combineHandlers(engine.noMethod)
 }
 
 func (engine *Engine) handle404(w http.ResponseWriter, req *http.Request) {
-	c := engine.createContext(w, req, nil, engine.allNoRoute)
+	c := engine.createContext(w, req, nil, engine.allNoRouteNoMethod)
 	// set 404 by default, useful for logging
 	c.Writer.WriteHeader(404)
 	c.Next()
@@ -122,6 +135,21 @@ func (engine *Engine) handle404(w http.ResponseWriter, req *http.Request) {
 	engine.reuseContext(c)
 }
 
+func (engine *Engine) handle405(w http.ResponseWriter, req *http.Request) {
+	c := engine.createContext(w, req, nil, engine.allNoRouteNoMethod)
+	// set 405 by default, useful for logging
+	c.Writer.WriteHeader(405)
+	c.Next()
+	if !c.Writer.Written() {
+		if c.Writer.Status() == 405 {
+			c.Data(-1, MIMEPlain, engine.Default405Body)
+		} else {
+			c.Writer.WriteHeaderNow()
+		}
+	}
+	engine.reuseContext(c)
+}
+
 // ServeHTTP makes the router implement the http.Handler interface.
 func (engine *Engine) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
 	engine.router.ServeHTTP(writer, request)