在Gin中设置路由未找到的处理方式

huangapple go评论86阅读模式
英文:

Setting up Route Not Found in Gin

问题

我已经在Gin中设置了默认路由和一些路由:

router := gin.Default()
router.POST("/users", save)
router.GET("/users", getAll)

但是如何处理Gin中的404 Route Not Found呢?

最初,我使用的是httprouter,我知道Gin也使用它,所以最初的代码是这样的:

router.NotFound = http.HandlerFunc(customNotFound)

以及函数:

func customNotFound(w http.ResponseWriter, r *http.Request) {
    // 返回JSON
    return
}

但是这种方法在Gin中不起作用。

我需要能够使用c *gin.Context返回JSON,这样我就可以使用:

c.JSON(404, gin.H{"code": "PAGE_NOT_FOUND", "message": "Page not found"})
英文:

I've setup a default router and some routes in Gin:

router := gin.Default()
router.POST("/users", save)
router.GET("/users",getAll)

but how do I handle 404 Route Not Found in Gin?

Originally, I was using httprouter which I understand Gin uses so this was what I originally had...

router.NotFound = http.HandlerFunc(customNotFound)

and the function:

func customNotFound(w http.ResponseWriter, r *http.Request) {
    //return JSON
    return
}

but this won't work with Gin.

I need to be able to return JSON using the c *gin.Context so that I can use:

c.JSON(404, gin.H{"code": "PAGE_NOT_FOUND", "message": "Page not found"})

答案1

得分: 70

你要找的是NoRoute处理程序。

更具体地说:

r := gin.Default()

r.NoRoute(func(c *gin.Context) {
	c.JSON(404, gin.H{"code": "PAGE_NOT_FOUND", "message": "页面未找到"})
})
英文:

What you're looking for is the NoRoute handler.

More precisely:

r := gin.Default()

r.NoRoute(func(c *gin.Context) {
	c.JSON(404, gin.H{"code": "PAGE_NOT_FOUND", "message": "Page not found"})
})

答案2

得分: 3

根据Pablo Fernandez的写法,我还看到可以使用405 MethodNotAllowed来实现相同的效果,所以类似于404的NoRoute,405对应的是NoMethod方法。

所以,以下是结果:


import (
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
)


func main() {

   app := gin.New()
	app.NoRoute(func(c *gin.Context) {
		c.JSON(http.StatusNotFound, gin.H{"code": "PAGE_NOT_FOUND", "message": "404 page not found"})
	})

	app.NoMethod(func(c *gin.Context) {
		c.JSON(http.StatusMethodNotAllowed, gin.H{"code": "METHOD_NOT_ALLOWED", "message": "405 method not allowed"})
	})

}

为了添加一个“catch all”方法,我们可以这样做:


import (
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
)


func main() {

   app := gin.New()
	app.NoRoute(func(c *gin.Context) {
		c.JSON(http.StatusNotFound, gin.H{"code": "PAGE_NOT_FOUND", "message": "404 page not found"})
	})

	app.NoMethod(func(c *gin.Context) {
		c.JSON(http.StatusMethodNotAllowed, gin.H{"code": "METHOD_NOT_ALLOWED", "message": "405 method not allowed"})
	})

}

	// 设置错误处理中间件
	app.Use(func(c *gin.Context) {
		log.Printf("Total Errors -> %d", len(c.Errors))

		if len(c.Errors) <= 0 {
			c.Next()
			return
		}

		for _, err := range c.Errors {
			log.Printf("Error -> %+v\n", err)
		}
		c.JSON(http.StatusInternalServerError, "")

	})

现在,gin只有这两个方法用于处理这两种类型的错误,我猜这是因为在构建API时这两种错误是最常见的,并且希望在首次设置应用程序时添加一些默认处理程序。

实际上,我们可以在这里看到实现:

// NoRoute添加NoRoute的处理程序。默认情况下返回404代码。
func NoRoute(handlers ...gin.HandlerFunc) {
	engine().NoRoute(handlers...)
}

// NoMethod是Engine.NoMethod的包装器。
func NoMethod(handlers ...gin.HandlerFunc) {
	engine().NoMethod(handlers...)
}

现在,默认情况下,当使用gin框架的用户没有使用这两个处理程序时,它们使用的默认主体在这里定义:

