23

So basically I have a server component in app dir and I want to get the pathname. I tried to do it using window.location but it does not work. Is there any way I can do this?

Updater XD
  • 261
  • 1
  • 3
  • 8
  • I don't think window exists on the serverside. Consider using the path module and dirname? – evolutionxbox Feb 06 '23 at 14:30
  • I already know that window does not exists, but thanks anyways – Updater XD Feb 06 '23 at 14:38
  • found some info on answer by @and-yet-it-compiles in documentation "Using cookies() or headers() in a Server Component will opt the whole route into dynamic rendering at request time." source: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic-rendering – artifii May 31 '23 at 08:07

4 Answers4

13

Take a look at https://github.com/vercel/next.js/issues/43704 , pauliusuza solved this issue

You can do a workaround using a middleware

import { NextResponse } from 'next/server';

export function middleware(request: Request) {

  // Store current request url in a custom header, which you can read later
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set('x-url', request.url);

  return NextResponse.next({
    request: {
      // Apply new request headers
      headers: requestHeaders,
    }
  });
}

Then use it from inside of a root layout:

import { headers } from 'next/headers';

export default function RootLayout() {
  const headersList = headers();
  // read the custom x-url header
  const header_url = headersList.get('x-url') || "";
}

Hope that helps

Björn
  • 203
  • 3
  • 8
  • 1
    One caveat here though. This will completely disable SSG for the page. More information could be found https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic-rendering. – Ankit Jain May 16 '23 at 06:07
  • 4
    In my case, I got the pathname using the `x-invoke-path` header – KBeDev May 19 '23 at 16:26
  • I get null logged for header_url – reactor Jun 12 '23 at 02:22
8

Alternatively, I think an even easier solution would be to use Next's headers already present in the request, like host or refer.

Example:

import { headers } from 'next/headers';

export default function Navbar() {
    const headersList = headers();
    const domain = headersList.get('host') || "";
    const fullUrl = headersList.get('referer') || "";

    console.log(fullUrl);
}
7

This works for me

import { headers } from "next/headers";

const headersList = headers();
const domain = headersList.get("x-forwarded-host") || "";
const protocol = headersList.get("x-forwarded-proto") || "";
const pathname = headersList.get("x-invoke-path") || "";
Amos
  • 1,154
  • 1
  • 16
  • 35
2

This finds the pathname assuming you got a referer cookie:

import { headers } from 'next/headers';

const domain = headersList.get('host') || "";
const fullUrl = headersList.get('referer') || "";
const [,pathname] = fullUrl.match( new RegExp(`https?:\/\/${domain}(.*)`))||[];

console.log(pathname);
yoty66
  • 390
  • 2
  • 12