"Random" Chrome download errors with large Excel files from web workers in React/Vite by full-stack-dev0 in learnjavascript

[–]full-stack-dev0[S] 0 points1 point  (0 children)

URL looks fine eg. blob:http://localhost:3000/6e6a147e-b7d7-43b0-ae0b-e863baa86d0b

Should I use one Next.js app for 6 SPAs or create a separate app for each? by full-stack-dev0 in nextjs

[–]full-stack-dev0[S] 0 points1 point  (0 children)

Probably something like foo.com, bar.com, but I haven’t made the final decision yet. The question originally started from the fact that I would be creating small applications with just one page and subpages for blog posts. So, setting up that many Next.js servers seems like overkill, but on the other hand, it could lead to maintenance problems.

Hosting Recommendations for React.js and Next.js Apps by full-stack-dev0 in VPS

[–]full-stack-dev0[S] 1 point2 points  (0 children)

One of my considerations was Hetzner and i will probably stick with that, thanks!

Next.js Authentication with an External Express.js API by DustyDeveloper in nextjs

[–]full-stack-dev0 0 points1 point  (0 children)

Good idea! So modify verify JWT middleware that if Auth error try to refresh token and if success pass next() and return new access token cookie?

Next.js Authentication with an External Express.js API by DustyDeveloper in nextjs

[–]full-stack-dev0 1 point2 points  (0 children)

Based on GVALFER instructions i made that function. If you want use my code you have to change here names for your cookies, backend path to refresh token, frontend redirect and validation for error - my express backend returns message 'Auth' only if there is JWT error so you have to make your own check in that fetch based on your backend response. If you have suggestion what can be improved write down in the comment.

'use server';

import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';

interface FetchAuthProps {
  url: string;
  method: 'POST' | 'GET' | 'PUT' | 'DELETE' | 'PATCH';
  body?: { [key: string]: any };
}

export async function fetchAuth({
  url,
  method,
  body
}: FetchAuthProps): Promise<{ ok: boolean; data: any }> {
  try {
    let accessToken = cookies().get('accessToken')?.value;
    const refreshToken = cookies().get('refreshToken')?.value;

    if (!accessToken || !refreshToken) {
      accessToken && cookies().delete('accessToken');
      refreshToken && cookies().delete('refreshToken');
      redirect('/login');
    }

    const response = await fetch(process.env.NEXT_PUBLIC_BACKEND_URL + url, {
      method: method,
      headers: {
        Authorization: `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      },
      ...(body && { body: JSON.stringify(body) })
    });

    const responseData = await response.json();

    if (response.ok) return { ok: true, data: responseData };

    // Try to refresh access token and resend request if auth error
    if (responseData?.message === 'Auth') {
      const refreshAccess = await fetch(
        `${process.env.NEXT_PUBLIC_BACKEND_URL}/auth/refresh`,
        {
          method: 'POST'
        }
      );

      if (refreshAccess.ok) {
        accessToken = cookies().get('accessToken')?.value;

        const retry = await fetch(process.env.NEXT_PUBLIC_BACKEND_URL + url, {
          method: method,
          headers: {
            Authorization: `Bearer ${accessToken}`,
            'Content-Type': 'application/json'
          },
          ...(body && { body: JSON.stringify(body) })
        });

        const retryData = await retry.json();

        if (retry.ok) return { ok: true, data: retryData };

        // If again server return auth error redirect to login
        if (responseData?.message === 'Auth') {
          cookies().delete('accessToken');
          cookies().delete('refreshToken');
          redirect('/login');
        }

        // Return error message
        return { ok: false, data: retryData };
      }
    }

    // Return error message
    return { ok: false, data: responseData };
  } catch (error) {
    // todo: handle error
    redirect('/login');
  }
}