Description

I'm trying to use gin to build a k8s restapi service,but it seems that there is something wrong with gin’s routing function.

Details

I have defined the following two routes to handle namespaced resource requests and none-namespaced resource requests respectively.

    namespacedRouter := router.Group("/:api-version/namespaces")
    {
        // /{api-version}/namespaces/{namespace-name}/{resource-kind}
        namespacedRouter.GET("/:namespace-name/:resource-kind", ApiNamespacedList)

        // /{api-version}//namespaces/{namespace-name}/{resource-kind}/{resource-name}
        namespacedRouter.GET("/:namespace-name/:resource-kind/:resource-name", ApiNamespacedGet)
    }

    naneNamespacedRouter := router.Group("/:api-version")
    {
        // /{api-version}/{resource-kind}
        naneNamespacedRouter.GET("/:resource-kind", ApiNoneNamespacedList)

        // /{api-version}/{resource-kind}/{resource-name}
        naneNamespacedRouter.GET("/:resource-kind/:resource-name", ApiNoneNamespacedGet)
    }

These routes work fine for namespaced resources, but only partially match none-namespaced resources.

Like this:

namespaced-list ok api/v1/namespaces/kube-system/pods

namespaced-get ok api/v1/namespaces/kube-system/pods/etcd-minikube

none-namespaced-list ok api/v1/namespaces api/v1/nodes

none-namespaced-get 404 api/v1/namespaces/default

none-namespaced-get ok api/v1/nodes/minikube

In summary, it fails to correctly match the get case for none-namespaced resources named namespaces

My guess is that the namespaces in the path make gin confused and unable to work properly.

Environment

  • go version: golang 1.20
  • gin version (or commit ref): v1.9.1
  • operating system: macOS 13.4 (22F66)

Comment From: arturiamu

After testing, I found that I only need to change api/v1/namespaces/default to api/v1/ns/default for normal access.But this result is obviously not what I want, so I hope to understand whether this is a bug in gin logic, or if there is any way for me to use this route normally without using the above method.

Comment From: arturiamu

So it should be certain that there is a problem with gin in the process of processing namespace.

Comment From: f-pisani

Gin does not implement its own router; it uses httprouter as a router. Here's how it works: https://github.com/julienschmidt/httprouter#how-does-it-work.

"/v1/namespaces/default" does not match the "/:api-version/:resource-kind/:resource-name" route because with httprouter, by design, a request can only match exactly one or no route. If you follow the routing path, "/v1/namespaces" matches with "/:api-version/namespaces," and the wildcard path "/:api-version/:resource-kind" is ignored in this case because it can't be "/namespaces" or "/:resource-kind".

You can use another prefix to disambiguate, like "/:api-version/resources/:resource-kind/:resource-name."