Next.js Discord

Discord Forum

What is the best way to set a cookie in App router server component ?

Unanswered
English Angora posted this in #help-forum
Open in Discord
English AngoraOP
I have a requirement to increment a flag in the database and set a cookie with an expiry time of 5 minutes when a page loads, and the next time the page loads, check if the cookie is expired or not and increment the flag and set a new cookie if it's expired.

Currently, I'm planning to use a Route handler for setting the cookie and calling the Route handler when the server component loads(the server component is used because I want to increment the database flag and the page is a public page so can't use client-side data updation due to security).

Is this the right way or is there a better way?

24 Replies

I think that you can set cookies from the server component though, this would need to be double checked (in this case, setting the cookie is done via the SET-COOKIE header of the response to the request getting the RSC)
"so can't use client-side data updation due to security" you mean you are using HTTP-only cookies without JS I guess?
so yeah it seems that you should either use a middleware (ideal but can be tricky to get the value you want to set, if you need to call a database), or fallback to a client component that calls a route handler
that's because of streaming specifically
@Eric Burel you can't call your own route handlers from a server component
English AngoraOP
i try to call route handler in the data fetching stage of my server component and it is working fine, but when i try to set a cookie from there cookie is not created in the browser.
@English Angora i try to call route handler in the data fetching stage of my server component and it is working fine, but when i try to set a cookie from there cookie is not created in the browser.
it won't work when you build the app, because route handlers are not ready when you build the application, it's an anti-pattern
it will indeed not set the cookie because it is equivalent to setting a cookie from an RSC, which is not possible as @Ray pointed out
you need to call the route handler client-side, for example in a "useEffect" call when the component renders
@English Angora i try to call route handler in the data fetching stage of my server component and it is working fine, but when i try to set a cookie from there cookie is not created in the browser.
// middleware
export function middleware(req: NextRequest) {
  if (req.nextUrl.pathname.startWith("/page") {
     try {
       const res = await fetch(new URL("/api", req.url))
       const data = await res.json()
       if (data.cookie) {
          const response = NextResponse.next()
          response.cookies.set("cookie",data.cookie)
          return response
       }
     } catch (e) {}
  }
}

try something like this maybe if you don't want to handle it on client side and some operation isn't available on the edge runtime
@Eric Burel you need to call the route handler client-side, for example in a "useEffect" call when the component renders
English AngoraOP
But does it expose the api to public ?

The webpage is public, it's a multi-tenent page, so i want to count the page visitors. so the logic is the count will increment when a user visits and set a cookie for 5 mins, so when the next time the same user visits the page, the cookie is checked and if it does not exists then the count will be incremented and set a 5 min expiry cookie.

So if I use the client side method, does the api goes public ? if so, then anyone can use it to incerement the count right?

then i think the only option remaining is to try the middleware method. But i have some confusions there too, im using a rewrite in middleware, so how can i use cookie with rewrite
but you could still make it a route handler and call from the client though
because client-side code cannot alter the cookie
so if a user calls your Route Handler twice, they can't modify the cookie
it is controlled by the browser
this can probably be hacked by sending requests programmatically, you probably want to add a check on the IP too, and have maybe a blacklist of VPNs etc.
in case you have a risk that people cheats on the visitor count
@English Angora I'm using a rewrite in middleware, so how can i use cookie with rewrite
try
const response = NextResponse.rewrite()
response.cookies.set("cookie",data.cookie)
return response
English AngoraOP
I will keep these in my mind, when i code. thank you for your valuable suggestions @Eric Burel and @Ray.