Description
I'm trying to bind a UUID header field. It did not bind successfully but reported an error.
How to reproduce
package main
import (
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
func main(){
type A struct {
ID uuid.UUID `header:"ID"`
}
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
var a A
err := c.ShouldBindHeader(&a)
if err != nil {
panic(err)
}
c.JSON(200, gin.H{
"message": a.ID,
})
})
r.Run()
}
Expectations
requests.get("http://127.0.0.1:8088/ping", headers={"ID":"1b524196-100a-4ff6-8881-bf0e1e509b1d"})
-> 200
Actual result
2022/01/25 23:00:03 [Recovery] 2022/01/25 - 23:00:03 panic recovered:
GET /ping HTTP/1.1
Host: 127.0.0.1:8088
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Id: 1b524196-100a-4ff6-8881-bf0e1e509b1d
User-Agent: python-requests/2.27.1
["1b524196-100a-4ff6-8881-bf0e1e509b1d"] is not valid value for uuid.UUID
Environment
- go version: go1.17.5
- gin version (or commit ref): v1.7.7
- operating system: windows/amd64
Comment From: Bisstocuz
It's not Gin's bug.
type A struct {
ID uuid.UUID `header:"ID"`
}
should be
type A struct {
ID string `header:"ID"`
}
If you wanna transfer it to uuid.UUID
, use uuid.Parse(a.ID)
, check this: https://pkg.go.dev/github.com/google/uuid#Parse
Comment From: lynkas
@Bisstocuz Thank you. The UUID in body and URI can be bind correctly. Have "uuid in header cannot be bind directly" been mentioned somewhere?
Comment From: Bisstocuz
github.com/google/uuid
is not a standard library, and uuid.UUID
is not a compatible type with HTTP headers. It's ordinary to throw an error.
Here is binding code:
case reflect.Array:
if !ok {
vs = []string{opt.defaultValue}
}
if len(vs) != value.Len() {
return false, fmt.Errorf("%q is not valid value for %s", vs, value.Type().String())
}
return true, setArray(vs, value, field)
Comment From: iyear
If you expect to receive a UUID
, you can use binding
which is the gin
built-in validator.
https://github.com/go-playground/validator#format
You can also choose different UUID
types to bind.
func main() {
type A struct {
ID string `header:"ID" binding:"required,uuid"`
}
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
var a A
err := c.ShouldBindHeader(&a)
if err != nil {
panic(err)
}
c.JSON(200, gin.H{
"message": a.ID,
})
})
r.Run()
}