0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ログインページにリダイレクトしたい

Posted at

この記事について

Next.jsで、ログイン必須のページにアクセスされたとき、ログインしていなければ強制的にログインページにリダイレクトする仕組みを紹介する。

準備

  • Nextプロジェクトのルートディレクトリにpluginファルダを作成し、その中にaxios.tsファイルを作成する
  • npm install axiosまたはyarn add axios等でaxiosをインストールする

実装

plugin/axios.ts
import axios from "axios";

const axios_instance = axios.create({
    headers:{
        "Content-Type": "application/json",
    },
});

axios_instance.interceptors.request.use(

    function(config){

        return config;
    },

    function (error){

        return Promise.reject(error);
    }
);

axios_instance.interceptors.response.use(

    function (response){

        return response;
    },

    function (error){

        const originalConfig = error.config;
        if(
            error.response &&
            error.response.status === 401 &&
            !originalConfig.retry
        ){
            //認証エラーならリトライ
            originalConfig.retry = true;

            //以下の場合はリトライしない
            if(originalConfig.url === "ログインAPIへのパス"){

                return Promise.reject(error);
            }
            
            axios_instance
            .post("リトライAPIへのパス", {refresh:""})
            .then((response) => {
                return axios_instance(originalConfig);
            })
            .catch(function(error){
                return Promise.reject(error);
            });
        }
        else if(error.response && error.response.status !== 422){

            window.location.href = "ログインAPIへのパス";
        }
        else{
            
            return Promise.reject(error);
        }
    }
);

export default axios_instance;

解説

axiosインスタンスの作成

共通ヘッダーの設定
const axios_instance = axios.create({
    headers:{
        "Content-Type": "application/json",
    },
});

Content-Type が "application/json" に設定された axios インスタンスを作成している。
これにより、送信されるリクエストはすべて JSON 形式でデータを扱うことが前提となる。

インターセプタ

リクエストインターセプタ
axios_instance.interceptors.request.use(

    function(config){

        return config;
    },

    function (error){

        return Promise.reject(error);
    }
);

リクエストが送信される前にインターセプターが実行され、渡されたconfig(リクエストの設定情報)をそのまま返す。また、エラーが発生した場合は、単にPromise.reject(error)でエラーを返す。

レスポンスインターセプタ
axios_instance.interceptors.response.use(

    function (response){

        return response;
    },

    function (error){

        const originalConfig = error.config;
        if(
            error.response &&
            error.response.status === 401 &&
            !originalConfig.retry
        ){
            //認証エラーならリトライ
            originalConfig.retry = true;

            //以下の場合はリトライしない
            if(originalConfig.url === "ログインAPIへのパス"){

                return Promise.reject(error);
            }
            
            axios_instance
            .post("リトライAPIへのパス", {refresh:""})
            .then((response) => {
                return axios_instance(originalConfig);
            })
            .catch(function(error){
                return Promise.reject(error);
            });
        }
        else if(error.response && error.response.status !== 422){

            window.location.href = "ログインAPIへのパス";
        }
        else{
            
            return Promise.reject(error);
        }
    }
);

レスポンスが正常に返ってきた場合は、レスポンスそのものをそのまま返すが、エラー時には以下のように処理される

  • 認証エラー(401)の場合:

    エラーが401(Unauthorized)で、かつリトライがまだ行われていない場合(originalConfig.retry が false の場合)に処理が進む。
    ログインAPIのエンドポイントに対してPOSTリクエストを送信して認証情報のリフレッシュ、成功した場合は元のリクエスト(originalConfig)を再実行する。
    ただし、リクエスト先がログインAPIへのパスの場合は、ログイン自体のエラーと判断しリトライは行わない。

originalConfig.retry を true に設定し、同じリクエストの二重リトライを防止。

  • 422エラーの場合:

    422エラーは特定のバリデーションエラーや処理上のエラーと判断され、そのままエラーを返す。
     

  • その他のエラー(422以外)の場合:

    エラーステータスが422以外であれば、ユーザーをログインページにリダイレクトする。これは、認証が失敗している場合など、再ログインが必要と判断された場合の処理。

使い方

axiosをインポートする際に、import axios from "@/plugin/axios";としてインポートする。

以降は普通のaxiosと同じようにリクエストを扱える

この場合、バックエンドへのリクエストはaxiosで行い、Next.js内への通信はfetchで行うなどの戦略が考えられる

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?