Next.js Discord

Discord Forum

Issue with Axios

Answered
Scale parasitoid posted this in #help-forum
Open in Discord
Avatar
Scale parasitoidOP
Hi, in my code I have an AXIOS wrapper that adds a bunch of small features to all api requests, but when trying to build recent releases, I have been getting this error
[ API ] : Failed to add client IP header: Error: Dynamic server usage: Route / couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error
    at m (/var/www/TermedFrontend/.next/server/chunks/994.js:1:41170)
    at d (/var/www/TermedFrontend/.next/server/chunks/512.js:1:10906)
    at s.getClientIp (/var/www/TermedFrontend/.next/server/chunks/521.js:1:11295)
    at async (/var/www/TermedFrontend/.next/server/chunks/521.js:1:10951)
    at async aF.request (/var/www/TermedFrontend/.next/server/chunks/916.js:3:21146)
    at async s.get (/var/www/TermedFrontend/.next/server/chunks/521.js:1:11546)
    at async n (/var/www/TermedFrontend/.next/server/app/(normal)/page.js:2:23226)
    at async c (/var/www/TermedFrontend/.next/server/app/(normal)/page.js:2:9306) {
  description: "Route / couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error",
  digest: 'DYNAMIC_SERVER_USAGE'
}


I tried to change it to return null when not in development or server side, but the build process stops straight after. Could you help me please?
Image
Answered by B33fb0n3
alr. add this to your layout and your page.tsx:
export const dynamic = 'force-dynamic'
View full answer

49 Replies

Avatar
Scale parasitoidOP
the API is important as the backend requires it as a system to stop multiaccounting and other backend projects. I tried to inject it using middleware aswell but it didn't work.

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
    const ip = request.headers.get("x-forwarded-for") || "Unknown IP";

    const response = NextResponse.next();
    response.headers.set("X-NEXT-CLIENT-IP", ip);

    const currentUser = request.cookies.get("token")?.value;

    if (
        currentUser &&
        (request.nextUrl.pathname.startsWith("/login") ||
            request.nextUrl.pathname.startsWith("/register"))
    ) {
        return NextResponse.redirect(new URL("/dash", request.url));
    }

    if (!currentUser && request.nextUrl.pathname.startsWith("/dash")) {
        return NextResponse.redirect(
            new URL(
                `/login?redirect=${encodeURIComponent(request.nextUrl.pathname)}`,
                request.url,
            ),
        );
    }

    return response;
}

