Pavindu
Pavindu

Reputation: 3112

Redirecting from server side in NextJS

I'm developing a Next.JS app where a user should login to see the content.I want to redirect the user to '/' if their username and password are correct.However my implementation seems not working.

I searched on SO for questions regarding this,but all of them were talking about redirecting with getInitialProps but it doesn't help me since I want to redirect user from my custom express server.

Login.js

 async handleSubmit(event) {
  event.preventDefault()
  const { username, password } = this.state

  try {
    const response = await fetch('/log_in', {
      method: 'post',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ username, password })
    })
  }

 catch (error) {
    console.log(error)
  }
}  

server.js

app.post('/log_in', (req,res) => {
    console.log(`login form data`);
    console.log(`Username : ${req.body.username}`);
    console.log(`password : ${req.body.password}`);
    if(req.body.username == "user" && req.body.password == "123"){
        res.redirect('/')
    }
}) 

Upvotes: 46

Views: 89092

Answers (5)

sanjai0py
sanjai0py

Reputation: 1

Try this.

import { NextResponse } from "next/server";

const redirects = {
  "/introduction/getting-started": "/introduction/welcome",
};

export function middleware(request) {
  const url = request.nextUrl.clone();
  const path = url.pathname;

  if (redirects[path]) {
    url.pathname = redirects[path];
    return NextResponse.redirect(url);
  }

  return NextResponse.next();
}

export const config = {
  matcher: Object.keys(redirects),
};

Docs: https://nextjs.org/docs/app/building-your-application/routing/middleware

Upvotes: -1

bsplosion
bsplosion

Reputation: 2866

App Router

You'll want to leverage a redirect function in your Server Components, Route Handlers, and Server Actions per the doc:

For instance, here's a sample for server components pulled from the docs, in a hypothetical app route of app/team/[id]/page.js, with a server-side redirect to the /login route if the team object is falsy:

import { redirect } from 'next/navigation'
 
async function fetchTeam(id) {
  const res = await fetch('https://...')
  if (!res.ok) return undefined
  return res.json()
}
 
export default async function Profile({ params }) {
  const team = await fetchTeam(params.id)
  if (!team) {
    redirect('/login')
  }
 
  // ...
}

Pages Router

This is now possible on Next.js 10+ without having to do any sort of response header manipulation directly. Use getServerSideProps or getStaticProps and return a redirect key as the only value from it if your conditions are met:

export async function getServerSideProps(context) {
  if(context.req.body.username == "user" && context.req.body.password == "123"){
    return {
      redirect: {
        permanent: false,
        destination: "/"
      }
    }
  }
}

Upvotes: 86

Dhyan TD
Dhyan TD

Reputation: 63

After the Nextjs 13, if you are using App router then @bsplosion answer doesn't work the way it used to or I can say there is a better option for server side redirecting. i.e, redirect() of next/navigation. It is explained very well here

Upvotes: 2

Svyatoslav
Svyatoslav

Reputation: 31

To those who are looking for GLOBAL server side redirects

  • The problem with getServerSideProps. It cannot be used inside _app.js file. This means we have to duplicate code for every page copying if (...) { ... return { redirect: {...} } } blocks to every private page's getServerSideProps function

In _app we need to create custom MyApp component, because getInitialProps doesn't work on _app by default as it said here

// _app.tsx
import type { AppContext, AppProps } from "next/app";
import App from 'next/app';

function MyApp({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />;
}

MyApp.getInitialProps = (appContext: AppContext) => {
  const { res, query } = appContext.ctx;
 
  // Load the page getInitiaProps
  const pageProps = App.getInitialProps(appContext);
  
  if (query.logged !== 'true') {
    // On the server, we'll use an HTTP response to
    // redirect with the status code of our choice.
    // 307 is for temporary redirects.
    res.writeHead(307, { location: `/app/login` });
    res.end();
    return {};
  }
  
  return { ...pageProps };
};

export default MyApp;

Example:

  • When I reload the page /app?logged=true, I stay on the page(or any other page with logged=true flag).
  • When I reload the page /app, I'm redirected to the login page

Ref: https://github.com/vercel/next.js/discussions/14547#discussioncomment-387271

Upvotes: 0

Richard Lindhout
Richard Lindhout

Reputation: 2068

It's a good idea for SEO to redirect server side if you can (not for login like the questions mention).

But for things like user language etc it's probably a good idea to use server side redirects like this. ----- REMOVED since it was bad code --------

Update, I ended up with this as I did have some problems with headers already sent. Please let me know how this can be fixed as it's not the most ideal (although Google does understand it according to this article https://www.seroundtable.com/google-meta-refresh-redirects-work-25335.html)

export default function HomePage({ language }) {
  return (
    <Head>
      <title>-</title>
      <meta httpEquiv="refresh" content={`0;url=/${language}/discover/0`} />
    </Head>
  );
}

Update Nextjs is adding native support there is an RFC available: https://github.com/vercel/next.js/discussions/17078

Upvotes: 6

Related Questions