J.Doe
J.Doe

Reputation: 81

NestJs : How to implement node.js Post and Get logic in NestJs

I'm trying to implement node.js Spotify Authorization flow in NestJs.

But HttpService Post and Get functions doesn't work as in node.js.

Node.js working example:

var request = require('request'); // "Request" library

app.get('/callback', function(req, res) {
    var authOptions = {
      url: 'https://some-url.com/api/token',
      form: {
        code: code,
        redirect_uri: redirect_uri,
        grant_type: 'authorization_code'
      },
      headers: {
        'Authorization': 'Basic ' + (Buffer.from(client_id + ':' + client_secret).toString('base64'))
      },
      json: true
    };

    // I'm trying to implement this post in NestJS
    request.post(authOptions, function(error, response, body) {
        var options = {
          url: 'https://api.spotify.com/v1/me',
          headers: { 'Authorization': 'Bearer ' + access_token },
          json: true
        };

        request.get(options, function(error, response, body) {
          console.log(body);
        });

}

I'm using HttpService Post method in NestJS and that doesn't work:

constructor(private httpService: HttpService) {}

@Get('callback')
callback(@Request() req, @Res() res): any {
  let code = req.query.code || null;
  const url = 'https://some-url.com/api/token';
  const form = {
    code: code,
    redirect_uri: this.redirect_uri,
    grant_type: 'authorization_code'
  }
  const headers = {
    'Authorization': 'Basic ' + (Buffer.from(this.client_id + ':' + this.client_secret))
  }

  // doesn't work
  this.httpService.post( url, form, { headers: headers }).pipe(
    map((response) => {
      console.log(response);
    }),
  );
}

Upvotes: 0

Views: 2229

Answers (4)

eliastg
eliastg

Reputation: 589

Add this imports to the controller:

import { Observable } from 'rxjs';
import { take, tap, map } from 'rxjs/operators';

Then try this:

constructor(private httpService: HttpService) {}

@Get('callback')
callback(@Request() req, @Res() res): Observable<any> {
  let code = req.query.code || null;
  const url = 'https://some-url.com/api/token';
  const form = {
    code: code,
    redirect_uri: this.redirect_uri,
    grant_type: 'authorization_code'
  }
  const headers = {
    'Authorization': 'Basic ' + (Buffer.from(this.client_id + ':' + 
    this.client_secret))
  }

  return this.httpService.post( url, form, { headers: headers }).pipe(
    // Take first result to complete the observable..
    take(1),
    
    // [OPTIONAL] Some debug log to see the response.
    tap((response: { data: any }) => {
       console.log(`Response: ${JSON.stringify(response.data)}`);
    })

    // Map the response object to just return its data. 
    map((response: { data: any }) => response.data),
  );
}

Upvotes: 0

Roomey Rahman
Roomey Rahman

Reputation: 331

In NestJS, you do not need to send req, res object to your function parameter. Nest Js provide build-in decorator for req.body, req.query and req.param as @Body, @Query, and @Param. I write down to call post method and get method. You can also use put, patch, delete, and other methods. Please make a data transfer object file in your module.

for further reference, you can check this: https://docs.nestjs.com/controllers

export class yourController {
    constructor(private readonly httpService: HttpService) {}

    @Post('your-route-name')
    public postMethod(@Body() yourDTO: YourDTOClass): Promise<interface> {
        try {
            return this.httpService.method(yourDTO);
        } catch (err) {
            throw new HttpException(err, err.status || HttpStatus.BAD_REQUEST);
        }
    }

    @Get('your-route-name')
    find(@Query() query: QueryDTO): Promise<interface> {
        try {
            return this.httpService.methodName(query);
        } catch (err) {
            throw new HttpException(err, err.status || HttpStatus.BAD_REQUEST);
        }
    }
}

Upvotes: 2

Willian
Willian

Reputation: 3405

You should prefix your controller with "async" and use "await" followed by "toPromise()"...

constructor(private httpService: HttpService) {}

@Get('callback')
async callback(@Request() req, @Res() res): any {
  // ... remaining code here

  const response = 
    await this.httpService.post(url, form, { headers: headers }).toPromise();
  return response;
}

Upvotes: 0

Linh
Linh

Reputation: 468

You should put return before this.httpService.post(...). Normally you would have to subscribe to the Observable returned by the post method but NestJS handles this for you through the @Get() decorator.

Upvotes: 0

Related Questions