diff --git a/src/core/intercepters/response.intercepter.ts b/src/core/intercepters/response.intercepter.ts index 4917ec1..e7310e2 100644 --- a/src/core/intercepters/response.intercepter.ts +++ b/src/core/intercepters/response.intercepter.ts @@ -16,6 +16,11 @@ export interface Response { @Injectable() export class ResponseInterceptor implements NestInterceptor> { intercept(_: ExecutionContext, next: CallHandler): Observable> { + const request = _.switchToHttp().getRequest(); + if (request.path.startsWith('/proxy')) { + return next.handle(); + } + return next.handle().pipe( map((data: T) => { return { message: 'success', data }; diff --git a/src/proxy/proxy.controller.ts b/src/proxy/proxy.controller.ts index 4f42643..6346437 100644 --- a/src/proxy/proxy.controller.ts +++ b/src/proxy/proxy.controller.ts @@ -1,7 +1,7 @@ -import { Controller, Get, Query, Response } from '@nestjs/common'; +import { Controller, Get, Param, Query, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { Response as Res } from 'express'; +import { Response } from 'express'; import { ProxyService } from 'src/proxy/proxy.service'; @@ -10,9 +10,18 @@ import { ProxyService } from 'src/proxy/proxy.service'; export class ProxyController { constructor(private readonly proxyService: ProxyService) {} + @Get(':host/:path(*)') + async getProxyImage( + @Res({ passthrough: true }) res: Response, + @Param('host') host: string, + @Param('path') path: string, + ) { + return await this.proxyService.proxyImage(host, path, res); + } + // TODO : 한정된 도메인에 대해서만 proxy 하도록 조건 추가 필요 @Get() - async getKakaoImage(@Query('url') url: string, @Response() res: Res) { + async getKakaoImage(@Query('url') url: string, @Res() res: Response) { const result = await this.proxyService.fetchKakaoImage(url); res.setHeader('Content-Type', result.contentType); diff --git a/src/proxy/proxy.service.ts b/src/proxy/proxy.service.ts index 4360b05..197d8af 100644 --- a/src/proxy/proxy.service.ts +++ b/src/proxy/proxy.service.ts @@ -1,7 +1,9 @@ import { HttpService } from '@nestjs/axios'; -import { Injectable } from '@nestjs/common'; +import { Injectable, StreamableFile } from '@nestjs/common'; +import { Response } from 'express'; import { map } from 'rxjs/operators'; +import { isReadable } from 'stream'; @Injectable() export class ProxyService { @@ -19,4 +21,24 @@ export class ProxyService { ) .toPromise(); } + + async proxyImage(host: string, path: string, res: Response) { + const { data, headers, status } = await this.httpService.axiosRef.request({ + url: `https://${host}/${path}`, + method: 'GET', + responseType: 'stream', + validateStatus: () => true, + decompress: false, + }); + + for (const key in headers) { + res.setHeader(key, headers[key]); + } + res.status(status); + if (isReadable(data)) { + return new StreamableFile(data); + } else { + throw new Error('Stream is not readable'); + } + } }