export const config = {
    matcher: ["/((?!api|_next/static|_next/image|.*\\.png$|favicon.ico).*)"],
};
Avatar
@B33fb0n3 axios is dead: https://www.adios-axios.com/ You want to use fetch. It includes everything that axios have
Avatar
Scale parasitoidOP
my main issue seems to be with getting the client IP on build, rather than the api fetch system
Avatar
@Scale parasitoid my main issue seems to be with getting the client IP on build, rather than the api fetch system
Avatar
why do you set an extra header, if you already have the ip inside your headers?
Image
Avatar
Scale parasitoidOP
wait am i stupid
one sec
Avatar
@B33fb0n3 why do you set an extra header, if you already have the ip inside your headers?
Avatar
Scale parasitoidOP
I'm pretty sure it was due to some cloudflare issues, but i'm not 100% sure I was just asked to make it
Avatar
@B33fb0n3 can you elaborate a bit more?
Avatar
Scale parasitoidOP
"so it can't be spoofed, it just adds a bit more secuiryt"
thats what the dev said
backend dev, but I also don't understand why my code doesn;'t work and at this point I wanna figure out how I could fix it just so I could fix an issue like this in the future
Avatar
@Scale parasitoid backend dev, but I also don't understand why my code doesn;'t work and at this point I wanna figure out how I could fix it just so I could fix an issue like this in the future
Avatar
When you want to find a specific error, you want to have a clean workspace. So you might also want to remove unnecessary code, that probably produces these errors. That would help us a lot πŸ‘
Also can you share your route handler?
Avatar
Scale parasitoidOP
src
 ┣ app
 ┃ ┣ (app)
 ┃ ┃ ┣ api
 ┃ ┃ ┃ ┣ setToken
 ┃ ┃ ┃ ┃ β”— route.ts
 ┃ ┃ ┃ β”— .placeholder
 ┃ ┃ ┣ [bio]
 ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ β”— ~
 ┃ ┃ ┃ ┣ (auth)
 ┃ ┃ ┃ ┃ ┣ reset
 ┃ ┃ ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ ┃ ┃ β”— verify
 ┃ ┃ ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ ┃ ┣ 404
 ┃ ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ ┃ ┣ 500
 ┃ ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ ┃ ┣ banned
 ┃ ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ ┃ ┣ test
 ┃ ┃ ┃ ┃ ┣ dev
 ┃ ┃ ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ ┃ ┣ wip
 ┃ ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ ┃ ┣ [slug]
 ┃ ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ ┃ β”— layout.tsx
 ┃ ┣ (auth)
 ┃ ┃ ┣ forgot
 ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ ┣ login
 ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ ┣ register
 ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ ┣ reset-password
 ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ ┣ verify
 ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ β”— layout.tsx
 ┃ ┣ (normal)
 ┃ ┃ ┣ layout.tsx
 ┃ ┃ β”— page.tsx
 ┃ ┣ dash
 ┃ ┃ ┣ layout.tsx
 ┃ ┃ β”— page.tsx
 ┃ ┣ error.tsx
 ┃ ┣ globals.css
 ┃ ┣ layout.tsx
 ┃ β”— not-found.tsx
 ┣ components
 ┃ ┣ auth
 ┃ ┃ ┣ forgot
 ┃ ┃ ┃ β”— forgot.tsx
 ┃ ┃ ┣ login
 ┃ ┃ ┃ β”— login.tsx
 ┃ ┃ ┣ register
 ┃ ┃ ┃ β”— register.tsx
 ┃ ┃ ┣ reset
 ┃ ┃ ┃ β”— reset.tsx
 ┃ ┃ β”— verify
 ┃ ┃ ┃ β”— verify.tsx
 ┃ ┣ dashboard
 ┃ ┃ β”— layout.tsx
 ┃ ┣ global
 ┃ ┃ ┣ admin
 ┃ ┃ β”— pages
 ┃ ┃ ┃ ┣ footer.tsx
 ┃ ┃ ┃ β”— nav.tsx
 ┃ ┣ home
 ┃ ┃ ┣ cta
 ┃ ┃ ┃ β”— cta.tsx
 ┃ ┃ ┣ features
 ┃ ┃ ┃ β”— features.tsx
 ┃ ┃ ┣ grid
 ┃ ┃ ┃ β”— grid.tsx
 ┃ ┃ β”— hero
 ┃ ┃ ┃ β”— hero.tsx
 ┃ ┣ profile
 ┃ ┃ ┣ banned
 ┃ ┃ ┃ β”— banned.tsx
 ┃ ┃ ┣ notfound
 ┃ ┃ ┃ β”— notfound.tsx
 ┃ ┃ ┣ page
 ┃ ┃ ┃ ┣ message.tsx
 ┃ ┃ ┃ β”— page.tsx
 ┃ ┃ β”— index.tsx
 ┃ ┣ storage
 ┃ ┃ ┣ api.tsx
 ┃ ┃ β”— base.tsx
 ┃ β”— ui
 ┃ ┃ ┣ button.tsx
 ┃ ┃ ┣ icons.tsx
 ┃ ┃ ┣ logo.tsx
 ┃ ┃ ┣ maraquee.tsx
 ┃ ┃ ┣ modal-video.tsx
 ┃ ┃ ┣ notification.tsx
 ┃ ┃ ┣ page-illustration.tsx
 ┃ ┃ ┣ redirect.tsx
 ┃ ┃ ┣ spotlight.tsx
 ┃ ┃ β”— tooltip.tsx
 ┣ data
 ┃ β”— redirects.ts
 ┣ lib
 ┃ ┣ Aos
 ┃ ┃ ┣ aos.css
 ┃ ┃ β”— aos.tsx
 ┃ ┣ data
 ┃ ┃ ┣ messages.ts
 ┃ ┃ β”— socials.ts
 ┃ ┣ prisma.ts
 ┃ β”— utils.ts
 ┣ modules
 ┃ ┣ Body
 ┃ ┃ ┣ Body.css
 ┃ ┃ β”— Body.tsx
 ┃ ┣ Console
 ┃ ┃ β”— Console.tsx
 ┃ ┣ Link
 ┃ ┃ β”— index.tsx
 ┃ ┣ meta.tsx
 ┃ β”— metagen.tsx
 ┣ prisma
 ┃ β”— schema.prisma
 ┣ styles
 ┃ β”— utils.css
 ┣ types
 ┃ β”— index.d.ts
 ┣ utils
 ┃ ┣ api
 ┃ ┃ ┣ debugLog.ts
 ┃ ┃ β”— getStats.ts
 ┃ ┣ server
 ┃ ┃ ┣ auth.ts
 ┃ ┃ ┣ dashboard.ts
 ┃ ┃ ┣ email.ts
 ┃ ┃ ┣ fetch.ts
 ┃ ┃ β”— profile.ts
 ┃ ┣ toasts.tsx
 ┃ ┣ uppercaseFirst.ts
 ┃ ┣ useMasonry.tsx
 ┃ β”— useMousePosition.tsx
 β”— middleware.ts
