blog/content/posts/gin-method-not-allowed/index.md
2023-10-17 18:42:36 +02:00

3.1 KiB

title date draft tags description summary cover
Gin Method Not Allowed 2023-10-17T18:29:45+02:00 false
go
gin
golang
http
ovh
ovhcloud
By default gin returns a 404 for an incorrect HTTP verb sent to a handled path. This can be fixed.
image relative alt caption hidden
gin.jpg true Gin & Tonic Gin & Tonic from Vlad Tchompalov sur (Unsplash) false

TL;DR: by default gin returns a 404 for an incorrect HTTP verb sent to a handled path. This can be fixed. Double-check the method you're using.

📖 Context

At OVHcloud, we use gin-gonic/gin as the go-to HTTP web framework for our internal services.

The default behavior when receiving a request for a path that's handled but with an incorrect HTTP verb is to reply with 404 Not Found. That's confusing because this status code is more often used when a path is not handled at all.

{{< highlight go "linenos=inline" >}} package main

import "github.com/gin-gonic/gin"

func main() { router := gin.Default() router.GET("/hello", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"hello": "gin"}) }) router.Run("localhost:8080") } {{< /highlight >}}

$ # existing path
$ curl -i http://localhost:8080/foo
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Tue, 17 Oct 2023 15:59:49 GMT
Content-Length: 15

{"hello":"gin"}⏎

$ # wrong method
$ curl -i -X POST http://localhost:8080/foo
HTTP/1.1 404 Not Found
Content-Type: text/plain
Date: Tue, 17 Oct 2023 16:00:03 GMT
Content-Length: 18

404 page not found⏎

$ # non-existent path
$ curl -i http://localhost:8080/bar
HTTP/1.1 404 Not Found
Content-Type: text/plain
Date: Tue, 17 Oct 2023 16:00:17 GMT
Content-Length: 18

404 page not found⏎

👨🏻‍🔧 Fixing the issue

The router can be configured to handle these cases, but it needs to be manually enabled:

{{< highlight go "linenos=inline,hl_lines=7" >}} package main

import "github.com/gin-gonic/gin"

func main() { router := gin.Default() router.HandleMethodNotAllowed = true router.GET("/hello", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"hello": "gin"}) }) router.Run("localhost:8080") } {{< /highlight >}}

$ # wrong method
$ curl -i -X POST http://localhost:8080/foo
HTTP/1.1 405 Method Not Allowed
Content-Type: text/plain
Date: Tue, 17 Oct 2023 16:00:53 GMT
Content-Length: 22

405 method not allowed⏎

As far as I can tell, this boolean isn't documented on the docs website, but it has a doc comment attached.

👀 Going further

As you can see, the response still misses the Allow header that should document the allowed methods on the endpoint.

A PR was opened in 2020 to fix this and maintainers seemed OK to merge it, but it had conflicts and the original author wasn't responsive ; so I opened a new one. I hope it will get merged soon!