javascriptgonext.jssession-cookies

How to pass golang gin sesssion to next.js


Using Next.js v14.2.3 App Router

I am following gin-contrib cookie-based sessions documentation, to increment a session count

    // This is the backend golang code
    ...
    cookieStore := sessions.NewCookieStore([]byte("secret"))
    router.Use(
        sessions.Sessions("mysession", cookieStore),
    )

    router.GET("incr", func(c *gin.Context) {
        session := sessions.Default(c)
        c.Header("Content-Type", "application/json")

        var count int
        v := session.Get("count")
        if v == nil {
            count = 0
        } else {
            count = v.(int)
            count++
        }
        session.Set("count", count)
        session.Save()
        c.JSON(200, gin.H{"count": count})
    })
    ...

This works using postman I can see the cookie session in the response and the counter increments with each request. (But I notice curl includes header and a cookie mysession)

curl --location 'localhost:8080/incr' \
--header 'Cookie: mysession=someLongKey='

Should I be setting this header with my fetch request? And how do I get the someLongKey value to send with the request?

Right now, when I try to send this request using fetch in next.js project.

        // this is the frontend next.js code
        const resp = await fetch(`${process.env.BACKEND}/incr`)
        const res = await Promise.all([resp.json()])
        console.log("this is the res ",res)

The output does not increment as expected,

this is the res  [ { count: 0 } ]
 POST /incr 200 in 16ms
this is the res  [ { count: 0 } ]
 POST /incr 200 in 17ms
this is the res  [ { count: 0 } ]
 POST /incr 200 in 15ms
this is the res  [ { count: 0 } ]

and when I use the browser developer tools I can not see the cookie in the response.


Solution

  • Using mdn web docs, updating the js code

    ...
    const resp = await fetch(`${process.env.BACKEND}/incr`)
    const cookie = resp.headers.get("set-cookie")
    console.log("this is the cookie ",cookie)
    ...
    

    the response cookies are seen in the headers.

    using this cookie and fetching again

            const resp = await fetch(`${process.env.BACKEND}/incr`,{
                headers:{
                    Cookie:`cookieValueFromAbove`
                }
            })
    

    Now I am able to see the counter increment as expected

    this is the res  [ { count: 1 } ]
     POST /incr 200 in 58ms
    this is the res  [ { count: 2 } ]
     POST /incr 200 in 52ms
    

    Putting it all together using the next.js cookie and headers documentation. Lead me to create middleware.ts

    ...
    export default async function middleware(request:NextRequest){
        const response = NextResponse.next();
        const cookieStore = cookies()
        let cookie = cookieStore.get('set-cookie')
        let header = ""
        if(!cookie) {
            console.log("we need to fetch from gin and get cookie from response")
            const initialPromise = await fetch(`${process.env.BACKEND}/incr`)
            header = initialPromise.headers.get('set-cookie')
            console.log("this is the response cookie",header)
        } else {
            console.log("Finally the cookie",cookie)
            response.headers.set('set-cookie',cookie.value)
        }
    
        return response
    }
    ...
    

    Updating the function in scr/app/lib/actions.ts

    ...
    export async function incr(...){
            const initialHeaders = headers().get('set-cookie')
            const initialPromise = await fetch(`${process.env.BACKEND}/incr`,{
                headers:{
                    cookie:initialHeaders
                },
            })
    
            const updatedHeaders = initialPromise.headers.get('set-cookie')
            cookies().set("set-cookie",updatedHeaders)
    }
    

    The output

    this is the res  [ { count: 43 } ]
     POST /incr 200 in 58ms
    this is the res  [ { count: 44 } ]
     POST /incr 200 in 26ms
    this is the res  [ { count: 45 } ]
     POST /incr 200 in 23ms
    this is the res  [ { count: 46 } ]
     POST /incr 200 in 22ms
    this is the res  [ { count: 47 } ]