var (
	default404Body = []byte("404 page not found")
	default405Body = []byte("405 method not allowed")
)

然后在函数handleHTTPRequest中使用,从632行开始:

	if engine.HandleMethodNotAllowed {
		for _, tree := range engine.trees {
			if tree.method == httpMethod {
				continue
			}
			if value := tree.root.getValue(rPath, nil, c.skippedNodes, unescape); value.handlers != nil {
				c.handlers = engine.allNoMethod
				serveError(c, http.StatusMethodNotAllowed, default405Body)
				return
			}
		}
	}
	c.handlers = engine.allNoRoute
	serveError(c, http.StatusNotFound, default404Body)
}
英文:

Adding to what Pablo Fernandez wrote I also seen that the same can be done with 405 MethodNotAllowed, so similarly if for 404 we've got NoRoute for 405 there is NoMethod method

So having this as result


import (
	&quot;github.com/gin-gonic/gin&quot;
	&quot;log&quot;
	&quot;net/http&quot;
)


func main() {

   app := gin.New()
	app.NoRoute(func(c *gin.Context) {
		c.JSON(http.StatusNotFound, gin.H{&quot;code&quot;: &quot;PAGE_NOT_FOUND&quot;, &quot;message&quot;: &quot;404 page not found&quot;})
	})

	app.NoMethod(func(c *gin.Context) {
		c.JSON(http.StatusMethodNotAllowed, gin.H{&quot;code&quot;: &quot;METHOD_NOT_ALLOWED&quot;, &quot;message&quot;: &quot;405 method not allowed&quot;})
	})

}

In order to add a 'catch all' method we can do:


import (
	&quot;github.com/gin-gonic/gin&quot;
	&quot;log&quot;
	&quot;net/http&quot;
)


func main() {

   app := gin.New()
	app.NoRoute(func(c *gin.Context) {
		c.JSON(http.StatusNotFound, gin.H{&quot;code&quot;: &quot;PAGE_NOT_FOUND&quot;, &quot;message&quot;: &quot;404 page not found&quot;})
	})

	app.NoMethod(func(c *gin.Context) {
		c.JSON(http.StatusMethodNotAllowed, gin.H{&quot;code&quot;: &quot;METHOD_NOT_ALLOWED&quot;, &quot;message&quot;: &quot;405 method not allowed&quot;})
	})

}

	// Set-up Error-Handler Middleware
	app.Use(func(c *gin.Context) {
		log.Printf(&quot;Total Errors -&gt; %d&quot;, len(c.Errors))

		if len(c.Errors) &lt;= 0 {
			c.Next()
			return
		}

		for _, err := range c.Errors {
			log.Printf(&quot;Error -&gt; %+v\n&quot;, err)
		}
		c.JSON(http.StatusInternalServerError, &quot;&quot;)

	})


Now, gin has these 2 method only for these 2 type of errors,my guess is because are the most common one while building an API and wanted to add some default handler when you first set up the application.

In fact, we can see the implementation here:

// NoRoute adds handlers for NoRoute. It returns a 404 code by default.
func NoRoute(handlers ...gin.HandlerFunc) {
	engine().NoRoute(handlers...)
}

// NoMethod is a wrapper for Engine.NoMethod.
func NoMethod(handlers ...gin.HandlerFunc) {
	engine().NoMethod(handlers...)
}

Now, the body that uses by default when these 2 handlers are not used by who uses the gin framework (so the default one are) are defined enter link description here

var (
	default404Body = []byte(&quot;404 page not found&quot;)
	default405Body = []byte(&quot;405 method not allowed&quot;)
)

And then later on used on the function handleHTTPRequest from line 632

	if engine.HandleMethodNotAllowed {
		for _, tree := range engine.trees {
			if tree.method == httpMethod {
				continue
			}
			if value := tree.root.getValue(rPath, nil, c.skippedNodes, unescape); value.handlers != nil {
				c.handlers = engine.allNoMethod
				serveError(c, http.StatusMethodNotAllowed, default405Body)
				return
			}
		}
	}
	c.handlers = engine.allNoRoute
	serveError(c, http.StatusNotFound, default404Body)
}

huangapple
  • 本文由 发表于 2015年9月8日 01:41:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/32443738.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定