Lesson 24-NestJS Sessions, Cookies, and HTTP

Sessions

In NestJS, session management is implemented by integrating third-party libraries such as express-session. Session management is a critical component of web development, used to track user activity and maintain user state across multiple requests.

Installing Dependencies

First, install express-session and its related dependencies.

npm install express-session

Configuring Sessions

Next, configure the session middleware in your NestJS application.

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as session from 'express-session';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Configure session middleware
  app.use(session({
    secret: 'your-secret-key',
    resave: false,
    saveUninitialized: false,
    cookie: {
      maxAge: 1000 * 60 * 60 * 24 * 7, // One week
      httpOnly: true,
      secure: false, // Set to true for HTTPS only
      sameSite: 'strict', // Or 'lax' or 'none'
    },
  }));

  await app.listen(3000);
}
bootstrap();

Using Sessions

Once the session middleware is configured, you can use req.session in controllers to read and set session data.

import { Controller, Get, Req } from '@nestjs/common';

@Controller()
export class AppController {
  @Get('/set-session')
  setSession(@Req() req) {
    req.session.views = (req.session.views || 0) + 1;
    return { views: req.session.views };
  }

  @Get('/get-session')
  getSession(@Req() req) {
    return { views: req.session.views };
  }
}

Session Storage

By default, express-session stores session data in the client’s cookie. For persistent session storage, you can use external storage services like Redis or MongoDB.

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as session from 'express-session';
import RedisStore from 'connect-redis';
import redis from 'redis';

const client = redis.createClient();

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Use Redis to store session data
  app.use(session({
    store: new RedisStore({ client }),
    secret: 'your-secret-key',
    resave: false,
    saveUninitialized: false,
    cookie: {
      maxAge: 1000 * 60 * 60 * 24 * 7, // One week
      httpOnly: true,
      secure: false, // Set to true for HTTPS only
      sameSite: 'strict', // Or 'lax' or 'none'
    },
  }));

  await app.listen(3000);
}
bootstrap();

Cookies

In NestJS, handling cookies is typically achieved by integrating third-party libraries such as express and cookie-parser. Cookies are a common technique for storing small amounts of data on the client side for use in subsequent requests.

Installing Dependencies

First, install cookie-parser.

npm install cookie-parser

Configuring Cookies

Next, configure the cookie-parser middleware in your NestJS application.

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as cookieParser from 'cookie-parser';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Configure cookie-parser middleware
  app.use(cookieParser());

  await app.listen(3000);
}
bootstrap();

Setting Cookies

Once the cookie-parser middleware is configured, you can use the res object in controllers to set cookies.

import { Controller, Get, Res } from '@nestjs/common';

@Controller()
export class AppController {
  @Get('/set-cookie')
  setCookie(@Res() res) {
    res.cookie('username', 'john_doe', { maxAge: 900000, httpOnly: true });
    res.send('Cookie has been set!');
  }
}

Reading Cookies

You can also use the req object in controllers to read cookies.

import { Controller, Get, Req } from '@nestjs/common';

@Controller()
export class AppController {
  @Get('/get-cookie')
  getCookie(@Req() req) {
    const username = req.cookies.username;
    return { username };
  }
}

Deleting Cookies

To delete a cookie, set its expiration date to a past time.

import { Controller, Get, Res } from '@nestjs/common';

@Controller()
export class AppController {
  @Get('/delete-cookie')
  deleteCookie(@Res() res) {
    res.clearCookie('username');
    res.send('Cookie has been deleted!');
  }
}

Additional Configuration Options

Cookies offer various configuration options, such as maxAge, httpOnly, secure, etc. Here are some common options:

  • maxAge: The maximum lifetime of the cookie (in milliseconds).
  • httpOnly: If set to true, the cookie cannot be accessed by JavaScript (enhances security).
  • secure: If set to true, the cookie is only sent over secure connections (HTTPS).
  • sameSite: Controls whether the cookie is sent with cross-site requests. Can be set to 'strict', 'lax', or 'none'.
import { Controller, Get, Res } from '@nestjs/common';

@Controller()
export class AppController {
  @Get('/set-cookie')
  setCookie(@Res() res) {
    res.cookie('username', 'john_doe', {
      maxAge: 900000,
      httpOnly: true,
      secure: true, // Should be true in production
      sameSite: 'strict',
    });
    res.send('Cookie has been set!');
  }
}

HTTP Module

In NestJS, the HTTP module (@nestjs/axios) provides a convenient way to make HTTP requests. This is commonly used to fetch data from external services or interact with other microservices.

Installing Dependencies

First, install @nestjs/axios.

npm install --save @nestjs/axios

Importing the HTTP Module

Next, import the HttpModule in your module file.

import { Module } from '@nestjs/common';
import { HttpModule } from '@nestjs/axios';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Module({
  imports: [HttpModule],
  controllers: [CatsController],
  providers: [CatsService],
})
export class CatsModule {}

Using HttpService

Inject the HttpService into a service and use it to make HTTP requests.

import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';

@Injectable()
export class CatsService {
  constructor(private readonly httpService: HttpService) {}

  async fetchCats(): Promise<any> {
    const { data } = await this.httpService.get('https://api.example.com/cats').toPromise();
    return data;
  }
}

Calling the Service in a Controller

Call the service method in a controller to fetch data and return it to the client.

import { Controller, Get } from '@nestjs/common';
import { CatsService } from './cats.service';

@Controller('cats')
export class CatsController {
  constructor(private readonly catsService: CatsService) {}

  @Get()
  async getCats() {
    return await this.catsService.fetchCats();
  }
}

Additional Configuration Options

@nestjs/axios provides various configuration options to customize HTTP request behavior, such as setting timeouts or adding default headers.

import { Module } from '@nestjs/common';
import { HttpModule } from '@nestjs/axios';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Module({
  imports: [
    HttpModule.register({
      timeout: 5000,
      maxRedirects: 5,
    }),
  ],
  controllers: [CatsController],
  providers: [CatsService],
})
export class CatsModule {}

Error Handling

When making HTTP requests, you may need to handle errors. This can be achieved by catching exceptions.

import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';

@Injectable()
export class CatsService {
  constructor(private readonly httpService: HttpService) {}

  async fetchCats(): Promise<any> {
    try {
      const { data } = await this.httpService.get('https://api.example.com/cats').toPromise();
      return data;
    } catch (error) {
      console.error('Error fetching cats:', error);
      throw new Error('Failed to fetch cats');
    }
  }
}
Share your love