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.
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
...
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 } ]