Search code examples
javascriptreactjsnext.jsfetch-apiapp-router

fetch() function next.js app router net::ERR_BLOCKED_BY_CLIENT


I am happened to start a projects' frontend with Next.js v13.4 app router, and i also have an additional backend. I use api folder under app directory to manage routes and all that stuff. When i try to login fetch() function throws error : net::ERR_BLOCKED_BY_CLIENT

Even though it was working on my local host, i tried to deploy it and after i deploy it on a remote ubuntu, fetch function doesn't work. The problem is not on backend or anything since when i curl it works and when i request w/ Postman it also works. I tried to open it on private tab (which closed every plugin) but it didn't work either, still only thing i see is error.

enter image description here

'use client';
import {NextPage} from 'next';
import {Formik, Form} from 'formik';
import * as Yup from 'yup';
import CrButton from '@/components/CrButton';
import logger from '@/utils/logger';
import useTheme from '@/utils/hooks/useTheme';
import {useEffect, useState} from 'react';
import {useRouter} from 'next/navigation';
import {toast} from 'react-toastify';

interface Props {
  section: string;
}

interface Values {
  email: string;
  password: string;
}

async function register(values: Values, role: string) {
  const res = await fetch(
    `http://localhost:3000/api/add?email=${values.email}&password=${
      values.password
    }&role=${role.toUpperCase()}`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
    }
  );

  const json = await res.json();

  return json;
}

const SubRegisterPage: NextPage<Props> = ({section, ...rest}) => {
  //...code
  async function handleOnSubmit(values: Values) {
    const res = await register(values, role);
    if (res.data.code === 200) {
      router.push('/login');
      toast.success('Aramıza katıldın, giriş yapmayı unutma!');
    }
    if (res.data.code == 1004) {
      toast.error(res.data.message);
    }
  }
}


Solution

  • Uh, I solved the problem afterwards and after several errors (now all fixed :) ).

    The problem was related to how the concepts of Server Side Components and Client Server Components work. In Client SC, the fetch is made by client (users' browsers) therefore it directs the request to their localhost while we expect it to work on server's localhost.

    For anyone who have this issue, you have two options:

    1. You can try to create a route.ts file for each fetch request you want to make in a path/folder (e.g app/api/auth/login), then in the client server component fetch the route.ts using the path. Since route.ts is a server component, its localhost will point to the remote's ,or server's, localhost; thus, you can make a backend / an api call from localhost (e.g localhost:3006/auth/login).

    2. If you are now willing not to make first one (if you don't want to make fetch requests or if your request should be work on client as in my case to attach cookie to users's client [the cookie set to frontend from backend in server will attach the token to server's cookies, not the clients' cookies ]), then you should create another apache or nginx conf for backend and use it. However in case you want your frontend to have ssl certificate, browser will coerce you to make backend https as well. you can't use let's encrypt for backend since it only accepts one conf file (only 1 domain). Therefore i created a subdomain for my backend (api.domain.com) and then get certificate using acme.sh (let's encrypt using it so it shouldn't be problematic).