Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NestJS returning the result of an HTTP request

Tags:

In my NestJS application I want to return the result of an http call.

Following the example of the NestJS HTTP module, what I'm doing is simply:

import { Controller, HttpService, Post } from '@nestjs/common'; import { AxiosResponse } from '@nestjs/common/http/interfaces/axios.interfaces'; import { Observable } from 'rxjs/internal/Observable';  @Controller('authenticate') export class AuthController {    constructor(private readonly httpService: HttpService) {}    @Post()   authenticate(): Observable<AxiosResponse<any>> {     return this.httpService.post(...);   } } 

However from the client I'm getting 500 and the server console is saying:

TypeError: Converting circular structure to JSON at JSON.stringify () at stringify (/Users/francesco.borzi/sources/business-controller-rewrite/node_modules/express/lib/response.js:1119:12) at ServerResponse.json (/Users/francesco.borzi/sources/business-controller-rewrite/node_modules/express/lib/response.js:260:14) at ExpressAdapter.reply (/Users/francesco.borzi/sources/business-controller-rewrite/node_modules/@nestjs/core/adapters/express-adapter.js:41:52) at RouterResponseController.apply (/Users/francesco.borzi/sources/business-controller-rewrite/node_modules/@nestjs/core/router/router-response-controller.js:11:36) at at process._tickCallback (internal/process/next_tick.js:182:7)

like image 655
Francesco Borzi Avatar asked May 15 '18 17:05

Francesco Borzi


2 Answers

This issue comes from the axios library. In order to fix that, you have to pull out the data property:

return this.httpService.post(...)   .pipe(     map(response => response.data),   ); 
like image 98
Kamil Myśliwiec Avatar answered Sep 28 '22 13:09

Kamil Myśliwiec


The problem seems to stem from the fact that we are trying to return a Response object directly, and that is circular by nature. I'm not sure of the correct way to implement this, but I was able to get around it by using axios directly, unwrapping the promise and returning just the data.

@Post('login')   async authenticateUser(@Body() LoginDto) {     const params = JSON.stringify(LoginDto);      return await axios.post('https://api.example.com/authenticate_user',       params,       {         headers: {           'Content-Type': 'application/json',         },       }).then((res) => {           return res.data;     }); } 

UPDATE

I realized I could just do the same thing to the Observable being returned from the httpService using the new rxjs pipe method, so that's probably the better way to do it.

@Post('login') async authenticateUser(@Body() LoginDto) {     const params = JSON.stringify(LoginDto);      return this.httpService.post('https://api.example.com/authenticate_user',       params,       {         headers: {           'Content-Type': 'application/json',         },       }).pipe(map((res) => {     return res.data;   })); } 
like image 40
andyrue Avatar answered Sep 28 '22 13:09

andyrue