diff --git a/gin.go b/gin.go index 3e7181cf..91783652 100644 --- a/gin.go +++ b/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)