Gin: How to use middleware to convert parameter values

Created on 24 Apr 2019  Â·  6Comments  Â·  Source: gin-gonic/gin

I want to implement such a function, convert the id parameter in the following route into an int type, what should I do?

package main

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

func main() {
    r := gin.Default()
        r.use(TestMiddleware)
    r.GET("/test/:id", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run() // listen and serve on 0.0.0.0:8080
}

func TestMiddleware(c *gin.Context) {
     //I want to change the type of this id parameter from string to int type here.what should I do?
    c.Next()
}

Most helpful comment

I'm not sure if this works for you, but you can create values on your gin.Context

First create a yourNewValue from a middleware

// Middleware
func ExampleMiddleware() gin.HandlerFunc  {
    return func(c *gin.Context) {
        c.Set("yourNewValue", "value")
        c.Next()
    }
}

Then get that value from your controller

// Controller
func(c *gin.Context) {
    c.JSON(200, gin.H{
        "ID": c.MustGet("yourNewValue"),
    })
}

All 6 comments

Use strconv:
yourValue, err := strconv.ParseInt(c.Param("id"), 10, 64)

使用strconv:
yourValue, err := strconv.ParseInt(c.Param("id"), 10, 64)

I know this method,This is not the result I want,
example:

//I request this address:127.0.0.1:8080/test/5
id := c.Param("id") //The value of id is "5",this is string,I want to convert to int,
//then,When I get it again, it becomes my converted value.
c.Param("id") 
//The purpose of my doing this is that I don't want to have to write duplicate code
//If I have other api, the id parameter also needs to be converted, I have to write it once.
//I don't know how to write

Thanks

@strivefatup So the way I solve this is with a few helper functions I keep in a path helper package
I think you can see what all my other helpers would look like based on this sample.

func GetPathInt(c *gin.Context, name string) (int, error) {
   val := c.Params.ByName(name)
   if val == "" {
      return 0, errors.New(name + " path parameter value is empty or not specified")
   }
   return strconv.Atoi(val)
}

@strivefatup So the way I solve this is with a few helper functions I keep in a path helper package
I think you can see what all my other helpers would look like based on this sample.

func GetPathInt(c *gin.Context, name string) (int, error) {
   val := c.Params.ByName(name)
   if val == "" {
      return 0, errors.New(name + " path parameter value is empty or not specified")
   }
   return strconv.Atoi(val)
}

Your method is also very good,It’s perfect if can change directly in the middleware,Thanks.

You can use the shouldbindurl function

package main

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

type Person struct {
        ID int `uri:"id"`
}

func main() {
        r := gin.Default()
        r.GET("/test/:id", func(c *gin.Context) {
                person := Person{}

                if err := c.ShouldBindUri(&person); err != nil {
                        c.JSON(400, gin.H{"msg": err})
                        return
                }

                c.JSON(200, gin.H{
                        "ID": person.ID,
                })
        })
        r.Run() // listen and serve on 0.0.0.0:8080
}
// client
// curl -X GET 127.0.0.1:8080/test/123
// output
// {"ID":123}

I'm not sure if this works for you, but you can create values on your gin.Context

First create a yourNewValue from a middleware

// Middleware
func ExampleMiddleware() gin.HandlerFunc  {
    return func(c *gin.Context) {
        c.Set("yourNewValue", "value")
        c.Next()
    }
}

Then get that value from your controller

// Controller
func(c *gin.Context) {
    c.JSON(200, gin.H{
        "ID": c.MustGet("yourNewValue"),
    })
}
Was this page helpful?
0 / 5 - 0 ratings