skip to Main Content

I have this controller

@Post('/login')
  async login(@Res() res: Response, @Body() body: LoginDto) {
    try {
      const user = await this.authService.login(body);
      return ResponseUtil.success(res, user, 'nice');
    } catch (error) {
      return ResponseUtil.serverError(res, error.stack);
    }
  }

I want to use res in authService without passing down res like this:

const user = await this.authService.login(res, body);

Or how can I use res in global?

2

Answers


  1. You can use dependency injection and global interceptor/middlewar to use response object from NestJS in your service without passing it down through method parameters

    Create a file response.decorator.ts

    
    import { createParamDecorator, ExecutionContext } from '@nestjs/common';
    
    export const Res = createParamDecorator(
      (data: unknown, ctx: ExecutionContext) => {
        const response = ctx.switchToHttp().getResponse();
        return response;
      },
    );
    

    Create a auth.controller.ts

    import { Controller, Post, Body, UseInterceptors } from '@nestjs/common';
    import { AuthService } from './auth.service';
    import { Res } from './response.decorator';
    import { Response } from 'express';
    import { ResponseUtil } from './response.util'; 
    @Controller('auth')
    export class AuthController {
      constructor(private readonly authService: AuthService) {}
    
      @Post('/login')
      async login(@Res() res: Response, @Body() body: LoginDto) {
        try {
          const user = await this.authService.login(body, res);
          return ResponseUtil.success(res, user, 'nice');
        } catch (error) {
          return ResponseUtil.serverError(res, error.stack);
        }
      }
    }
    

    Create a auth.service.ts

    import { Injectable, Inject } from '@nestjs/common';
    import { Response } from 'express';
    import { REQUEST } from '@nestjs/core';
    import { RequestContext } from './request.context'; // Assuming this context holds the current request
    
    @Injectable()
    export class AuthService {
      constructor(@Inject(REQUEST) private readonly requestContext: RequestContext) {}
    
      async login(body: LoginDto) {
        const res: Response = this.requestContext.getResponse();
        // Now you can use res here as you want
        if (!res) {
          throw new Error('Response object not found');
        }
        
        // here is how you can use it
        // res.status(200).json({ message: 'Success' });
    
        // Add Your login logic here
      }
    }
    
    Login or Signup to reply.
  2. To access res in authService without passing it explicitly, we can make a combination of a custom provider and middleware in NestJS.

    Create a Response Provider

    import { Injectable, Scope } from '@nestjs/common';
    import { Response } from 'express';
    
    @Injectable({ scope: Scope.REQUEST })
    export class ResponseProvider {
      private response: Response;
    
      setResponse(response: Response) {
        this.response = response;
      }
    
      getResponse(): Response {
        return this.response;
      }
    }
    

    Create Middleware to Inject Response

    import { Injectable, NestMiddleware } from '@nestjs/common';
    import { Request, Response, NextFunction } from 'express';
    import { ResponseProvider } from './response.provider'; // Adjust the import
    
    @Injectable()
    export class ResponseMiddleware implements NestMiddleware {
      constructor(private readonly responseProvider: ResponseProvider) {}
    
      use(req: Request, res: Response, next: NextFunction) {
        this.responseProvider.setResponse(res);
        next();
      }
    }
    

    Apply Middleware in Module

    import { Module, MiddlewareConsumer, NestModule, RequestMethod } from '@nestjs/common';
    import { AuthService } from './auth.service'; // Adjust the import
    import { AuthController } from './auth.controller'; // Adjust the import
    import { ResponseProvider } from './response.provider'; // Adjust the import
    import { ResponseMiddleware } from './response.middleware'; // Adjust the import
    
    @Module({
      providers: [AuthService, ResponseProvider],
      controllers: [AuthController],
    })
    export class AuthModule implements NestModule {
      configure(consumer: MiddlewareConsumer) {
        consumer
          .apply(ResponseMiddleware)
          .forRoutes({ path: '*', method: RequestMethod.ALL });
      }
    }
    

    Access Response in AuthService

    import { Injectable } from '@nestjs/common';
    import { ResponseProvider } from './response.provider'; // Adjust the import
    import { LoginDto } from './login.dto'; // Adjust the import
    
    @Injectable()
    export class AuthService {
      constructor(private readonly responseProvider: ResponseProvider) {}
    
      async login(body: LoginDto) {
        const res = this.responseProvider.getResponse();
        // Use the res object as needed
      }
    }
    

    Controller

    import { Controller, Post, Body } from '@nestjs/common';
    import { AuthService } from './auth.service'; // Adjust the import
    import { LoginDto } from './login.dto'; // Adjust the import
    import { ResponseUtil } from './response.util'; // Adjust the import
    
    @Controller('auth')
    export class AuthController {
      constructor(private readonly authService: AuthService) {}
    
      @Post('/login')
      async login(@Res() res: Response, @Body() body: LoginDto) {
        try {
          const user = await this.authService.login(body);
          return ResponseUtil.success(res, user, 'nice');
        } catch (error) {
          return ResponseUtil.serverError(res, error.stack);
        }
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search