restfilenestjsbackendhttpservice

How to make backend as a bridge between external url and frontend for retrieving files?


I am trying to get a .pbf file from a map server. (but the question expands to pdf, jpg or csv) I wanna obtain that .pbf file and return it in a GET request.

The file comes from a private server: http:XXX.XXX.XXX.XXX/geometrictiles/${source.layername}/{z}/{x}/{y}.pbf

And want to return the exact same file to a get API in mi backend, like: http://localhost:3001/geometrictiles/${source.layername}/{z}/{x}/{y}.pbf

So to use my backend as a bridge between mi react app, and the geometrictiles server.

I generated and endpoint in my controller like:

` @Get('/geoserver')
  async getGeoTiles(){
    const data = await this.geomService.getPBF('layername',11,585,783);
    // const file = createReadStream(join(stringdata, 'package.json'));
    // return 
    // new StreamableFile(file);
    return stringdata;
  }`

And in my service: 
`async getPBF (layername, z, x, y){
// just using a json route in order to test any file
    return this.httpService
    //here should be this URL, but for testing reasons
    //http:XXX.XXX.XXX.XXX/geometrictiles/${source.layername}/{z}/{x}/{y}.pbf
    .get('https://api.coindesk.com/v1/bpi/currentprice.json')
    .pipe(
      map((res) => {
        // console.log('res', res);
        return res.data;
      })
    )
    .pipe(
      catchError(() => {
        throw new ForbiddenException('API not available');
      }),
    );
  }`


But this is not returning the file json, csv nor PBF as I need.

How is this is done?


Solution

  • To get file using HttpService you should inject response in getGeoTiles method and write result of HttpService GET method to it response. Also, you should write 'Content-Disposition' header to response object.
    Here's example of this logic to retreive file from specific url:

    @Controller()
    export class AppController {
      constructor(private readonly httpSerivce: HttpService) {}
    
      @Get('/geoserver')
      async getGeoTiles(@Res() response: Response) {
        const { data } = await firstValueFrom(
          this.httpSerivce
            .get<ArrayBuffer>('https://api.coindesk.com/v1/bpi/currentprice.json', {
              // get the content as ArrayBuffer
              responseType: 'arraybuffer',
            })
            .pipe(
              catchError(() => {
                throw new ForbiddenException('API not available');
              }),
            ),
        );
        response.setHeader(
          'Content-Disposition',
          // Here write filename instead of 'currentprice.json'
          `attachment; filename=${encodeURI('currentprice.json')}`,
        );
        // write content to response object
        response.write(data);
        // finalize
        response.end();
      }
    }