Search code examples
gogo-gin

golang gin one route for different queries


is it possible in gin to have one route with either :item (name) OR :id?

example:

r.GET("/inventories/(:item|:id)", controllers.FindInventory)

Then I could probably do something like ...

func FindInventory(g *gin.Context) {
    var inv models.Inventory

    if item:
       err := models.DB.Where("item = ?", g.Param("item")).First(&inv).Error
    else:
       err := models.DB.Where("id = ?", g.Param("id")).First(&inv).Error
       
    if err != nil {
        g.JSON(http.StatusBadRequest, gin.H{"error": "Record not found!"})
        return
    }

    g.JSON(http.StatusOK, gin.H{"data": inv})
}

or is there a way to use one route for two types of queries ?


Solution

  • No, this is not supported. But there must be some way to distinguish between an item and an id. So it's easy to implement the logic yourself.

    Like this:

    r.GET("/inventories/:item", controllers.FindInventory)
    
    func FindInventory(g *gin.Context) {
        var inv models.Inventory
    
        item := g.Param("item")
        id, err := strconv.Atoi(item)
        if err != nil {
            err := models.DB.Where("item = ?", item).First(&inv).Error
        } else {
            err := models.DB.Where("id = ?", id).First(&inv).Error
        }
        if err != nil {
            g.JSON(http.StatusBadRequest, gin.H{"error": "Record not found!"})
            return
        }
    
        g.JSON(http.StatusOK, gin.H{"data": inv})
    }
    

    But if it's not possible to distinguish, then you'd need to have two separate request paths like

    • /inventories/by-item/:item
    • and /inventories/by-id/:id

    Update on 2023-05-31: merged @EpicAdidash's and @boyvinall's comments into the answer. Thank you!