T
TanStack7mo ago
graceful-blue

Redirect and set cookie from server function called in loader

Hi, I have a page that validates a token from an email link and then sets a cookie and redirects to a page the user now has access to. You can imagine this would work similar to an "magic link" email based auth system. When I try to set the cookie and redirect from the server function called by the route's loader, the cookie seems to never be set.
const exampleServerFn = createServerFn()
.validator(zodValidator(z.object({ token: z.string() })))
.handler(async () => {
const name = "test";
const cookieValue = "test";

setCookie(name, cookieValue, {
expires: getExpirationTime("1 week"),
secure: process.env.NODE_ENV === "production",
});

throw redirect({to: "/page-behind-cookie"});
});
const exampleServerFn = createServerFn()
.validator(zodValidator(z.object({ token: z.string() })))
.handler(async () => {
const name = "test";
const cookieValue = "test";

setCookie(name, cookieValue, {
expires: getExpirationTime("1 week"),
secure: process.env.NODE_ENV === "production",
});

throw redirect({to: "/page-behind-cookie"});
});
In my route I have the loader setup to call the server function:
export const Route = createFileRoute("/access-link-from-email")({
component: RouteComponent,
validateSearch: zodValidator(z.object({ token: z.string() })),
loaderDeps: ({ search }) => ({ token: search.token }),
async loader({ deps: { token }, params: { packetId, slug } }) {

// i call the server function here!
await exampleServerFn({
data: { token },
});
},
});
export const Route = createFileRoute("/access-link-from-email")({
component: RouteComponent,
validateSearch: zodValidator(z.object({ token: z.string() })),
loaderDeps: ({ search }) => ({ token: search.token }),
async loader({ deps: { token }, params: { packetId, slug } }) {

// i call the server function here!
await exampleServerFn({
data: { token },
});
},
});
The redirect is working correctly, however, no cookie is being set. I have tried a few combinations with setting headers as explicitly like so:
setHeader('Set-Cookie', getWebRequest()?.headers.getSetCookie())
setHeader('Set-Cookie', getWebRequest()?.headers.getSetCookie())
Or as part of the redirect but neither seem to be working since the getSetCookie() returns an empty array while being called after setCookie():
throw redirect({
to: "/page-behind-cookie",
headers: {
"Set-Cookie": getWebRequest()?.headers.getSetCookie().join(','),
}
});
throw redirect({
to: "/page-behind-cookie",
headers: {
"Set-Cookie": getWebRequest()?.headers.getSetCookie().join(','),
}
});
I have also tried calling the server function from the route's beforeLoad but that did not work either. Would love to know if I'm missing something or if this is not supposed to work, any workarounds you'd suggest. Thanks in advanced.
6 Replies
optimistic-gold
optimistic-gold7mo ago
getSetCookie returns the set cookie headers from the request, not the response. so its expected that this does not work you need to actually set the cookie in the redirect header however we could automatically collect headers set by the user and attach them to the redirect shouldnt be a big deal
constant-blue
constant-blue7mo ago
Doesn't this work by default cause I'm setting a cookie and redirecting immediately and it works fine
optimistic-gold
optimistic-gold7mo ago
apparently not? maybe not during SSR? did not test it @jason can you please provide a complete minimal example that fails for you? as a git repo
constant-blue
constant-blue7mo ago
Redirect in server function just throws an object so I see no reason while it shouldn't work At least it works for me Maybe he is on the version that didn't set cookie during SSR
optimistic-gold
optimistic-gold7mo ago
ok let's wait for a repro then
graceful-blue
graceful-blueOP7mo ago
hey all, i tried to create a new project for repro and was not able to repro it. so figured i must be doing something wrong... decided to try to update to the newest minors across all the tan stack packages and it is now working properly. thanks and sorry for the confusion! P.S. really love working with tanstack

Did you find this page helpful?