Stack I’m using:
- Appwrite (Backend)
- Next.js
I’m using Next.js middleware to implement some protected routes. In the middleware.ts
file, I’ve added a method that checks whether the user is logged in. After adding that, it’s showing the window is not defined
error. But I haven’t used window
anywhere in the method. Below is the main content of middleware.ts
const NOT_LOGGED_IN_ROUTES = ["/login"];
const LOGGED_IN_ROUTES = ["/edit-profile"];
export async function middleware(request: NextRequest) {
const currentPath = request.nextUrl.pathname;
const { AppwriteServices } = await import("@/AppwriteServices");
const appwriteServices = new AppwriteServices();
const isUserLoggedIn = (await appwriteServices.getCurrentUser()) !== null;
if (isUserLoggedIn && NOT_LOGGED_IN_ROUTES.includes(currentPath)) {
return NextResponse.redirect(new URL("/", request.url));
}
if (!isUserLoggedIn && LOGGED_IN_ROUTES.includes(currentPath)) {
return NextResponse.redirect(new URL("/login", request.url));
}
}
if the user is logged in, the getCurrentUser
method returns the user data, otherwise null
. Below is the content of getCurrentUser
getCurrentUser = async () => {
try {
await this.setSession();
return await account.get();
} catch (error) {
// throw new Error((<Error>error).message);
/*
Cannot throw an error here,
cause in Appwrite's `account.get()`,
catch means the user is not logged in.
*/
}
return null;
};
Above used setSession
method is shown below
private async setSession() {
try {
const cookieValue = await this.getCookieValue();
const authCookies = {
[`a_session_${AppwriteProject.toLowerCase()}`]: cookieValue,
};
client.headers["X-Fallback-Cookies"] = JSON.stringify(authCookies);
} catch (error) {
throw new Error((<Error>error).message);
}
}
Above used client
is the client object provided by appwrite
. And the getCookieValue
method is shown below
private async getCookieValue() {
try {
const { cookies } = await import("next/headers");
const sessionNames = [
`a_session_${AppwriteProject.toLowerCase()}`,
`a_session_${AppwriteProject.toLowerCase()}_legacy`,
];
const cookieStore = cookies();
const hash =
cookieStore.get(sessionNames[0]) ??
cookieStore.get(sessionNames[1]) ??
null;
return hash?.value || "";
} catch (error) {
throw new Error((<Error>error).message);
}
}
The AppwriteProject
variable used above is just an env variable.
I had to set the sessions manually cause Appwrite
uses localStorage
to store and retrieve session tokens and I’m doing everything on the server-side.
So as you can see above, I haven’t used window
anywhere in the method/s. There are some appwrite
provided methods as well. the account.get()
, which source code you can check here
In the account.get()
method, another client.call()
method is used, where we can see some use of the window
object. But it’s not used directly. There are fallback checks with if
statements. So there’s no way for the window
object to get executed.
Besides that, I’m using the same getCurrentUser
method on another server component and that works fine.
Can’t understand what’s the issue here. Any help will be appreciated. Also, let me know if you need any further info
2
Answers
There are 3 contexts where your code can run when you make a Next.js app
The Appwrite web sdk (appwrite NPM package) uses isomorphic fetch so that the same fetch can be used in both client and server side, but it doesn’t work on the edge.
For now, I would suggest not using the web sdk in the middleware.
In order to use the window object you need to use it in a client component and wrap it in a
window != undefined
.Note: It can’t be used in a sever component or in a Next JS middleware.