LoginSignup
s_kajigo
@s_kajigo (kaji shogo)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

SPA構成の通信がステートレスかどうかがわからない

現在Rails apiとreactでのポートフォリオ作成に取り組んでいます。
ログイン機能を、railsのdevise,devise_token_authを使用してcookieにaccess-tokenが保存される形で実装しました。
react側では、cookieに保存されたtoken情報をリクエストヘッダーとして投げることでユーザーを判別し、ユーザーが存在すればstateを更新してログイン状態にしたり、個別のユーザーデータを操作できるようにしています。

今回わからないことは、
このアプリケーションがステートフルなのか、ステートレスなのかです。
自分で調べた結果、ログインリクエストが成功すると、cookieにアクセストークンが保存される通信の結果が保存されるという意味で、ステートフルではないかと考えているのですが確信が持てません。

実装したコード

auth.js
import { client } from "./client";
import Cookies from "js-cookie";

// サインアップ
export const signUp = (params) => {
 return client.post("/auth", params);
};

// サインイン
export const signIn = (params) => {
 return client.post("/auth/sign_in", params);
};

// サインアウト
export const signOut = () => {
 return client.delete("/auth/sign_out", {
  headers: {
   "access-token": Cookies.get("_access_token"),
   client: Cookies.get("_client"),
   uid: Cookies.get("_uid"),
  },
 });
};

// Cookieに必要なデータセットがあるかを確認。揃っていればrailsに投げてcurrentUserがいるかを検索。
export const getCurrentUser = () => {
 if (
  !Cookies.get("_access_token") ||
  !Cookies.get("_client") ||
  !Cookies.get("_uid")
 )
  return console.log("ログイン中のユーザーはいません。");
 return (
  client.get("/auth/sessions", {
   headers: {
    "access-token": Cookies.get("_access_token"),
    "client": Cookies.get("_client"),
    "uid": Cookies.get("_uid"),
   },
  })
 )
};
App.js
import { createContext, useEffect, useState } from "react";
import { BrowserRouter, Switch, Route, Redirect } from "react-router-dom";
import { getCurrentUser } from "./api/auth";
import { Home } from "./components/Home";
import { SignIn } from "./components/SignIn";
import { SignUp } from "./components/SignUp";
import { Top } from "./components/Top";

export const AuthContext = createContext();

function App() {
  const [loading, setLoading] = useState(true);
  const [isSignedIn, setIsSignedIn] = useState(false);
  const [currentUser, setCurrentUser] = useState();

  // Cookieからログイン中ユーザーを取得、結果をハンドリング
  const handleGetCurrentUser = async () => {
    try {
      const res = await getCurrentUser();
      if (res?.status === 200) {
        setIsSignedIn(true);
        setCurrentUser(res?.data.currentUser);
        console.log(res?.data.currentUser);
      } else {
        console.log("no current user");
      }
    } catch (e) {
      console.log(e);
    }
    setLoading(false);
  };

  useEffect(() => {
    handleGetCurrentUser();
  }, [setCurrentUser]);

  const Private = ({ children }) => {
    if (!loading) {
      if (isSignedIn) {
        return children;
      } else {
        return <Redirect to="/signin" />;
      }
    } else {
      return <></>;
    }
  };
  return (
    <AuthContext.Provider
      value={{
        loading,
        setLoading,
        isSignedIn,
        setIsSignedIn,
        currentUser,
        setCurrentUser,
      }}
    >
      <BrowserRouter>
        <Switch>
          <Route exact path="/top">
            <Top />
          </Route>
          <Route exact path="/signin">
            <SignIn />
          </Route>
          <Private>
            <Route exact path="/">
              <Home />
            </Route>
          </Private>
        </Switch>
      </BrowserRouter>
    </AuthContext.Provider>
  );
}

export default App;

api

session_controller.rb
class Api::V1::Auth::SessionsController < ApplicationController

 def index
     if current_api_v1_user
         render json: {status:200, current_user: current_api_v1_user }
     else
         render json: {status: 500, message: "ユーザーが存在しません"}
     end
 end
end

的をいない記載があるかと思いますが、ご教授いただけたら幸いです。

0

1Answer

http/1.0は完璧にステートレスでした。この時期にセッション管理の考えが登場してます。今の1.1はkeep-aliveなどの要求でステートフルの努力はされるものの以前ステートレスです。何故ならサーバー側はtcpセッション数を節約して多くの方にサービスを使ってもらいたいからです。
 さて、httpsはtcp上はステートフルですが、アプリ層ではステートレスです。そのため、cookieやフィンガープリントを用いて疑似的にステートフルにする技術がセッション管理です。
 尚、http拡張のwebSocket(ws://、wss://)は完全にステートフルです。cockpit zabbixのグラフ表示がリアルタイムで更新される奴です。

1

Comments

  1. @s_kajigo

    Questioner
    回答ありがとうございます。大変わかりやすい記事でした。
    今回はCookieを使用しているためフロントとバックエンドで擬似的なステートフル通信を行なっているということですね。
    まだまだ知識が浅いので、100%回答を理解できたわけではないので、さらに学習した上で改めて今回いただいた回答を理解できるようにさせていただきます。

Your answer might help someone💌