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)
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), );
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; })); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With