DEV Community

Navin Yadav
Navin Yadav

Posted on

StateFul and StateLess System

Stateful vs stateless

In this Post we will understand stateful as well as stateless system write some code and understand thieir benefit

Here is the repo for both stateful and stateless code
auth repo

Theory

1. StateFul System.
stateful system remember past interaction by storing state across all request.server store state

Advantage.
Simple Client Logic

Disadvantage
Hard to scale
Server must manage session

2. StateLess System
stateLess system treat each request completely independent.It doesn't know anythin about previous interaction. user need to send info by tokens.tokens are store from client side eg. inside cookies

Advantage.
High Scalability
Fault tolerance

Disadvantage
Repeated data sent every time.

practical
In this practical section we are going to use express,mongoose for our practical

First of all initialize npm then add package
express - for creating server
nodemon - for restarting server everytime any file changes
mongodb - for connection to mongodb
moongoose - for creating schema
dotenv - loading env variables
bcrypt - so that we can hash user password

create folder:- models controllers routes

npm i express nodemon mongodb mongoose dotenv bcrypt
Enter fullscreen mode Exit fullscreen mode

create db.js

const mongoose = require('mongoose')

const connectDB = async () => {
  try {
    await mongoose.connect(process.env.MONGODB_URI)
    console.log('mongodb connected');
  } catch (error) {
    console.log('mongodb connection error ', error);
    process.exit(1)
  }
}
module.exports = connectDB;
Enter fullscreen mode Exit fullscreen mode

create index.js and start express server and also add db connection

stateful example

const express = require('express')
const session = require('express-session')
const authRouter = require('./routes/user.route');
const connectDB = require('./db.index');
const app = express();
const PORT = 8080;
const dotenv = require('dotenv')
dotenv.config()
app.use(express.json())

app.get('/', (req, res) => {
  res.send('ok')
})
//we created a session for stateful system
app.use(session({
  secret: "Navin45",
  resave: false,
  saveUninitialized: false
}))
app.use('/auth', authRouter)

app.listen(PORT, async () => {
  await connectDB()
  console.log(`server is listening http://localhost:${PORT}`)
})
Enter fullscreen mode Exit fullscreen mode

In this we create 4 fuction but the import part is we attach userId session after verify it's email and password and by using this we can get user state when ever we need.

 req.session.userId = user._id;
Enter fullscreen mode Exit fullscreen mode
const User = require('../models/user.model.js')

const register = async (req, res) => {
  try {
    const { name, email, password } = req.body;
    const user = await User.create({ name, email, password })
    return res.status(201).json(user)
  } catch (error) {
    console.log(error);
  }
}
const login = async (req, res) => {
  try {
    const { email, password } = req.body;
    if (!email || !password) {
      return res.status(400).json({ mess: "Please enter all fields" })
    }
    const user = await User.findOne({ email });
    if (!user) {
      return res.status(404).json({ mess: "Invalid crediatels " })
    }

    const isValidPassword = await user.isPasswordCorrect(password)
    if (!isValidPassword) {
      return res.status(404).json({ mess: "Invalid crediatels " })
    }
    // 🛑STATEFULL PART
    req.session.userId = user._id;
    return res.status(200).json({ mess: "Login successfully " })
  } catch (error) {
    console.log(error);
    return res.status(500).json({ mess: "Internal server errror" })
  }
}
const logout = (req, res) => {
  try {
    req.session.destroy(() => {
      res.json({ mess: "logout successfully" })
    })
  } catch (error) {
    return res.status(500).json({ mess: "Internal server error" })
  }
}
const dashboard = async (req, res) => {
  if (!req.session.userId) {
    return res.status(401).json({ mess: "Not logged in" })
  }
  return res.status(200).json({
    mess: "Welcome to dashboard",
    userId: req.session.userId
  })
}
module.exports = {
  register,
  login,
  logout,
  dashboard
}
Enter fullscreen mode Exit fullscreen mode

stateless example
we uses jsonwebtoken package for maintaining stateless state
jwt contain 3 part header payload signature

npm i jsonwebtoken
Enter fullscreen mode Exit fullscreen mode
const User = require('../models/user.model')

const jwt = require('jsonwebtoken')

const JWT_SECREAT = "navin5500";

const reqister = async (req, res) => {
  try {
    const { name, email, password } = req.body;

    if (!email || !password) {
      return res.status(400).json({ mess: "please enter details" })
    }
    const isUserExists = await User.findOne({ email })
    if (isUserExists) {
      return res.status(405).json({ message: "User with this email already exists " })
    }
    const user = await User.create({ name, email, password })

    return res.status(200).json({ message: "Use register successfully " })

  } catch (error) {
    console.log(error)
    return res.status(500).json({ mess: "internal server error" })

  }
}
const login = async (req, res) => {
  try {
    const { email, password } = req.body;
    if (!email || !password) {
      return res.status(400).json({ mess: "Please enter all fields" })
    }
    const user = await User.findOne({ email });
    if (!user) {
      return res.status(404).json({ mess: "Invalid crediatels " })
    }

    const isValidPassword = await user.isPasswordCorrect(password)
    if (!isValidPassword) {
      return res.status(404).json({ mess: "Invalid crediatels " })
    }

    // 🛑STATELESS PART
    const token = jwt.sign(
      { userId: user._id },
      JWT_SECREAT,
      { expiresIn: "1h" }
    )
    return res.status(200).json({ mess: "Login successfully ", token })
  } catch (error) {
    console.log(error);
    return res.status(500).json({ mess: "Internal server errror" })
  }
}

const dashboard = async (req, res) => {
  try {
    return res.status(200).json({ mess: "Welcome to dashboard", userId: req.userId })
  } catch (error) {
    return res.status(500).json({ mess: "Internal server error", })

  }
}

module.exports = {
  reqister,
  login,
  dashboard,
}
Enter fullscreen mode Exit fullscreen mode

This is a middleware any request will try access any imp data first will grow through this if validate then go next else it will return from here only and we also attact userId on request so that we can get user info whenver we need

const jwt = require('jsonwebtoken')
const JWT_SECREAT = "navin5500";

const checkHeader = (req, res, next) => {
  const authHeader = req.headers.authorization;

  if (!authHeader) {
    return res.status(401).json({ message: "No token provided" });
  }
  const token = authHeader.split(" ")[1];

  try {
    const decoded = jwt.verify(token, JWT_SECREAT)
    req.userId = decoded.userId;
    next()
  } catch (error) {
    return res.status(401).json({ message: "Invalid token" });
  }
}

module.exports = { checkHeader }
Enter fullscreen mode Exit fullscreen mode

Top comments (0)