Fiber version
Issue description
After testing, the reason is that the session cannot store the structure
Code snippet
package main
import (
"fmt"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/session"
)
// Auth Auth
type Auth struct {
Name string
}
func main() {
store := session.New()
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
sess, err := store.Get(c)
if err != nil {
panic(err)
}
defer sess.Save()
sess.Set("auth", Auth{
Name: "ok",
})
return c.SendString("ok")
})
app.Get("/session", func(c *fiber.Ctx) error {
sess, err := store.Get(c)
if err != nil {
panic(err)
}
defer sess.Save()
auth := sess.Get("auth")
fmt.Println("auth:", auth)
return c.SendString("ok")
})
app.Listen("127.0.0.1:3008")
}
Just got the exact same error lol
But I have nothing to say, just an identical problem
The problem is in the session.Save() method. If you call session.Get() when you've set your value, but before session.Save() is called, you get the correct value back.
The problem is in the following switch statement in write_bytes.go. Because of the user-defined struct, the switch statement chooses the default case, which leads to an ErrUnsupportedType error being thrown and the value not being stored, which leads to the (key, value) pair not being saved.
switch v.Kind() {
case reflect.Array, reflect.Slice:
l := v.Len()
b = AppendArrayHeader(b, uint32(l))
for i := 0; i < l; i++ {
b, err = AppendIntf(b, v.Index(i).Interface())
if err != nil {
return b, err
}
}
return b, nil
case reflect.Ptr:
if v.IsNil() {
return AppendNil(b), err
}
b, err = AppendIntf(b, v.Elem().Interface())
return b, err
default:
return b, &ErrUnsupportedType{T: v.Type()}
}
After some debugging, I found out that if I added the following case to the switch statement, it would follow that path. I unfortunately do not have any experience with msgp and I'm still a beginner in Go, so I don't really know how to proceed further.
case reflect.Struct:
Okay, I kinda have it working now, but it's not perfect yet. This afternoon I did some research on msgp and as far as I know, it is not possible to convert the struct into bytes. Therefore, I'm converting the struct into a map[string]interface{}, which msgp can convert. My implementation uses github.com/fatih/structs to convert the structs into maps, after which I tell the program to append the map to the byte[].
case reflect.Struct:
m := structs.Map(i)
b, err = AppendMapStrIntf(b, m)
return b, err
This results into the following output when running the snippet from @chinaapus:
auth: map[Name: ok]
There are two things I don't like about this implementation:
map[string]interface{} to the user and as far as I've seen, there is no way to convert a map[string]interface{} to a struct, without first defining the structure of the struct. These things can be solved:
structs.Map() method in our code, as it is the only method out of the library we are using.map[string]interface{} back into a struct. They'll have to define the structure of the final struct, then there are various methods/libraries to do the conversion itself.@Fenny Let me know what you think about the implementation & disadvantages and I'll work on creating a PR.
Most helpful comment
The problem is in the following switch statement in write_bytes.go. Because of the user-defined struct, the switch statement chooses the default case, which leads to an ErrUnsupportedType error being thrown and the value not being stored, which leads to the (key, value) pair not being saved.
After some debugging, I found out that if I added the following case to the switch statement, it would follow that path. I unfortunately do not have any experience with msgp and I'm still a beginner in Go, so I don't really know how to proceed further.