I use the APP dir
if thats what you're asking
API requests are handled on a seperate go server
Avatar
no I mean more the code of your route handler. Not the folder structure πŸ™‚
Also remove the headers that I mentioned and maybe other code that is unnecessary
I also recoded it using fetch rather than axios
Avatar
@Scale parasitoid Sorry I'm a bit stupid I don't know what you mean by route handler <:Sob:1232609083757035571>
Avatar
inside your nextjs app you can defined "route handlers". Others name them "api routes" or maybe even another term. You are using a route handler here (as you error message shows). Inside that route handler this error is thrown. So I want to take a look at the route handler (copy paste the whole file to for example pastebin or any other plattform).

More about route handlers:
https://nextjs.org/docs/app/building-your-application/routing/route-handlers
Avatar
Scale parasitoidOP
Ohhh
import type { ResponseProp } from "@/types";

/*
Copyright Β© 2024 Kars (github.com/kars1996)

Not to be shared, replicated or used without prior consent.
Contact Kars for any enquiries
*/

const Data: ResponseProp = {
    response: "Logged Out",
    status: 200,
};

export async function GET(): Promise<Response> {
    const response = new Response(JSON.stringify("Signed Out"), {
        status: 200,
    });

    response.headers.set(
        "Set-Cookie",
        "token=; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=0",
    );

    return new Response(JSON.stringify(Data), {
        status: Data.status,
        headers: {
            "Content-Type": "application/json",
        },
    });
}

I have one route handler here that isn't even really in use
"use server";
import "server-only";
import type { StatsProp } from "@/types";
import api from "../server/fetch";

export async function getStats(): Promise<StatsProp> {
    return await api.get<StatsProp>("/stats");
}
however the API wrapper is used multiple times to fetch stuff
including authentication and stuff
so I belive the issue was in prerendering everything, the code tried to create a header which isn't allowed and caused a error
Avatar
which nextjs version are you using?
Avatar
Scale parasitoidOP
15.0.3
Avatar
can you also return your created response instead of creating a new response?
Image
Avatar
@B33fb0n3 can you also return your created response instead of creating a new response?
Avatar
Scale parasitoidOP
yeah I should probably do that
done
but the route wasn't even being used
Avatar
can you share the page with the path /? It seems like you are using headers somewhere there
Avatar
@Scale parasitoid but the route wasn't even being used
Avatar
Before sharing it, can you add this to your page.tsx:
export const dynamic = 'force-dynamic'
export const dynamic = 'force-dynamic'
import CTA from "@/components/home/cta/cta";
import Features from "@/components/home/features/features";
import Grid from "@/components/home/grid/grid";
import Hero from "@/components/home/hero/hero";
import Link from "next/link";

/*
Copyright Β© 2024 Kars (github.com/kars1996)

Not to be shared, replicated or used without prior consent.
Contact Kars for any enquiries
*/
export default function IndexPage() {
    return (
        <main className="relative flex grow flex-col">
            <Hero />
            <Features />
            <Grid />
            <CTA />
        </main>
    );
}
import Footer from "@/components/global/pages/footer";
import Nav from "@/components/global/pages/nav";
import { cookies } from "next/headers";

/*
Copyright Β© 2024 Kars (github.com/kars1996)

Not to be shared, replicated or used without prior consent.
Contact Kars for any enquiries
*/

export default async function DefaultLayout({
    children,
}: {
    children: React.ReactNode;
}) {
    const cookieStore = await cookies();
    const token = cookieStore.get("token");
    return (
        <div>
            <Nav isAuth={token ? true : false} />
            {children}
            <Footer />
        </div>
    );
}
Answer
Avatar
Scale parasitoidOP
so if i just forced all of them to be dynamic it works??
😭
yeah that fixed it
thanks so much
Avatar
@Scale parasitoid so if i just forced all of them to be dynamic it works??
Avatar
well.. you are using headers. Headers are different for each client. So serving it static will result in security vulnerabilities
happy to help
much appreciated
have a nice day
Avatar
u 2