Datalytics Labs

Ever wondered why HTTP is often described as stateless but not sessionless? Let’s dive deeper into this fascinating aspect of web protocols, and this time, we’ll get our hands dirty with some code!
HTTP, the backbone of the internet, operates on a stateless model. Each connection is independent, with no memory of previous requests. Every time you send a request to the server, it’s like starting a new conversation—no knowledge of past interactions.
Now, here’s where sessions come into play. While HTTP itself is stateless, we can establish sessions to introduce a layer of continuity and security. Let’s see how this works in a Node.js environment with a simple example using Express and a hypothetical database.

const express = require('express');
const session = require('express-session');
const app = express();

// Set up session middleware
app.use(session({

secret: 'my-secret-key',
resave: false,
saveUninitialized: true
}));

// routes will be implemented from here
app.listen(3000, () => {
console.log('Server is running on port 3000');
});

In this Node.js example, we’re using the Express framework and the express-session middleware to handle sessions. When a user adds an item to their cart (a hypothetical scenario), we store that information in the session. Subsequent requests within the same session can access and modify this cart data.
Now, let’s touch on the database aspect. Consider a simplified database schema for our hypothetical e-commerce site:

CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE,
password VARCHAR(100) -- Hashed and salted, of course!
);

CREATE TABLE carts (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
item VARCHAR(50)
);

Here, we have a basic schema with users and a separate table for their shopping carts. Now, it’s time to add routes / API endpoints for our server.

// Example route to demonstrate session usage
app.get(‘/add-to-cart/:item’, (req, res) => {
if (!req.session.cart) {
req.session.cart = [];
}
const newItem = req.params.item;
req.session.cart.push(newItem);

res.send(`Item ${newItem} added to your cart. Cart contents:
${req.session.cart}`);
});

// New route to view cart
app.get(‘/view-cart’, (req, res) => {
if (!req.session.cart) {
req.session.cart = [];
}

res.send(`Your cart contains: ${req.session.cart}`);
});

Each user can have multiple items in their cart, and the session helps maintain this connection between requests. Now, you can test the session continuity by opening your browser and visiting:

  1. http://localhost:3000/add-to-cart/item1
  2. http://localhost:3000/add-to-cart/item2
  3. http://localhost:3000/view-cart

The /view-cart route should display the items “item1” and “item2” because the session maintains the cart information across multiple requests within the same session.
In essence, while HTTP requests remain stateless, the dynamic creation and management of sessions over these stateless connections, coupled with a database, add a layer of continuity and security to the communication process. Middleware components, databases, and fixed durations for session existence contribute to this intricate dance of statelessness and session management.
Let’s discuss what is going on here.
So, as we continue our journey in the world of web protocols, let’s not just talk about it – let’s code it and see the magic happen!