A api is call localhost internally it didn't triggr my backend server(express-app)

I have Next.js, Express, and MySQL running, and everything works fine with Next.js (nextjs-app) and Express (express-js), like login and signup. However, I’m having an issue with a server-side function in Next.js called checkAuth(). This function is supposed to call an Express API to verify authentication by checking the cookie token. Instead of calling the correct API, checkAuth() is incorrectly calling localhost:4000 internally. Other APIs, like login and signup, work fine. Do you know why this might be happening?

export default async function middleware(req: NextRequest) {

  // Authentication checks
  const token = await checkAuth();
  const isLoggedIn = token ? true : false;


  const publicPaths = ["/", "/signin", "/signup", "/pricing"];
  const authPaths = ["/", "/signin", "/signup"];


    if (isLoggedIn) {
      if (authPaths.includes(url.pathname)) {
        url.pathname = "/dashboard";
        return NextResponse.redirect(url);
      }
    } else {
        url.pathname = "/signin";
        return NextResponse.redirect(url);
      }
  
  }

}
"use server";
import { cookies } from "next/headers";

export const checkAuth = async (): Promise<string> => {
  try {
    const cookiestore = cookies();
    const tokenData = cookiestore.get("token");
    const token = JSON.parse(tokenData?.value as string)?.token;


    if (!token) {
      return "";
    }

    // Initial API request to check if authenticated
    let response = await fetch(`http:/localhost:4000/api/v1/auth/checkAuth`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Cookie': `token=${encodeURIComponent(token)}`, // Include token in the request header
      },
      credentials: 'include', // Ensure cookies are included in the request
      body: JSON.stringify({}), // Send an empty body
    });


    if (response.ok) {
      const data = await response.json();
      console.log("Authentication successful");
      return data as string;
    } else if (response.status === 401) {
      console.log("Token expired, attempting to refresh");
      }
    }

    console.log("Authentication failed");
    return "";
  } catch (error: any) {
    console.error("Error in checkAuth:", error);
    return "";
  }
};

docker-compose.yml

version: '3.8'

services:
  mysql:
    image: mysql:8.0
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: mydatabase
      MYSQL_USER: myuser
      MYSQL_PASSWORD: mypassword
    ports:
      - "3307:3306"
    volumes:
      - mysql-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "myuser", "-pmypassword"]
      interval: 10s
      retries: 5
      start_period: 30s
      timeout: 10s

  express-app:
    image: express-app:latest
    container_name: express-app
    ports:
      - "4000:4000"
    env_file:
      - .env-server
    depends_on:
      mysql:
        condition: service_healthy

  nextjs-app:
    image: nextjs-app:latest
    container_name: nextjs-app
    ports:
      - "3000:3000"
    env_file:
      - .env
    depends_on:
      mysql:
        condition: service_healthy
    volumes:
      - nextjs-uploads:/app/uploads

volumes:
  nextjs-uploads:
  mysql-data:

networks:
  app-network:
    driver: bridge

First, you’re using http:/ instead of http://

Second, localhost directs a container to itself, just like any other system. If you want a container to access another, use the container/service name - http://express-app:4000

If nothing beside that service is accessing the express app, you don’t need to map the ports. Same with the mysql database

And lastly, you shouldn’t have secrets such as database password in your compose file, interpolate them or use the env_file property

1 Like